1*c9945492SAndroid Build Coastguard Worker #include <stdlib.h>
2*c9945492SAndroid Build Coastguard Worker #include <stdint.h>
3*c9945492SAndroid Build Coastguard Worker #include "lock.h"
4*c9945492SAndroid Build Coastguard Worker #include "fork_impl.h"
5*c9945492SAndroid Build Coastguard Worker
6*c9945492SAndroid Build Coastguard Worker /*
7*c9945492SAndroid Build Coastguard Worker this code uses the same lagged fibonacci generator as the
8*c9945492SAndroid Build Coastguard Worker original bsd random implementation except for the seeding
9*c9945492SAndroid Build Coastguard Worker which was broken in the original
10*c9945492SAndroid Build Coastguard Worker */
11*c9945492SAndroid Build Coastguard Worker
12*c9945492SAndroid Build Coastguard Worker static uint32_t init[] = {
13*c9945492SAndroid Build Coastguard Worker 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
14*c9945492SAndroid Build Coastguard Worker 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
15*c9945492SAndroid Build Coastguard Worker 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
16*c9945492SAndroid Build Coastguard Worker 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
17*c9945492SAndroid Build Coastguard Worker 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
18*c9945492SAndroid Build Coastguard Worker 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
19*c9945492SAndroid Build Coastguard Worker 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
20*c9945492SAndroid Build Coastguard Worker 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657};
21*c9945492SAndroid Build Coastguard Worker
22*c9945492SAndroid Build Coastguard Worker static int n = 31;
23*c9945492SAndroid Build Coastguard Worker static int i = 3;
24*c9945492SAndroid Build Coastguard Worker static int j = 0;
25*c9945492SAndroid Build Coastguard Worker static uint32_t *x = init+1;
26*c9945492SAndroid Build Coastguard Worker static volatile int lock[1];
27*c9945492SAndroid Build Coastguard Worker volatile int *const __random_lockptr = lock;
28*c9945492SAndroid Build Coastguard Worker
lcg31(uint32_t x)29*c9945492SAndroid Build Coastguard Worker static uint32_t lcg31(uint32_t x) {
30*c9945492SAndroid Build Coastguard Worker return (1103515245*x + 12345) & 0x7fffffff;
31*c9945492SAndroid Build Coastguard Worker }
32*c9945492SAndroid Build Coastguard Worker
lcg64(uint64_t x)33*c9945492SAndroid Build Coastguard Worker static uint64_t lcg64(uint64_t x) {
34*c9945492SAndroid Build Coastguard Worker return 6364136223846793005ull*x + 1;
35*c9945492SAndroid Build Coastguard Worker }
36*c9945492SAndroid Build Coastguard Worker
savestate()37*c9945492SAndroid Build Coastguard Worker static void *savestate() {
38*c9945492SAndroid Build Coastguard Worker x[-1] = (n<<16)|(i<<8)|j;
39*c9945492SAndroid Build Coastguard Worker return x-1;
40*c9945492SAndroid Build Coastguard Worker }
41*c9945492SAndroid Build Coastguard Worker
loadstate(uint32_t * state)42*c9945492SAndroid Build Coastguard Worker static void loadstate(uint32_t *state) {
43*c9945492SAndroid Build Coastguard Worker x = state+1;
44*c9945492SAndroid Build Coastguard Worker n = x[-1]>>16;
45*c9945492SAndroid Build Coastguard Worker i = (x[-1]>>8)&0xff;
46*c9945492SAndroid Build Coastguard Worker j = x[-1]&0xff;
47*c9945492SAndroid Build Coastguard Worker }
48*c9945492SAndroid Build Coastguard Worker
__srandom(unsigned seed)49*c9945492SAndroid Build Coastguard Worker static void __srandom(unsigned seed) {
50*c9945492SAndroid Build Coastguard Worker int k;
51*c9945492SAndroid Build Coastguard Worker uint64_t s = seed;
52*c9945492SAndroid Build Coastguard Worker
53*c9945492SAndroid Build Coastguard Worker if (n == 0) {
54*c9945492SAndroid Build Coastguard Worker x[0] = s;
55*c9945492SAndroid Build Coastguard Worker return;
56*c9945492SAndroid Build Coastguard Worker }
57*c9945492SAndroid Build Coastguard Worker i = n == 31 || n == 7 ? 3 : 1;
58*c9945492SAndroid Build Coastguard Worker j = 0;
59*c9945492SAndroid Build Coastguard Worker for (k = 0; k < n; k++) {
60*c9945492SAndroid Build Coastguard Worker s = lcg64(s);
61*c9945492SAndroid Build Coastguard Worker x[k] = s>>32;
62*c9945492SAndroid Build Coastguard Worker }
63*c9945492SAndroid Build Coastguard Worker /* make sure x contains at least one odd number */
64*c9945492SAndroid Build Coastguard Worker x[0] |= 1;
65*c9945492SAndroid Build Coastguard Worker }
66*c9945492SAndroid Build Coastguard Worker
srandom(unsigned seed)67*c9945492SAndroid Build Coastguard Worker void srandom(unsigned seed) {
68*c9945492SAndroid Build Coastguard Worker LOCK(lock);
69*c9945492SAndroid Build Coastguard Worker __srandom(seed);
70*c9945492SAndroid Build Coastguard Worker UNLOCK(lock);
71*c9945492SAndroid Build Coastguard Worker }
72*c9945492SAndroid Build Coastguard Worker
initstate(unsigned seed,char * state,size_t size)73*c9945492SAndroid Build Coastguard Worker char *initstate(unsigned seed, char *state, size_t size) {
74*c9945492SAndroid Build Coastguard Worker void *old;
75*c9945492SAndroid Build Coastguard Worker
76*c9945492SAndroid Build Coastguard Worker if (size < 8)
77*c9945492SAndroid Build Coastguard Worker return 0;
78*c9945492SAndroid Build Coastguard Worker LOCK(lock);
79*c9945492SAndroid Build Coastguard Worker old = savestate();
80*c9945492SAndroid Build Coastguard Worker if (size < 32)
81*c9945492SAndroid Build Coastguard Worker n = 0;
82*c9945492SAndroid Build Coastguard Worker else if (size < 64)
83*c9945492SAndroid Build Coastguard Worker n = 7;
84*c9945492SAndroid Build Coastguard Worker else if (size < 128)
85*c9945492SAndroid Build Coastguard Worker n = 15;
86*c9945492SAndroid Build Coastguard Worker else if (size < 256)
87*c9945492SAndroid Build Coastguard Worker n = 31;
88*c9945492SAndroid Build Coastguard Worker else
89*c9945492SAndroid Build Coastguard Worker n = 63;
90*c9945492SAndroid Build Coastguard Worker x = (uint32_t*)state + 1;
91*c9945492SAndroid Build Coastguard Worker __srandom(seed);
92*c9945492SAndroid Build Coastguard Worker savestate();
93*c9945492SAndroid Build Coastguard Worker UNLOCK(lock);
94*c9945492SAndroid Build Coastguard Worker return old;
95*c9945492SAndroid Build Coastguard Worker }
96*c9945492SAndroid Build Coastguard Worker
setstate(char * state)97*c9945492SAndroid Build Coastguard Worker char *setstate(char *state) {
98*c9945492SAndroid Build Coastguard Worker void *old;
99*c9945492SAndroid Build Coastguard Worker
100*c9945492SAndroid Build Coastguard Worker LOCK(lock);
101*c9945492SAndroid Build Coastguard Worker old = savestate();
102*c9945492SAndroid Build Coastguard Worker loadstate((uint32_t*)state);
103*c9945492SAndroid Build Coastguard Worker UNLOCK(lock);
104*c9945492SAndroid Build Coastguard Worker return old;
105*c9945492SAndroid Build Coastguard Worker }
106*c9945492SAndroid Build Coastguard Worker
random(void)107*c9945492SAndroid Build Coastguard Worker long random(void) {
108*c9945492SAndroid Build Coastguard Worker long k;
109*c9945492SAndroid Build Coastguard Worker
110*c9945492SAndroid Build Coastguard Worker LOCK(lock);
111*c9945492SAndroid Build Coastguard Worker if (n == 0) {
112*c9945492SAndroid Build Coastguard Worker k = x[0] = lcg31(x[0]);
113*c9945492SAndroid Build Coastguard Worker goto end;
114*c9945492SAndroid Build Coastguard Worker }
115*c9945492SAndroid Build Coastguard Worker x[i] += x[j];
116*c9945492SAndroid Build Coastguard Worker k = x[i]>>1;
117*c9945492SAndroid Build Coastguard Worker if (++i == n)
118*c9945492SAndroid Build Coastguard Worker i = 0;
119*c9945492SAndroid Build Coastguard Worker if (++j == n)
120*c9945492SAndroid Build Coastguard Worker j = 0;
121*c9945492SAndroid Build Coastguard Worker end:
122*c9945492SAndroid Build Coastguard Worker UNLOCK(lock);
123*c9945492SAndroid Build Coastguard Worker return k;
124*c9945492SAndroid Build Coastguard Worker }
125