~ chicken-core (chicken-5) ef8c7d136487418159c706b30a46453baa4abf0a
commit ef8c7d136487418159c706b30a46453baa4abf0a Author: felix <felix@call-with-current-continuation.org> AuthorDate: Sat Nov 4 12:40:20 2017 +0100 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Sat Nov 4 12:40:20 2017 +0100 use direct syscall for getrandom(2), obtain uniformity via loop diff --git a/runtime.c b/runtime.c index df42986f..ffb526b4 100644 --- a/runtime.c +++ b/runtime.c @@ -12554,7 +12554,7 @@ C_word C_random_bytes(C_word buf, C_word size) arc4random_buf(C_data_pointer(buf), count); #elif defined(SYS_getrandom) && defined(__NR_getrandom) while(count > 0) { - r = getrandom(C_data_pointer(buf) + off, count, GRND_NONBLOCK); + r = syscall(SYS_getrandom, C_data_pointer(buf) + off, count, GRND_NONBLOCK); if(r == -1) { if(errno != EINTR) return C_SCHEME_FALSE; @@ -12594,14 +12594,21 @@ C_word C_random_bytes(C_word buf, C_word size) } +#ifdef C_SIXTYFOUR +# define rand_uint C_u32 +#else +# define rand_uint C_u64 +#endif + + /* WELL512 pseudo random number generator, see also: https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear http://lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf */ -static C_u32 random_word(void) +static rand_uint random_word(void) { - C_u32 a, b, c, d, r; + rand_uint a, b, c, d, r; a = random_state[random_state_index]; c = random_state[(random_state_index+13)&15]; b = a^c^(a<<16)^(c<<15); @@ -12615,11 +12622,21 @@ static C_u32 random_word(void) r = random_state[random_state_index]; return r; } - + + +static rand_uint random_uniform(rand_uint bound) +{ + rand_uint r; + + do { r = random_word(); } while(r >= bound); + + return r; +} + C_regparm C_word C_random_fixnum(C_word n) { - C_u32 r = random_word(); + rand_uint r; C_word nf; if (!(n & C_FIXNUM_BIT)) @@ -12630,7 +12647,7 @@ C_regparm C_word C_random_fixnum(C_word n) if(nf < 0) barf(C_OUT_OF_RANGE_ERROR, "pseudo-random-integer", n, C_fix(0)); - return C_fix(((double)r / 0xffffffffUL) * C_unfix(n)); + return C_fix(random_uniform(nf)); } @@ -12655,7 +12672,7 @@ C_s_a_u_i_random_int(C_word **ptr, C_word n, C_word rn) len -= sizeof(C_u32); } - *end = random_word() >> len; + *end = random_word() >> len; /* XXX is this right? uniform? */ return C_bignum_simplify(result); }Trap