X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fprng%2Frandom.c;h=d3780fa7eac3b47fd15ce51a546a66d1a0ce93a3;hb=ea3b40a321e751e016948087ef23ae7b9e8e0150;hp=4b2daef2116774776d8287c2191478442309efea;hpb=c7ce1b20d2f37f97f9cfcd57cb4fb4c7cd66a3a0;p=musl diff --git a/src/prng/random.c b/src/prng/random.c index 4b2daef2..d3780fa7 100644 --- a/src/prng/random.c +++ b/src/prng/random.c @@ -1,21 +1,12 @@ -/* - * random.c - Copyright © 2011 Szabolcs Nagy - * Permission to use, copy, modify, and/or distribute this code - * for any purpose with or without fee is hereby granted. - * There is no warranty. -*/ - #include #include +#include "lock.h" +#include "fork_impl.h" /* this code uses the same lagged fibonacci generator as the original bsd random implementation except for the seeding - -different seeds produce different sequences with long period -(other libcs seed the state with a park-miller generator -when seed=0 some fail to produce good random sequence -others produce the same sequence as another seed) +which was broken in the original */ static uint32_t init[] = { @@ -32,6 +23,8 @@ static int n = 31; static int i = 3; static int j = 0; static uint32_t *x = init+1; +static volatile int lock[1]; +volatile int *const __random_lockptr = lock; static uint32_t lcg31(uint32_t x) { return (1103515245*x + 12345) & 0x7fffffff; @@ -53,7 +46,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 +64,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 +88,37 @@ char *initstate(unsigned seed, char *state, size_t size) { else n = 63; x = (uint32_t*)state + 1; - srandom(seed); + __srandom(seed); + savestate(); + 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; }