aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--Makefile3
-rw-r--r--get_stack_limit.c26
-rw-r--r--get_stack_space.c5
-rw-r--r--libsimple/random.h103
-rw-r--r--libsimple/stack.h50
-rw-r--r--random_bits.c6
-rw-r--r--random_bytes.c41
8 files changed, 208 insertions, 28 deletions
diff --git a/LICENSE b/LICENSE
index b29e37d..be3bb97 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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
diff --git a/Makefile b/Makefile
index 4c2f411..c85db9d 100644
--- a/Makefile
+++ b/Makefile
@@ -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