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

1990/0911/port/stream.c (diff list | history)

1990/0907/sys/src/9/port/stream.c:10,161990/0911/sys/src/9/port/stream.c:10,15 (short | long | prev | next)
1990/0227    
 
1990/0321    
enum { 
1990/0907    
	Nclass=4,	/* number of block classes */ 
1990/0321    
	Nlds=32,	/* max number of pushable line disciplines */ 
}; 
 
1990/0312    
/* 
1990/0907/sys/src/9/port/stream.c:22,421990/0911/sys/src/9/port/stream.c:21,28
1990/0312    
/* 
 *  line disciplines that can be pushed 
 */ 
1990/0321    
static Qinfo *lds[Nlds+1]; 
1990/0911    
static Qinfo *lds; 
1990/0227    
 
1990/0907    
void 
newqinfo(Qinfo *qi) 
{ 
	int i; 
                 
	for(i=0; i<Nlds && lds[i]; i++) 
		if(lds[i] == qi) 
			return; 
	if(i == Nlds) 
		panic("pushable"); 
	lds[i] = qi; 
} 
                 
1990/0227    
/* 
 *  All stream structures are ialloc'd at boot time 
 */ 
1990/0907/sys/src/9/port/stream.c:48,581990/0911/sys/src/9/port/stream.c:34,39
1990/0227    
/* 
 *  The block classes.  There are Nclass block sizes, each with its own free list. 
 *  All are ialloced at qinit() time. 
1990/08272    
 * 
 *  NOTE: to help the mappings on the IO2 and IO3 boards, the data pointed 
 *	  to by a block must not cross a 4k boundary.  Therefore: 
 *	  1) all the following block sizes divide evenly into 4k 
 *	  2) all the blocks are ialloc'd to not cross 4k boundaries 
1990/0227    
 */ 
typedef struct { 
	int	size; 
1990/0907/sys/src/9/port/stream.c:62,1211990/0911/sys/src/9/port/stream.c:43,55
1990/0227    
} Bclass; 
Bclass bclass[Nclass]={ 
	{ 0 }, 
1990/08272    
	{ 64 }, 
	{ 256 }, 
1990/0911    
	{ 68 }, 
	{ 260 }, 
1990/0409    
	{ 4096 }, 
1990/0227    
}; 
 
/* 
1990/0331    
 *  Dump all block information of how many blocks are in which queues 
 */ 
void 
1990/0707    
dumpblocks(Queue *q, char c) 
{ 
	Block *bp; 
	uchar *cp; 
1990/0911    
#include "stream.h" 
1990/0707    
 
	lock(q); 
	for(bp = q->first; bp; bp = bp->next){ 
1990/0801    
		print("%c%d%c", c, bp->wptr-bp->rptr, (bp->flags&S_DELIM)); 
1990/0707    
		for(cp = bp->rptr; cp<bp->wptr && cp<bp->rptr+10; cp++) 
			print(" %uo", *cp); 
		print("\n"); 
	} 
	unlock(q); 
} 
                 
void 
1990/0331    
dumpqueues(void) 
{ 
	Queue *q; 
	int count; 
	Block *bp; 
1990/0509    
	Bclass *bcp; 
1990/0331    
                 
1990/0509    
	print("\n"); 
1990/0331    
	for(q = qlist; q < qlist + conf.nqueue; q++, q++){ 
		if(!(q->flag & QINUSE)) 
			continue; 
1990/0707    
		print("%s %ux  R n %d l %d f %ux r %ux", q->info->name, q, q->nb, 
			q->len, q->flag, &(q->r)); 
		print("  W n %d l %d f %ux r %ux\n", WR(q)->nb, WR(q)->len, WR(q)->flag, 
			&(WR(q)->r)); 
		dumpblocks(q, 'R'); 
		dumpblocks(WR(q), 'W'); 
1990/0331    
	} 
1990/0509    
	print("\n"); 
1990/0511    
	for(bcp=bclass; bcp<&bclass[Nclass]; bcp++){ 
1990/0509    
		lock(bcp); 
		for(count = 0, bp = bcp->first; bp; count++, bp = bp->next) 
			; 
		unlock(bcp); 
		print("%d blocks of size %d\n", count, bcp->size); 
	} 
	print("\n"); 
1990/0331    
} 
                 
