plan 9 kernel history: overview | file list | diff list

2002/1017/alphapc/random.c (diff list | history)

2002/1017/sys/src/9/alphapc/random.c:1,1382002/1130/sys/src/9/alphapc/random.c:1 (short | long | prev)
2000/0609    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
                 
                 
struct Rb 
{ 
	QLock; 
	Rendez	producer; 
	Rendez	consumer; 
	ulong	randomcount; 
	uchar	buf[1024]; 
	uchar	*ep; 
	uchar	*rp; 
	uchar	*wp; 
	uchar	next; 
	uchar	wakeme; 
	ushort	bits; 
	ulong	randn; 
} rb; 
                 
static int 
rbnotfull(void*) 
{ 
	int i; 
                 
	i = rb.rp - rb.wp; 
	return i != 1 && i != (1 - sizeof(rb.buf)); 
} 
                 
static int 
rbnotempty(void*) 
{ 
	return rb.wp != rb.rp; 
} 
                 
void 
genrandom(void*) 
{ 
	up->basepri = PriNormal; 
	up->priority = up->basepri; 
                 
	for(;;){ 
		for(;;) 
			if(++rb.randomcount > 100000) 
				break; 
		if(anyhigher()) 
			sched(); 
		if(!rbnotfull(0)) 
			sleep(&rb.producer, rbnotfull, 0); 
	} 
} 
                 
/* 
 *  produce random bits in a circular buffer 
 */ 
static void 
randomclock(void) 
{ 
	if(rb.randomcount == 0 || !rbnotfull(0)) 
		return; 
                 
	rb.bits = (rb.bits<<2) ^ rb.randomcount; 
	rb.randomcount = 0; 
                 
	rb.next++; 
	if(rb.next != 8/2) 
		return; 
	rb.next = 0; 
                 
	*rb.wp ^= rb.bits; 
	if(rb.wp+1 == rb.ep) 
		rb.wp = rb.buf; 
	else 
		rb.wp = rb.wp+1; 
                 
	if(rb.wakeme) 
		wakeup(&rb.consumer); 
} 
                 
2000/0618    
void 
2000/0609    
randominit(void) 
{ 
2002/1017    
	addclock0link(randomclock, 1000/HZ); 
2000/0609    
	rb.ep = rb.buf + sizeof(rb.buf); 
	rb.rp = rb.wp = rb.buf; 
	kproc("genrandom", genrandom, 0); 
} 
                 
/* 
 *  consume random bytes from a circular buffer 
 */ 
2000/0618    
ulong 
2000/0609    
randomread(void *xp, ulong n) 
{ 
	uchar *e, *p; 
	ulong x; 
                 
	p = xp; 
                 
	if(waserror()){ 
		qunlock(&rb); 
		nexterror(); 
	} 
                 
	qlock(&rb); 
	for(e = p + n; p < e; ){ 
		if(rb.wp == rb.rp){ 
			rb.wakeme = 1; 
			wakeup(&rb.producer); 
			sleep(&rb.consumer, rbnotempty, 0); 
			rb.wakeme = 0; 
			continue; 
		} 
                 
		/* 
		 *  beating clocks will be precictable if 
		 *  they are synchronized.  Use a cheap pseudo 
		 *  random number generator to obscure any cycles. 
		 */ 
		x = rb.randn*1103515245 ^ *rb.rp; 
		*p++ = rb.randn = x; 
                 
		if(rb.rp+1 == rb.ep) 
			rb.rp = rb.buf; 
		else 
			rb.rp = rb.rp+1; 
	} 
	qunlock(&rb); 
	poperror(); 
                 
	wakeup(&rb.producer); 
                 
	return n; 
} 
2002/1130    
#include "../pc/random.c" 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)