diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-06-27 19:45:40 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-06-27 19:45:40 -0400 |
commit | 619c99de4be8f0618e7c4cb65039de2aa1e2536c (patch) | |
tree | 716fd002c3f62a2e7d2f57b59f9dd63294042a62 | |
parent | cfa816bf3f823a3bedfedd8e214ea929c5c755fe (diff) |
get_random_u32_below()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | include/linux/random.h | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/include/linux/random.h b/include/linux/random.h index ea101d53..3203d13c 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -9,6 +9,7 @@ #include <unistd.h> #include <sys/syscall.h> #include <linux/bug.h> +#include <linux/log2.h> #ifdef SYS_getrandom static inline int getrandom(void *buf, size_t buflen, unsigned int flags) @@ -40,7 +41,30 @@ static inline type get_random_##type(void) \ get_random_type(int); get_random_type(long); +get_random_type(u8); +get_random_type(u16); get_random_type(u32); get_random_type(u64); +static inline u32 get_random_u32_below(u32 ceil) +{ + if (ceil <= 1) + return 0; + for (;;) { + if (ceil <= 1U << 8) { + u32 mult = ceil * get_random_u8(); + if (likely(is_power_of_2(ceil) || (u8)mult >= (1U << 8) % ceil)) + return mult >> 8; + } else if (ceil <= 1U << 16) { + u32 mult = ceil * get_random_u16(); + if (likely(is_power_of_2(ceil) || (u16)mult >= (1U << 16) % ceil)) + return mult >> 16; + } else { + u64 mult = (u64)ceil * get_random_u32(); + if (likely(is_power_of_2(ceil) || (u32)mult >= -ceil % ceil)) + return mult >> 32; + } + } +} + #endif /* _LINUX_RANDOM_H */ |