/* 
1990/0227    
 *  Allocate streams, queues, and blocks.  Allocate n block classes with 
 *	1/2(m+1) to class m < n-1 
1990/0907/sys/src/9/port/stream.c:128,1331990/0911/sys/src/9/port/stream.c:62,70
1990/0227    
	Block *bp; 
	Bclass *bcp; 
 
1990/0911    
	/* 
	 *  allocate blocks, queues, and streams 
	 */ 
1990/0227    
	slist = (Stream *)ialloc(conf.nstream * sizeof(Stream), 0); 
	qlist = (Queue *)ialloc(conf.nqueue * sizeof(Queue), 0); 
	blist = (Block *)ialloc(conf.nblock * sizeof(Block), 0); 
1990/0907/sys/src/9/port/stream.c:138,1501990/0911/sys/src/9/port/stream.c:75,82
1990/0227    
			n = n/2; 
		bcp = &bclass[class]; 
		for(i = 0; i < n; i++) { 
1990/08272    
			/* 
			 *  The i == 0 means that each allocation range 
			 *  starts on a page boundary.  This makes sure 
			 *  no block crosses a page boundary. 
			 */ 
1990/0907    
			if(bcp->size) 
				bp->base = (uchar *)ialloc(bcp->size, i == 0); 
1990/0911    
				bp->base = (uchar *)ialloc(bcp->size, 0); 
1990/0227    
			bp->lim = bp->base + bcp->size; 
			bp->flags = class; 
			freeb(bp); 
1990/0907/sys/src/9/port/stream.c:151,1591990/0911/sys/src/9/port/stream.c:83,109
1990/0227    
			bp++; 
		} 
	} 
1990/0911    
 
	/* 
	 *  make stream modules available 
	 */ 
	streaminit0(); 
1990/0227    
} 
 
/* 
1990/0911    
 *  make known a stream module and call its initialization routine, if 
 *  it has one. 
 */ 
void 
newqinfo(Qinfo *qi) 
{ 
	qi->next = lds; 
	lds = qi; 
	if(qi->reset) 
		(*qi->reset)(); 
} 
 
/* 
1990/0227    
 *  allocate a block 
 */ 
