mirror of git://git.musl-libc.org/musl
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.
This commit is contained in:
parent
af3d5405b8
commit
f7dff1852b
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue