~kris/9p

9hist

3256d08c2e17a90b29e3aa142a717b462ff3218d — David du Colombier 32 years ago b7e9d0a
Plan 9 from Bell Labs 1994-02-08
5 files changed, 212 insertions(+), 67 deletions(-)

M port/alloc.c
M port/devcons.c
M port/portfns.h
M port/qio.c
M power/mem.h
M port/alloc.c => port/alloc.c +3 -0
@@ 118,6 118,9 @@ xinit(void)
	conf.base1 = (ulong)KADDR(conf.base1);
	conf.npage0 = (ulong)KADDR(conf.npage0);
	conf.npage1 = (ulong)KADDR(conf.npage1);

	/* setup initial memory allocations for interrupt time */
	qinit();
}

/*

M port/devcons.c => port/devcons.c +25 -8
@@ 44,10 44,10 @@ printinit(void)
 *   or uart code.  Multi-line messages to serial consoles may get
 *   interspersed with other messages.
 */
void
putstrn(char *str, int n)
static void
putstrn0(char *str, int n, int usewrite)
{
	int m;
	int m, x;
	char *t;
	char buf[PRINTSIZE+2];



@@ 73,17 73,34 @@ putstrn(char *str, int n)
			memmove(buf, str, m);
			buf[m] = '\r';
			buf[m+1] = '\n';
			qwrite(printq, buf, m+2, 1);
			if(usewrite)
				qwrite(printq, buf, m+2, 0);
			else {
				x = splhi();
				qproduce(printq, buf, m+2);
				splx(x);
			}
			str = t + 1;
			n -= m + 1;
		}
		else {
			qwrite(printq, str, n, 1);
		} else {
			if(usewrite)
				qwrite(printq, str, n, 0);
			else {
				x = splhi();
				qproduce(printq, str, n);
				splx(x);
			}
			break;
		}
	}
}

void
putstrn(char *str, int n)
{
	putstrn0(str, n, 0);
}

int
sprint(char *s, char *fmt, ...)
{


@@ 734,7 751,7 @@ conswrite(Chan *c, void *va, long n, ulong offset)
			if(bp > sizeof buf)
				bp = sizeof buf;
			memmove(buf, a, bp);
			putstrn(a, bp);
			putstrn0(a, bp, 1);
			a += bp;
			l -= bp;
		}

M port/portfns.h => port/portfns.h +1 -0
@@ 183,6 183,7 @@ int		qcanread(Queue*);
void		qclose(Queue*);
int		qconsume(Queue*, void*, int);
void		qhangup(Queue*);
void		qinit(void);
int		qlen(Queue*);
void		qlock(QLock*);
Queue*		qopen(int, int, void (*)(void*), void*);

M port/qio.c => port/qio.c +182 -59
@@ 79,6 79,9 @@ struct Queue
	Rendez	rr;		/* process waiting to read */
	QLock	wlock;		/* mutex for writing processes */
	Rendez	wr;		/* process waiting to write */

	uchar	*syncbuf;	/* synchronous IO buffer */
	int	synclen;	/* syncbuf length */
};

enum


@@ 188,17 191,30 @@ iallockproc(void *arg)
}

void
iallocinit(void)
qinit(void)
{
	int pow;
	Chunkl *cl;
	Chunk *p;

	/* start with a bunch of initial blocks */
	for(pow = Minpow; pow <= Maxpow; pow++){
		cl = &arena.alloc[pow];
		cl->goal = Maxpow-pow + 16;
		cl->goal = Maxpow-pow + 32;
		cl->first = 0;
		for(; cl->have < cl->goal; cl->have++){
			p = malloc(1<<pow);
			p->next = cl->first;
			cl->first = p;
		}
	}

	/* start garbage collector */
}

void
iallocinit(void)
{
	/* start garbage collector/creator */
	kproc("ialloc", iallockproc, 0);
}



@@ 216,15 232,19 @@ ixsummary(void)
	print("\n");
}

/*
 *  interrupt time allocation (round data base address to 64 bit boundary)
 */
Block*
iallocb(int size)
{
	int pow;
	ulong addr;
	Chunkl *cl;
	Chunk *p;
	Block *b;

	size += sizeof(Block);
	size += sizeof(Block) + 7;
	for(pow = Minpow; pow <= Maxpow; pow++){
		if(size <= (1<<pow)){
			cl = &arena.alloc[pow];


@@ 239,12 259,15 @@ iallocb(int size)
			cl->have--;
			cl->first = p->next;
			unlock(cl);

			b = (Block *)p;
			memset(b, 0, sizeof(Block));
			b->base = (uchar*)(b+1);
			addr = (ulong)b;
			addr = (addr + sizeof(Block) + 7) & ~7;
			b->base = (uchar*)addr;
			b->wp = b->base;
			b->rp = b->base;
			b->lim = b->base + (1<<pow) - sizeof(Block);
			b->lim = ((uchar*)b) + (1<<pow);
			return b;
		}
	}


@@ 268,21 291,25 @@ ifree(void *a)
}

/*
 *  allocate queues and blocks
 *  allocate queues and blocks (round data base address to 64 bit boundary)
 */
Block*
allocb(int size)
{
	Block *b;
	ulong addr;

	b = malloc(sizeof(Block) + size);
	size += sizeof(Block) + 7;
	b = malloc(size);
	if(b == 0)
		exhausted("Blocks");

	b->base = (uchar*)(b+1);
	addr = (ulong)b;
	addr = (addr + sizeof(Block) + 7) & ~7;
	b->base = (uchar*)addr;
	b->rp = b->base;
	b->wp = b->base;
	b->lim = b->base + size;
	b->lim = ((uchar*)b) + size;
	b->flag = 0;

	return b;


@@ 343,12 370,32 @@ int
qproduce(Queue *q, void *vp, int len)
{
	Block *b;
	int dowakeup;
	int i, dowakeup;
	uchar *p = vp;

	/* sync with qread */
	dowakeup = 0;
	lock(q);

	if(q->syncbuf){
		/* synchronous communications, just copy into buffer */
		if(len < q->synclen)
			q->synclen = len;
		i = q->synclen;
		memmove(q->syncbuf, p, i);
		q->syncbuf = 0;		/* tell reader buffer is full */
		len -= i;
		if(len <= 0 || (q->state & Qmsg)){
			unlock(q);
			wakeup(&q->rr);
			return i;
		}

		/* queue anything that's left */
		dowakeup = 1;
		p += i;
	}

	/* no waiting receivers, room in buffer? */
	if(q->len >= q->limit){
		unlock(q);


@@ 379,8 426,7 @@ qproduce(Queue *q, void *vp, int len)
	if(q->state & Qstarve){
		q->state &= ~Qstarve;
		dowakeup = 1;
	} else
		dowakeup = 0;
	}
	unlock(q);

	if(dowakeup){


@@ 416,6 462,14 @@ qopen(int limit, int msg, void (*kick)(void*), void *arg)
}

static int
filled(void *a)
{
	Queue *q = a;

	return q->syncbuf == 0;
}

static int
notempty(void *a)
{
	Queue *q = a;


@@ 436,6 490,16 @@ qread(Queue *q, void *vp, int len)

	qlock(&q->rlock);
	if(waserror()){
		/* can't let go if the buffer is in use */
		if(q->syncbuf){
			qlock(&q->wlock);
			x = splhi();
			lock(q);
			q->syncbuf = 0;
			unlock(q);
			splx(x);
			qunlock(&q->wlock);
		}
		qunlock(&q->rlock);
		nexterror();
	}


@@ 460,10 524,23 @@ qread(Queue *q, void *vp, int len)
			return 0;
		}

		q->state |= Qstarve;
		unlock(q);
		splx(x);
		sleep(&q->rr, notempty, q);
		if(globalmem(vp)){
			/* just let the writer fill the buffer directly */
			q->synclen = len;
			q->syncbuf = vp;
			unlock(q);
			splx(x);
			sleep(&q->rr, filled, q);
			len = q->synclen;
			poperror();
			qunlock(&q->rlock);
			return len;
		} else {
			q->state |= Qstarve;
			unlock(q);
			splx(x);
			sleep(&q->rr, notempty, q);
		}
	}

	/* remove a buffered block */


@@ 490,8 567,7 @@ qread(Queue *q, void *vp, int len)
	if(b->rp >= b->wp || (q->state&Qmsg)) {
		poison(b);
		free(b);
	}
	else {
	} else {
		x = splhi();
		lock(q);
		b->next = q->bfirst;


@@ 521,64 597,111 @@ qnotfull(void *a)
/*
 *  write to a queue.  if no reader blocks are posted
 *  queue the data.
 *
 *  all copies should be outside of spl since they can fault.
 */
long
qwrite(Queue *q, void *vp, int len, int nowait)
{
	int x, dowakeup;
	int n, sofar, x, dowakeup;
	Block *b;
	uchar *p = vp;

	b = allocb(len);
	memmove(b->wp, p, len);
	b->wp += len;
	dowakeup = 0;

	/* flow control */
	while(!qnotfull(q)){
		if(nowait)
			return len;
		qlock(&q->wlock);
		if(waserror()) {
	if(waserror()){
		qunlock(&q->wlock);
		nexterror();
	};
	qlock(&q->wlock);

	sofar = 0;
	if(q->syncbuf){
		if(len < q->synclen)
			sofar = len;
		else
			sofar = q->synclen;

		memmove(q->syncbuf, p, sofar);
		q->synclen = sofar;
		q->syncbuf = 0;
		wakeup(&q->rr);

		if(len == sofar || (q->state & Qmsg)){
			qunlock(&q->wlock);
			nexterror();
			poperror();
			return len;
		}
		q->state |= Qflow;
		sleep(&q->wr, qnotfull, q);
		qunlock(&q->wlock);
		poperror();
	}

	x = splhi();
	lock(q);
	do {
		n = len-sofar;
		if(n > 128*1024)
			n = 128*1024;

		b = allocb(n);
		memmove(b->wp, p+sofar, n);
		b->wp += n;
	
		/* flow control */
		while(!qnotfull(q)){
			if(nowait){
				free(b);
				qunlock(&q->wlock);
				poperror();
				return len;
			}
			q->state |= Qflow;
			sleep(&q->wr, qnotfull, q);
		}
	
		x = splhi();
		lock(q);
	
		if(q->state & Qclosed){
			unlock(q);
			splx(x);
			error(Ehungup);
		}
	
		if(q->syncbuf){
			/* we guessed wrong and did an extra copy */
			if(n > q->synclen)
				n = q->synclen;
			memmove(q->syncbuf, b->rp, n);
			q->synclen = n;
			q->syncbuf = 0;
			dowakeup = 1;
			free(b);
		} else {
			/* we guessed right, queue it */
			if(q->bfirst)
				q->blast->next = b;
			else
				q->bfirst = b;
			q->blast = b;
			q->len += n;
	
			if(q->state & Qstarve){
				q->state &= ~Qstarve;
				dowakeup = 1;
			}
		}

	if(q->state & Qclosed){
		unlock(q);
		splx(x);
		error(Ehungup);
	}

	if(q->bfirst)
		q->blast->next = b;
	else
		q->bfirst = b;
	q->blast = b;
	q->len += len;

	if(q->state & Qstarve){
		q->state &= ~Qstarve;
		dowakeup = 1;
	} else
		dowakeup = 0;
		if(dowakeup){
			if(q->kick)
				(*q->kick)(q->arg);
			wakeup(&q->rr);
		}

	unlock(q);
	splx(x);

	if(dowakeup){
		if(q->kick)
			(*q->kick)(q->arg);
		wakeup(&q->rr);
	}
		sofar += n;
	} while(sofar < len && (q->state & Qmsg) == 0);

	qunlock(&q->wlock);
	poperror();
	return len;
}


M power/mem.h => power/mem.h +1 -0
@@ 130,6 130,7 @@
#define	USTKSIZE	(4*1024*1024)		/* size of user stack */
#define LKSEGSIZE	(25*BY2PG)
#define LKSEGBASE	(USTKTOP-USTKSIZE-LKSEGSIZE)	
#define globalmem(x)	(((ulong)x)&KZERO)	/* addresses valid in all contexts */
/*
 * Exception codes
 */