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

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

1990/03013/sys/src/9/port/stream.c:7,181990/0312/sys/src/9/port/stream.c:7,30 (short | long | prev | next)
1990/0227    
#include	"errno.h" 
#include	"devtab.h" 
 
1990/0312    
/* 
 *  process end line discipline 
 */ 
1990/0227    
static void stputq(Queue*, Block*); 
Qinfo procinfo = { stputq, nullput, 0, 0, "process" } ; 
extern Qinfo noetherinfo; 
1990/0312    
Qinfo procinfo = { stputq, nullput, 0, 0, "process" }; 
1990/0227    
 
1990/0312    
/* 
 *  line disciplines that can be pushed 
 * 
 *  WARNING: this table should be the result of configuration 
 */ 
extern Qinfo noetherinfo; 
extern Qinfo dkmuxinfo; 
extern Qinfo urpinfo; 
1990/0227    
static Qinfo *lds[] = { 
	&noetherinfo, 
1990/0312    
	&dkmuxinfo, 
	&urpinfo, 
1990/0227    
	0 
}; 
 
1990/03013/sys/src/9/port/stream.c:34,401990/0312/sys/src/9/port/stream.c:46,54
1990/0227    
 */ 
typedef struct { 
	int	size; 
	Queue; 
1990/0312    
	Blist; 
	QLock;		/* qlock for sleepers on r */ 
	Rendez	r;	/* sleep here waiting for blocks */ 
1990/0227    
} Bclass; 
Bclass bclass[Nclass]={ 
	{ 0 }, 
1990/03013/sys/src/9/port/stream.c:108,1141990/0312/sys/src/9/port/stream.c:122,130
1990/0227    
	while(bcp->first == 0){ 
		unlock(bcp); 
		print("waiting for blocks\n"); 
1990/0312    
		qlock(bcp); 
1990/0227    
		sleep(&bcp->r, isblock, (void *)bcp); 
1990/0312    
		qunlock(bcp); 
1990/0227    
		lock(bcp); 
	} 
	bp = bcp->first; 
1990/03013/sys/src/9/port/stream.c:128,1521990/0312/sys/src/9/port/stream.c:144,176
1990/0227    
} 
 
/* 
 *  Free a block.  Poison its pointers so that someone trying to access 
 *  it after freeing will cause a dump. 
1990/0312    
 *  Free a block (or list of blocks).  Poison its pointers so that 
 *  someone trying to access it after freeing will cause a dump. 
1990/0227    
 */ 
void 
freeb(Block *bp) 
{ 
	Bclass *bcp; 
1990/0312    
	int tries; 
1990/0227    
 
	bcp = &bclass[bp->flags & S_CLASS]; 
	bp->rptr = bp->wptr = 0; 
	lock(bcp); 
1990/0312    
	bp->rptr = bp->wptr = 0; 
1990/0227    
	if(bcp->first) 
		bcp->last->next = bp; 
	else 
		bcp->first = bp; 
1990/0312    
	tries = 0; 
	while(bp->next){ 
		if(++tries > 10){ 
			dumpstack(); 
			panic("freeb"); 
		} 
		bp = bp->next; 
	} 
1990/0227    
	bcp->last = bp; 
	bp->next = 0; 
	wakeup(&bcp->r); 
	unlock(bcp); 
1990/0312    
	wakeup(&bcp->r); 
1990/0227    
} 
 
/* 
1990/03013/sys/src/9/port/stream.c:269,2791990/0312/sys/src/9/port/stream.c:293,303
1990/0227    
		q->last->next = bp; 
	else 
		q->first = bp; 
	q->len += bp->wptr - bp->rptr; 
1990/0312    
	q->len += BLEN(bp); 
1990/0227    
	delim = bp->flags & S_DELIM; 
	while(bp->next) { 
		bp = bp->next; 
		q->len += bp->wptr - bp->rptr; 
1990/0312    
		q->len += BLEN(bp); 
1990/0227    
		delim |= bp->flags & S_DELIM; 
	} 
	q->last = bp; 
1990/03013/sys/src/9/port/stream.c:292,3061990/0312/sys/src/9/port/stream.c:316,329
1990/0227    
		q->last->next = bp; 
	else 
		q->first = bp; 
	q->len += bp->wptr - bp->rptr; 
1990/0312    
	q->len += BLEN(bp); 
1990/0227    
	delim = bp->flags & S_DELIM; 
	while(bp->next) { 
		bp = bp->next; 
		q->len += bp->wptr - bp->rptr; 
1990/0312    
		q->len += BLEN(bp); 
1990/0227    
		delim |= bp->flags & S_DELIM; 
	} 
	q->last = bp; 
	bp->next = 0; 
	return delim; 
} 
 
1990/03013/sys/src/9/port/stream.c:307,3131990/0312/sys/src/9/port/stream.c:330,336
1990/0227    
/* 
 *  add a block to the start of a queue  
 */ 
