diff options
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | get_stack_limit.c | 26 | ||||
-rw-r--r-- | get_stack_space.c | 5 | ||||
-rw-r--r-- | libsimple/random.h | 103 | ||||
-rw-r--r-- | libsimple/stack.h | 50 | ||||
-rw-r--r-- | random_bits.c | 6 | ||||
-rw-r--r-- | random_bytes.c | 41 |
8 files changed, 208 insertions, 28 deletions
@@ -1,6 +1,6 @@ ISC License -© 2017, 2018, 2021, 2022, 2023, 2024 Mattias Andrée <maandree@kth.se> +© 2017, 2018, 2021, 2022, 2023, 2024 Mattias Andrée <m@maandree.se> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -11,7 +11,7 @@ include mk/$(OS).mk LIB_MAJOR = 1 -LIB_MINOR = 7 +LIB_MINOR = 8 LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) LIB_NAME = simple @@ -941,6 +941,7 @@ OBJ =\ qsort_ushortp.o\ qsort_ushortp_nul.o\ random_bits.o\ + random_bytes.o\ random_float.o\ random_signed.o\ random_unsigned.o\ diff --git a/get_stack_limit.c b/get_stack_limit.c index 363147a..cb19f2d 100644 --- a/get_stack_limit.c +++ b/get_stack_limit.c @@ -12,7 +12,7 @@ libsimple_get_stack_limit(size_t *restrict soft, size_t *restrict hard) size_t off = 0; size_t lineoff, linelen; - fd = open("/proc/self/limits", O_RDONLY); + fd = open("/proc/thread-self/limits", O_RDONLY); if (fd < 0) return -1; @@ -41,22 +41,30 @@ libsimple_get_stack_limit(size_t *restrict soft, size_t *restrict hard) if (!strcmp(line, "Max stack size ")) goto line_found; } - } - + line_found: close(fd); line = &line[sizeof("Max stack size ") - 1U]; - while (*line == ' ') + while (*line == ' ' || *line == '\t') line++; - if (soft) - *soft = (size_t)strtoull(line, NULL, 10); + if (soft) { + *soft = SIZE_MAX; + if (isdigit(*line)) + *soft = (size_t)strtoull(line, NULL, 10); + } - while (*line == ' ') + while (*line != ' ' && *line != '\t' && *line && *line != '\n') line++; - if (hard) - *hard = (size_t)strtoull(line, NULL, 10); + + while (*line == ' ' || *line == '\t') + line++; + if (hard) { + *hard = SIZE_MAX; + if (isdigit(*line)) + *hard = (size_t)strtoull(line, NULL, 10); + } return 0; } diff --git a/get_stack_space.c b/get_stack_space.c index 7f1fdd3..bb0d92b 100644 --- a/get_stack_space.c +++ b/get_stack_space.c @@ -12,7 +12,7 @@ libsimple_get_stack_space(uintptr_t *restrict low, uintptr_t *restrict high) size_t off = 0; size_t lineoff, linelen; - fd = open("/proc/self/maps", O_RDONLY); + fd = open("/proc/thread-self/maps", O_RDONLY); if (fd < 0) return -1; @@ -41,9 +41,8 @@ libsimple_get_stack_space(uintptr_t *restrict low, uintptr_t *restrict high) if (!strcmp(&line[linelen - (sizeof(" [stack]\n") - 1U)], " [stack]\n")) goto line_found; } - } - + line_found: close(fd); diff --git a/libsimple/random.h b/libsimple/random.h index 29e3bbf..d3cc008 100644 --- a/libsimple/random.h +++ b/libsimple/random.h @@ -9,8 +9,7 @@ * @since 1.6 */ LIBSIMPLE_GCC_ONLY__(__attribute__((__warn_unused_result__))) -unsigned int libsimple_generate_seed(void); /* TODO add man page */ - +unsigned int libsimple_generate_seed(void); /* TODO man */ /** * Wrapper for srand(3) that creates a pseudo-random @@ -20,14 +19,102 @@ unsigned int libsimple_generate_seed(void); /* TODO add man page */ * @since 1.6 */ inline void -libsimple_srand(void) /* TODO add man page */ +libsimple_srand(void) /* TODO man */ { srand(libsimple_generate_seed()); } +/** + * Generate a set of uniformly random bits + * + * @param bits The number of bits to generate + * @param unused This parameter is unused, but is provided so that + * the function has a prototype that is compatible + * with alternative functions that need an extra + * argument to make it reenterent + * @return An integer with it's lowest `bits` bits independently + * randomly set, each bit has a 50 % chance of being + * cleared and 50 a % chance of being set, any excess + * bit will be cleared + * + * @since 1.6 + */ +uintmax_t libsimple_random_bits(size_t bits, void *unused); /* TODO man */ -/* TODO doc, man (since 1.6) (libsimple_random_float requires -lm) */ -uintmax_t libsimple_random_bits(size_t bits, void *unused); -uintmax_t libsimple_random_unsigned(uintmax_t (*rng)(size_t bits, void *user), void *user, uintmax_t min, uintmax_t max); -intmax_t libsimple_random_signed(uintmax_t (*rng)(size_t bits, void *user), void *user, intmax_t min, intmax_t max); -long double libsimple_random_float(uintmax_t (*rng)(size_t bits, void *user), void *user, long double min, long double postmax); +/** + * Generate a uniformally random, unsigned integer with [`min`, `max`] + * + * @param rng Random bit generating function, `libsimple_random_bits` + * can be used, if any other function is used, it must + * have the same specification: the first argument is + * the number of bits to generate, the second argument + * will be `user` and is either unused or defined by the + * function, and the returned value shall have it's `bits` + * lowest bits randomly set and all other bits cleared + * @param user Pass into `*rng` as it's second argument + * @param min The lower, inclusive, boundary for the random value + * @param max The upper, inclusive, boundary for the random value + * @return A uniformally random, unsigned integer within [`min`, `max`] + * + * @since 1.6 + */ +uintmax_t libsimple_random_unsigned(uintmax_t (*rng)(size_t bits, void *user), void *user, uintmax_t min, uintmax_t max); /* TODO man */ + +/** + * Generate a uniformally random, signed integer with [`min`, `max`] + * + * @param rng Random bit generating function, `libsimple_random_bits` + * can be used, if any other function is used, it must + * have the same specification: the first argument is + * the number of bits to generate, the second argument + * will be `user` and is either unused or defined by the + * function, and the returned value shall have it's `bits` + * lowest bits randomly set and all other bits cleared + * @param user Pass into `*rng` as it's second argument + * @param min The lower, inclusive, boundary for the random value + * @param max The upper, inclusive, boundary for the random value + * @return A uniformally random, signed integer within [`min`, `max`] + * + * @since 1.6 + */ +intmax_t libsimple_random_signed(uintmax_t (*rng)(size_t bits, void *user), void *user, intmax_t min, intmax_t max); /* TODO man */ + +/** + * Generate a uniformally random, real number with [`min`, `postmax`) + * + * @param rng Random bit generating function, `libsimple_random_bits` + * can be used, if any other function is used, it must + * have the same specification: the first argument is + * the number of bits to generate, the second argument + * will be `user` and is either unused or defined by the + * function, and the returned value shall have it's `bits` + * lowest bits randomly set and all other bits cleared + * @param user Pass into `*rng` as it's second argument + * @param min The lower, inclusive, boundary for the random value + * @param max The upper, exclusive, boundary for the random value + * @return A uniformally random, real number within [`min`, `postmax`) + * + * @linkwith -lm + * + * @since 1.6 + */ +long double libsimple_random_float(uintmax_t (*rng)(size_t bits, void *user), void *user, long double min, long double postmax); /* TODO man */ + +/** + * Generate a set uniformally random bytes + * + * @param rng Random bit generating function, `libsimple_random_bits` + * can be used, if any other function is used, it must + * have the same specification: the first argument is + * the number of bits to generate, the second argument + * will be `user` and is either unused or defined by the + * function, and the returned value shall have it's `bits` + * lowest bits randomly set and all other bits cleared + * @param user Pass into `*rng` as it's second argument + * @param buffer Output buffer for the random bytes + * @param bytes The number of bytes to generate + * @return The end of `buffer` + * + * @since 1.7 + */ +void *libsimple_random_bytes(uintmax_t (*rng)(size_t bits, void *user), void *user, void *buffer, size_t bytes); /* TODO man */ diff --git a/libsimple/stack.h b/libsimple/stack.h index a7b1294..bb082f6 100644 --- a/libsimple/stack.h +++ b/libsimple/stack.h @@ -1,11 +1,53 @@ /* See LICENSE file for copyright and license details. */ -int libsimple_get_stack_space(uintptr_t *restrict, uintptr_t *restrict); /* TODO man, doc (since 1.7) */ -int libsimple_get_stack_limit(size_t *restrict, size_t *restrict); /* TODO man, doc (since 1.7) */ -int libsimple_get_stack_direction(void); /* TODO man, doc (since 1.7) */ +/** + * Get area of the the thread's stack space + * + * @param low Output parameter for the address of the beginning of the stack space + * @param high Output parameter for the address immediately after the last byte in the stack space + * @return 0 on success, -1 on failure + * + * @since 1.7 + */ +LIBSIMPLE_GCC_ONLY__(__attribute__((__nonnull__))) +int libsimple_get_stack_space(uintptr_t *restrict low, uintptr_t *restrict high); /* TODO man */ -int libsimple_needstack(size_t); /* TODO man, doc (since 1.7) */ +/** + * Get the stack size limit for the thread + * + * @param soft Output parameter for the soft limit, or `NULL` + * @param hard Output parameter for the hard limit, or `NULL` + * @return 0 on success, -1 on failure + * + * @since 1.7 + */ +int libsimple_get_stack_limit(size_t *restrict soft, size_t *restrict hard); /* TODO man */ + +/** + * Get the direction the stack grows in + * + * @return +1 if the stack grows upwards (higher addresses), + * -1 if the stack grows downwards (lower addresses), + * 0 on failure + * + * @throws ENOTSUP Unable to determine stack growth direction + * + * @since 1.7 + */ +int libsimple_get_stack_direction(void); /* TODO man */ + +/** + * Check if the some amount of memory can be allowed on the stack + * + * @param n The amount of memory + * @return 1 if `n` bytes can be allocated, + * 0 if `n` bytes may or may not be allocated, + * -1 on failure + * + * @since 1.7 + */ +int libsimple_needstack(size_t n); /* TODO man */ #ifndef needstack # define needstack libsimple_needstack #endif diff --git a/random_bits.c b/random_bits.c index 528b09e..a6d95a2 100644 --- a/random_bits.c +++ b/random_bits.c @@ -14,8 +14,10 @@ libsimple_random_bits(size_t bits, void *unused) bits -= 8; } - ret <<= bits; - ret |= (uintmax_t)(rand() & ((1 << bits) - 1)); + if (bits) { + ret <<= bits; + ret |= (uintmax_t)(rand() & ((1 << bits) - 1)); + } (void) unused; return ret; diff --git a/random_bytes.c b/random_bytes.c new file mode 100644 index 0000000..723fc63 --- /dev/null +++ b/random_bytes.c @@ -0,0 +1,41 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +void * +libsimple_random_bytes(uintmax_t (*rng)(size_t bits, void *user), void *user, void *buffer, size_t bytes) +{ + char *buf = buffer; + uintmax_t rnd; + + while (bytes >= sizeof(uintmax_t)) { + rnd = (*rng)(sizeof(uintmax_t) * 8U, user); + memcpy(buf, &rnd, sizeof(uintmax_t)); + bytes -= sizeof(uintmax_t); + buf = &buf[sizeof(uintmax_t)]; + } + + if (bytes) { + rnd = (*rng)(bytes * 8U, user); + while (bytes) { + *buf++ = (char)(rnd & 255U); + bytes--; + rnd >>= 8; + } + } + + return buf; +} + + +#else +#include "test.h" + +int +main(void) +{ + return 0; +} + +#endif |