1*d11907f1SDavid du Colombier #include "u.h"
2*d11907f1SDavid du Colombier #include "../port/lib.h"
3*d11907f1SDavid du Colombier #include "mem.h"
4*d11907f1SDavid du Colombier #include "dat.h"
5*d11907f1SDavid du Colombier #include "fns.h"
6*d11907f1SDavid du Colombier #include "../port/error.h"
7*d11907f1SDavid du Colombier
8*d11907f1SDavid du Colombier
9*d11907f1SDavid du Colombier struct Rb
10*d11907f1SDavid du Colombier {
11*d11907f1SDavid du Colombier QLock;
12*d11907f1SDavid du Colombier Rendez producer;
13*d11907f1SDavid du Colombier Rendez consumer;
14*d11907f1SDavid du Colombier ulong randomcount;
15*d11907f1SDavid du Colombier uchar buf[1024];
16*d11907f1SDavid du Colombier uchar *ep;
17*d11907f1SDavid du Colombier uchar *rp;
18*d11907f1SDavid du Colombier uchar *wp;
19*d11907f1SDavid du Colombier uchar next;
20*d11907f1SDavid du Colombier uchar wakeme;
21*d11907f1SDavid du Colombier ushort bits;
22*d11907f1SDavid du Colombier ulong randn;
23*d11907f1SDavid du Colombier } rb;
24*d11907f1SDavid du Colombier
25*d11907f1SDavid du Colombier static int
rbnotfull(void *)26*d11907f1SDavid du Colombier rbnotfull(void*)
27*d11907f1SDavid du Colombier {
28*d11907f1SDavid du Colombier int i;
29*d11907f1SDavid du Colombier
30*d11907f1SDavid du Colombier i = rb.rp - rb.wp;
31*d11907f1SDavid du Colombier return i != 1 && i != (1 - sizeof(rb.buf));
32*d11907f1SDavid du Colombier }
33*d11907f1SDavid du Colombier
34*d11907f1SDavid du Colombier static int
rbnotempty(void *)35*d11907f1SDavid du Colombier rbnotempty(void*)
36*d11907f1SDavid du Colombier {
37*d11907f1SDavid du Colombier return rb.wp != rb.rp;
38*d11907f1SDavid du Colombier }
39*d11907f1SDavid du Colombier
40*d11907f1SDavid du Colombier static void
genrandom(void *)41*d11907f1SDavid du Colombier genrandom(void*)
42*d11907f1SDavid du Colombier {
43*d11907f1SDavid du Colombier up->basepri = PriNormal;
44*d11907f1SDavid du Colombier up->priority = up->basepri;
45*d11907f1SDavid du Colombier
46*d11907f1SDavid du Colombier for(;;){
47*d11907f1SDavid du Colombier for(;;)
48*d11907f1SDavid du Colombier if(++rb.randomcount > 100000)
49*d11907f1SDavid du Colombier break;
50*d11907f1SDavid du Colombier if(anyhigher())
51*d11907f1SDavid du Colombier sched();
52*d11907f1SDavid du Colombier if(!rbnotfull(0))
53*d11907f1SDavid du Colombier sleep(&rb.producer, rbnotfull, 0);
54*d11907f1SDavid du Colombier }
55*d11907f1SDavid du Colombier }
56*d11907f1SDavid du Colombier
57*d11907f1SDavid du Colombier /*
58*d11907f1SDavid du Colombier * produce random bits in a circular buffer
59*d11907f1SDavid du Colombier */
60*d11907f1SDavid du Colombier static void
randomclock(void)61*d11907f1SDavid du Colombier randomclock(void)
62*d11907f1SDavid du Colombier {
63*d11907f1SDavid du Colombier if(rb.randomcount == 0 || !rbnotfull(0))
64*d11907f1SDavid du Colombier return;
65*d11907f1SDavid du Colombier
66*d11907f1SDavid du Colombier rb.bits = (rb.bits<<2) ^ rb.randomcount;
67*d11907f1SDavid du Colombier rb.randomcount = 0;
68*d11907f1SDavid du Colombier
69*d11907f1SDavid du Colombier rb.next++;
70*d11907f1SDavid du Colombier if(rb.next != 8/2)
71*d11907f1SDavid du Colombier return;
72*d11907f1SDavid du Colombier rb.next = 0;
73*d11907f1SDavid du Colombier
74*d11907f1SDavid du Colombier *rb.wp ^= rb.bits;
75*d11907f1SDavid du Colombier if(rb.wp+1 == rb.ep)
76*d11907f1SDavid du Colombier rb.wp = rb.buf;
77*d11907f1SDavid du Colombier else
78*d11907f1SDavid du Colombier rb.wp = rb.wp+1;
79*d11907f1SDavid du Colombier
80*d11907f1SDavid du Colombier if(rb.wakeme)
81*d11907f1SDavid du Colombier wakeup(&rb.consumer);
82*d11907f1SDavid du Colombier }
83*d11907f1SDavid du Colombier
84*d11907f1SDavid du Colombier void
randominit(void)85*d11907f1SDavid du Colombier randominit(void)
86*d11907f1SDavid du Colombier {
87*d11907f1SDavid du Colombier /* Frequency close but not equal to HZ */
88*d11907f1SDavid du Colombier addclock0link(randomclock, 13);
89*d11907f1SDavid du Colombier rb.ep = rb.buf + sizeof(rb.buf);
90*d11907f1SDavid du Colombier rb.rp = rb.wp = rb.buf;
91*d11907f1SDavid du Colombier kproc("genrandom", genrandom, 0);
92*d11907f1SDavid du Colombier }
93*d11907f1SDavid du Colombier
94*d11907f1SDavid du Colombier /*
95*d11907f1SDavid du Colombier * consume random bytes from a circular buffer
96*d11907f1SDavid du Colombier */
97*d11907f1SDavid du Colombier ulong
randomread(void * xp,ulong n)98*d11907f1SDavid du Colombier randomread(void *xp, ulong n)
99*d11907f1SDavid du Colombier {
100*d11907f1SDavid du Colombier uchar *e, *p;
101*d11907f1SDavid du Colombier ulong x;
102*d11907f1SDavid du Colombier
103*d11907f1SDavid du Colombier p = xp;
104*d11907f1SDavid du Colombier
105*d11907f1SDavid du Colombier if(waserror()){
106*d11907f1SDavid du Colombier qunlock(&rb);
107*d11907f1SDavid du Colombier nexterror();
108*d11907f1SDavid du Colombier }
109*d11907f1SDavid du Colombier
110*d11907f1SDavid du Colombier qlock(&rb);
111*d11907f1SDavid du Colombier for(e = p + n; p < e; ){
112*d11907f1SDavid du Colombier if(rb.wp == rb.rp){
113*d11907f1SDavid du Colombier rb.wakeme = 1;
114*d11907f1SDavid du Colombier wakeup(&rb.producer);
115*d11907f1SDavid du Colombier sleep(&rb.consumer, rbnotempty, 0);
116*d11907f1SDavid du Colombier rb.wakeme = 0;
117*d11907f1SDavid du Colombier continue;
118*d11907f1SDavid du Colombier }
119*d11907f1SDavid du Colombier
120*d11907f1SDavid du Colombier /*
121*d11907f1SDavid du Colombier * beating clocks will be predictable if
122*d11907f1SDavid du Colombier * they are synchronized. Use a cheap pseudo-
123*d11907f1SDavid du Colombier * random number generator to obscure any cycles.
124*d11907f1SDavid du Colombier */
125*d11907f1SDavid du Colombier x = rb.randn*1103515245 ^ *rb.rp;
126*d11907f1SDavid du Colombier *p++ = rb.randn = x;
127*d11907f1SDavid du Colombier
128*d11907f1SDavid du Colombier if(rb.rp+1 == rb.ep)
129*d11907f1SDavid du Colombier rb.rp = rb.buf;
130*d11907f1SDavid du Colombier else
131*d11907f1SDavid du Colombier rb.rp = rb.rp+1;
132*d11907f1SDavid du Colombier }
133*d11907f1SDavid du Colombier qunlock(&rb);
134*d11907f1SDavid du Colombier poperror();
135*d11907f1SDavid du Colombier
136*d11907f1SDavid du Colombier wakeup(&rb.producer);
137*d11907f1SDavid du Colombier
138*d11907f1SDavid du Colombier return n;
139*d11907f1SDavid du Colombier }
140