static void 
1990/0312    
void 
1990/0227    
putbq(Blist *q, Block *bp) 
{ 
	lock(q); 
1990/03013/sys/src/9/port/stream.c:316,3271990/0312/sys/src/9/port/stream.c:339,350
1990/0227    
	else 
		q->last = bp; 
	q->first = bp; 
	q->len += bp->wptr - bp->rptr; 
1990/0312    
	q->len += BLEN(bp); 
1990/0227    
	unlock(q); 
} 
 
/* 
 *  remove the first block from a queue  
1990/0312    
 *  remove the first block from a queue 
1990/0227    
 */ 
Block * 
getq(Queue *q) 
1990/03013/sys/src/9/port/stream.c:334,3401990/0312/sys/src/9/port/stream.c:357,363
1990/0227    
		q->first = bp->next; 
		if(q->first == 0) 
			q->last = 0; 
		q->len -= bp->wptr - bp->rptr; 
1990/0312    
		q->len -= BLEN(bp); 
1990/0227    
		if((q->flag&QHIWAT) && q->len < Streamhi/2){ 
			wakeup(&q->other->next->other->r); 
			q->flag &= ~QHIWAT; 
1990/03013/sys/src/9/port/stream.c:344,3491990/0312/sys/src/9/port/stream.c:367,376
1990/0227    
	unlock(q); 
	return bp; 
} 
1990/0312    
 
/* 
 *  remove the first block from a list of blocks 
 */ 
1990/0227    
Block * 
getb(Blist *q) 
{ 
1990/03013/sys/src/9/port/stream.c:354,3601990/0312/sys/src/9/port/stream.c:381,387
1990/0227    
		q->first = bp->next; 
		if(q->first == 0) 
			q->last = 0; 
		q->len -= bp->wptr - bp->rptr; 
1990/0312    
		q->len -= BLEN(bp); 
1990/0227    
		bp->next = 0; 
	} 
	return bp; 
1990/03013/sys/src/9/port/stream.c:361,3661990/0312/sys/src/9/port/stream.c:388,467
1990/0227    
} 
 
/* 
1990/0312    
 *  make sure the first block has n bytes 
 */ 
Block * 
pullup(Block *bp, int n) 
{ 
	Block *nbp; 
	int i; 
 
	/* 
	 *  this should almost always be true, the rest it 
	 *  just for to avoid every caller checking. 
	 */ 
	if(BLEN(bp) >= n) 
		return bp; 
 
	/* 
	 *  if not enough room in the first block, 
	 *  add another to the front of the list. 
	if(bp->lim - bp->rptr < n){ 
		nbp = allocb(n); 
		nbp->next = bp; 
		bp = nbp; 
	} 
 
	/* 
	 *  copy bytes from the trailing blocks into the first 
	 */ 
	n -= BLEN(bp); 
	while(nbp = bp->next){ 
		i = BLEN(nbp); 
		if(i > n) { 
			memcpy(bp->wptr, nbp->rptr, n); 
			bp->wptr += n; 
			nbp->rptr += n; 
			return bp; 
		} else { 
			memcpy(bp->wptr, nbp->rptr, i); 
			bp->wptr += i; 
			bp->next = nbp->next; 
			nbp->next = 0; 
			freeb(nbp); 
		} 
	} 
	freeb(bp); 
	return 0; 
} 
 
/* 
 *  grow the front of a list of blocks by n bytes 
 */ 
Block * 
prepend(Block *bp, int n) 
{ 
	Block *nbp; 
 
	if(bp->base && (bp->rptr - bp->base)>=n){ 
		/* 
		 *  room for channel number in first block of message 
		 */ 
		bp->rptr -= n; 
		return bp; 
	} else { 
		/* 
		 *  make new block, put message number at end 
		 */ 
		nbp = allocb(2); 
		nbp->next = bp; 
		nbp->wptr = nbp->lim; 
		nbp->rptr = nbp->wptr - n; 
		return nbp; 
	} 
} 
 
/* 
1990/0227    
 *  put a block into the bit bucket 
 */ 
void 
1990/03013/sys/src/9/port/stream.c:415,4211990/0312/sys/src/9/port/stream.c:516,522
1990/0227    
	int len; 
 
	len = strlen(name); 
	if(bp->wptr - bp->rptr < len) 
1990/0312    
	if(BLEN(bp) < len) 
1990/0227    
		return 0; 
	if(strncmp(name, (char *)bp->rptr, len)==0){ 
		if(bp->rptr[len] == ' ') 
1990/03013/sys/src/9/port/stream.c:622,6271990/0312/sys/src/9/port/stream.c:723,729
1990/0227    
		freeb(bp); 
		q->flag |= QHUNGUP; 
		q->other->flag |= QHUNGUP; 
1990/0312    
		wakeup(&q->other->r); 
1990/0227    
	} else { 
		lock(q); 
		if(q->first) 
1990/03013/sys/src/9/port/stream.c:628,6351990/0312/sys/src/9/port/stream.c:730,741
1990/0227    
			q->last->next = bp; 
		else 
			q->first = bp; 
1990/0312    
		q->len += BLEN(bp); 
		while(bp->next) { 
			bp = bp->next; 
			q->len += BLEN(bp); 
		} 
1990/0227    
		q->last = bp; 
		q->len += bp->wptr - bp->rptr; 
		if(q->len >= Streamhi) 
			q->flag |= QHIWAT; 
		unlock(q); 
1990/03013/sys/src/9/port/stream.c:651,6581990/0312/sys/src/9/port/stream.c:757,763
1990/0227    
		n = i; 
	if(n<0) 
		return 0; 
	memcpy(buf + c->offset, str, n); 
	c->offset += n; 
1990/0312    
	memcpy(buf, str + c->offset, n); 
1990/0227    
	return n; 
} 
 
1990/03013/sys/src/9/port/stream.c:716,7221990/0312/sys/src/9/port/stream.c:821,827
1990/0227    
			continue; 
		} 
 
		i = bp->wptr - bp->rptr; 
1990/0312    
		i = BLEN(bp); 
1990/0227    
		if(i <= left){ 
			memcpy(buf, bp->rptr, i); 
			left -= i; 
1990/03013/sys/src/9/port/stream.c:806,8121990/0312/sys/src/9/port/stream.c:911,917
1990/0227    
 *  send the request as a single delimited block 
 */ 
long 
streamwrite(Chan *c, void *a, long n) 
1990/0312    
streamwrite(Chan *c, void *a, long n, int docopy) 
1990/0227    
{ 
	Stream *s; 
	Block *bp; 
1990/03013/sys/src/9/port/stream.c:846,8521990/0312/sys/src/9/port/stream.c:951,957
1990/0227    
	if(q->other->flag & QHUNGUP) 
		error(0, Ehungup); 
 
	if(GLOBAL(a) || n==0){ 
1990/0312    
	if((GLOBAL(a) && !docopy) || n==0){ 
1990/0227    
		/* 
		 *  `a' is global to the whole system, just create a 
		 *  pointer to it and pass it on. 
1990/03013/sys/src/9/port/stream.c:886,8891990/0312/sys/src/9/port/stream.c:991,1018
1990/0227    
	qunlock(&s->wrlock); 
	poperror(); 
	return n; 
1990/0312    
} 
 
/* 
 *  like andrew's getmfields but no hidden state 
 */ 
int 
getfields(char *lp,	/* to be parsed */ 
	char **fields,	/* where to put pointers */ 
	int n,		/* number of pointers */ 
	char sep	/* separator */ 
) 
{ 
	int i; 
 
	for(i=0; lp && *lp && i<n; i++){ 
		while(*lp == sep) 
			*lp++=0; 
		if(*lp == 0) 
			break; 
		fields[i]=lp; 
		while(*lp && *lp != sep) 
			lp++; 
	} 
	return i; 
1990/0227    
} 


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