diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-06-29 15:29:52 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-06-29 15:29:52 -0400 |
commit | f7dff1852b996363061e04531a15a3403351c375 (patch) | |
tree | aeed815eab8e766a10f0af833b8e31dc2d826073 /src/prng/random.c | |
parent | af3d5405b8d7b00c121643d7a0c0b9bb31cc7139 (diff) | |
download | musl-f7dff1852b996363061e04531a15a3403351c375.tar.gz musl-f7dff1852b996363061e04531a15a3403351c375.tar.bz2 musl-f7dff1852b996363061e04531a15a3403351c375.tar.xz musl-f7dff1852b996363061e04531a15a3403351c375.zip |
locking support for random() prng
these interfaces are required to be thread-safe even though they are
not state-free. the random number sequence is shared across all
threads.
Diffstat (limited to 'src/prng/random.c')
-rw-r--r-- | src/prng/random.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/prng/random.c b/src/prng/random.c index 4b2daef2..cc5702ed 100644 --- a/src/prng/random.c +++ b/src/prng/random.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <stdint.h> +#include "libc.h" /* this code uses the same lagged fibonacci generator as the @@ -32,6 +33,7 @@ static int n = 31; static int i = 3; static int j = 0; static uint32_t *x = init+1; +static int lock; static uint32_t lcg31(uint32_t x) { return (1103515245*x + 12345) & 0x7fffffff; @@ -53,7 +55,7 @@ static void loadstate(uint32_t *state) { j = x[-1]&0xff; } -void srandom(unsigned seed) { +static void __srandom(unsigned seed) { int k; uint64_t s = seed; @@ -71,11 +73,20 @@ void srandom(unsigned seed) { x[0] |= 1; } +void srandom(unsigned seed) { + LOCK(&lock); + __srandom(seed); + UNLOCK(&lock); +} + char *initstate(unsigned seed, char *state, size_t size) { - void *old = savestate(); + void *old; + if (size < 8) return 0; - else if (size < 32) + LOCK(&lock); + old = savestate(); + if (size < 32) n = 0; else if (size < 64) n = 7; @@ -86,26 +97,36 @@ char *initstate(unsigned seed, char *state, size_t size) { else n = 63; x = (uint32_t*)state + 1; - srandom(seed); + __srandom(seed); + UNLOCK(&lock); return old; } char *setstate(char *state) { - void *old = savestate(); + void *old; + + LOCK(&lock); + old = savestate(); loadstate((uint32_t*)state); + UNLOCK(&lock); return old; } long random(void) { long k; - if (n == 0) - return x[0] = lcg31(x[0]); + LOCK(&lock); + if (n == 0) { + k = x[0] = lcg31(x[0]); + goto end; + } x[i] += x[j]; k = x[i]>>1; if (++i == n) i = 0; if (++j == n) j = 0; +end: + UNLOCK(&lock); return k; } |