Charles.Forsyth20071008-092659b57e419 years agoHistory
156 lines · 2.2 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h" static struct{	QLock;	Rendez	producer;	Rendez	consumer;	ulong	randomcount;	uchar	buf[1024];	uchar	*ep;	uchar	*rp;	uchar	*wp;	uchar	next;	uchar	bits;	uchar	wakeme;	uchar	filled;	int	target;	int	kprocstarted;	ulong	randn;} rb; static intrbnotfull(void*){	int i; 	i = rb.wp - rb.rp;	if(i < 0)		i += sizeof(rb.buf);	return i < rb.target;} static intrbnotempty(void*){	return rb.wp != rb.rp;} static voidgenrandom(void*){	setpri(PriBackground); 	for(;;) {		for(;;)			if(++rb.randomcount > 100000)				break;		if(anyhigher())			sched();		if(rb.filled || !rbnotfull(0))			sleep(&rb.producer, rbnotfull, 0);	}} /* *  produce random bits in a circular buffer */static voidrandomclock(void){	uchar *p; 	if(rb.randomcount == 0)		return; 	if(!rbnotfull(0)) {		rb.filled = 1;		return;	} 	rb.bits = (rb.bits<<2) ^ (rb.randomcount&3);	rb.randomcount = 0; 	rb.next += 2;	if(rb.next != 8)		return; 	rb.next = 0;	*rb.wp ^= rb.bits ^ *rb.rp;	p = rb.wp+1;	if(p == rb.ep)		p = rb.buf;	rb.wp = p; 	if(rb.wakeme)		wakeup(&rb.consumer);} voidrandominit(void){	/* Frequency close but not equal to HZ */	addclock0link(randomclock, 13);	rb.target = 16;	rb.ep = rb.buf + sizeof(rb.buf);	rb.rp = rb.wp = rb.buf;} /* *  consume random bytes from a circular buffer */ulongrandomread(void *xp, ulong n){	int i, sofar;	uchar *e, *p; 	p = xp; 	qlock(&rb);	if(waserror()){		qunlock(&rb);		nexterror();	}	if(!rb.kprocstarted){		rb.kprocstarted = 1;		kproc("genrand", genrandom, nil, 0);	} 	for(sofar = 0; sofar < n; sofar += i){		i = rb.wp - rb.rp;		if(i == 0){			rb.wakeme = 1;			wakeup(&rb.producer);			sleep(&rb.consumer, rbnotempty, 0);			rb.wakeme = 0;			continue;		}		if(i < 0)			i = rb.ep - rb.rp;		if((i+sofar) > n)			i = n - sofar;		memmove(p + sofar, rb.rp, i);		e = rb.rp + i;		if(e == rb.ep)			e = rb.buf;		rb.rp = e;	}	if(rb.filled && rb.wp == rb.rp){		i = 2*rb.target;		if(i > sizeof(rb.buf) - 1)			i = sizeof(rb.buf) - 1;		rb.target = i;		rb.filled = 0;	}	poperror();	qunlock(&rb); 	wakeup(&rb.producer); 	return n;}