static int 
1990/0907/sys/src/9/port/stream.c:169,1751990/0911/sys/src/9/port/stream.c:119,124
1990/0227    
{ 
	Block *bp; 
	Bclass *bcp; 
1990/0322    
	int loop=0; 
1990/0227    
 
	/* 
	 *  map size to class 
1990/0907/sys/src/9/port/stream.c:183,1921990/0911/sys/src/9/port/stream.c:132,137
1990/0227    
	lock(bcp); 
	while(bcp->first == 0){ 
		unlock(bcp); 
1990/0403    
		if(loop++ == 10){ 
1990/0331    
			dumpqueues(); 
1990/0403    
			print("waiting for blocks\n"); 
1990/0331    
		} 
1990/03292    
		qlock(bcp); 
1990/0322    
		tsleep(&bcp->r, isblock, (void *)bcp, 250); 
1990/03292    
		qunlock(bcp); 
1990/0907/sys/src/9/port/stream.c:242,2471990/0911/sys/src/9/port/stream.c:187,212
1990/0227    
} 
 
/* 
1990/0911    
 *  pad a block to the front with n bytes 
 */ 
Block * 
padb(Block *bp, int n) 
{ 
	Block *nbp; 
 
	if(bp->base && bp->rptr-bp->base>=n){ 
		bp->rptr -= n; 
		return bp; 
	} else { 
		nbp = allocb(n); 
		nbp->wptr = nbp->lim; 
		nbp->rptr = nbp->wptr - n; 
		nbp->next = bp; 
		return nbp; 
	} 
}  
 
/* 
1990/0227    
 *  allocate a pair of queues.  flavor them with the requested put routines. 
 *  the `QINUSE' flag on the read side is the only one used. 
 */ 
1990/0907/sys/src/9/port/stream.c:572,5841990/0911/sys/src/9/port/stream.c:537,549
1990/0227    
static Qinfo * 
qinfofind(char *name) 
{ 
	Qinfo **qip; 
1990/0911    
	Qinfo *qi; 
1990/0227    
 
	if(name == 0) 
		error(0, Ebadld); 
	for(qip = lds; *qip; qip++) 
		if(strcmp((*qip)->name, name)==0) 
			return *qip; 
1990/0911    
	for(qi = lds; qi; qi = qi->next) 
		if(strcmp(qi->name, name)==0) 
			return qi; 
1990/0227    
	error(0, Ebadld); 
} 
 
1990/0907/sys/src/9/port/stream.c:1070,10841990/0911/sys/src/9/port/stream.c:1035,1050
1990/0227    
	long rem; 
	int i; 
 
1990/0911    
	s = c->stream; 
 
1990/0227    
	/* 
	 *  one writer at a time 
	 */ 
	s = c->stream; 
	qlock(&s->wrlock); 
	if(waserror()){ 
		qunlock(&s->wrlock); 
		nexterror(); 
	} 
1990/0911    
	 */ 
1990/0227    
 
	/* 
	 *  decode the qid 
1990/0907/sys/src/9/port/stream.c:1088,10961990/0911/sys/src/9/port/stream.c:1054,1060
1990/0227    
		break; 
	case Sctlqid: 
		n = streamctlwrite(s, a, n); 
		qunlock(&s->wrlock); 
		poperror(); 
		return n; 
1990/0911    
		goto out; 
1990/0227    
	default: 
		panic("bad stream qid\n"); 
	} 
1990/0907/sys/src/9/port/stream.c:1139,11461990/0911/sys/src/9/port/stream.c:1103,1111
1990/0227    
			} 
		} 
	} 
	qunlock(&s->wrlock); 
	poperror(); 
1990/0911    
out: 
/*	qunlock(&s->wrlock); 
	poperror(); /**/ 
1990/0227    
	return n; 
1990/0312    
} 
 
1990/0907/sys/src/9/port/stream.c:1196,11991990/0911/sys/src/9/port/stream.c:1161,1213
1990/0801    
 
	devdir(c, c->qid, name, n, 0, &dir); 
	convD2M(&dir, db); 
1990/0911    
} 
 
/* 
 *  Dump all block information of how many blocks are in which queues 
 */ 
void 
dumpblocks(Queue *q, char c) 
{ 
	Block *bp; 
	uchar *cp; 
 
	lock(q); 
	for(bp = q->first; bp; bp = bp->next){ 
		print("%c%d%c", c, bp->wptr-bp->rptr, (bp->flags&S_DELIM)); 
		for(cp = bp->rptr; cp<bp->wptr && cp<bp->rptr+10; cp++) 
			print(" %uo", *cp); 
		print("\n"); 
	} 
	unlock(q); 
} 
 
void 
dumpqueues(void) 
{ 
	Queue *q; 
	int count; 
	Block *bp; 
	Bclass *bcp; 
 
	print("\n"); 
	for(q = qlist; q < qlist + conf.nqueue; q++, q++){ 
		if(!(q->flag & QINUSE)) 
			continue; 
		print("%s %ux  R n %d l %d f %ux r %ux", q->info->name, q, q->nb, 
			q->len, q->flag, &(q->r)); 
		print("  W n %d l %d f %ux r %ux\n", WR(q)->nb, WR(q)->len, WR(q)->flag, 
			&(WR(q)->r)); 
		dumpblocks(q, 'R'); 
		dumpblocks(WR(q), 'W'); 
	} 
	print("\n"); 
	for(bcp=bclass; bcp<&bclass[Nclass]; bcp++){ 
		lock(bcp); 
		for(count = 0, bp = bcp->first; bp; count++, bp = bp->next) 
			; 
		unlock(bcp); 
		print("%d blocks of size %d\n", count, bcp->size); 
	} 
	print("\n"); 
1990/0227    
} 


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