From f02bdf3ceaf245982728722a2c3eced750c511a1 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 22 Sep 2024 11:22:38 +0200 Subject: m MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- get_stack_limit.c | 23 ++++++++---- get_stack_space.c | 2 +- libsimple/random.h | 104 +++++++++++++++++++++++++++++++++++++++++++++++------ libsimple/stack.h | 50 +++++++++++++++++++++++--- 4 files changed, 157 insertions(+), 22 deletions(-) diff --git a/get_stack_limit.c b/get_stack_limit.c index 7005727..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; @@ -47,15 +47,24 @@ line_found: close(fd); line = &line[sizeof("Max stack size ") - 1U]; - while (*line == ' ') + while (*line == ' ' || *line == '\t') + line++; + if (soft) { + *soft = SIZE_MAX; + if (isdigit(*line)) + *soft = (size_t)strtoull(line, NULL, 10); + } + + while (*line != ' ' && *line != '\t' && *line && *line != '\n') line++; - if (soft) - *soft = (size_t)strtoull(line, NULL, 10); - while (*line == ' ') + while (*line == ' ' || *line == '\t') line++; - if (hard) - *hard = (size_t)strtoull(line, NULL, 10); + 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 5e54aac..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; diff --git a/libsimple/random.h b/libsimple/random.h index ecce38c..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,17 +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 */ + +/** + * 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 */ -/* 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, 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 */ -/* TODO doc, man (since 1.7) */ -void *libsimple_random_bytes(uintmax_t (*rng)(size_t bits, void *user), void *user, void *buffer, size_t bytes); +/** + * 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 -- cgit v1.2.3-70-g09d2