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

1990/0801/port/devpipe.c (diff list | history)

1990/0227/sys/src/9/port/devpipe.c:129,1351990/0312/sys/src/9/port/devpipe.c:129,135 (short | long)
1990/0227    
		postnote(u->p, 1, "sys: write on closed pipe", NExit); 
		error(0, Egreg); 
	} 
	return streamwrite(c, va, n); 
1990/0312    
	return streamwrite(c, va, n, 0); 
1990/0227    
} 
 
void 
1990/0312/sys/src/9/port/devpipe.c:11,171990/0403/sys/src/9/port/devpipe.c:11,17 (short | long)
1990/0227    
static void pipeiput(Queue*, Block*); 
static void pipeoput(Queue*, Block*); 
static void pipestclose(Queue *); 
Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "process" }; 
1990/0403    
Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "pipe" }; 
1990/0227    
 
void 
pipeinit(void) 
1990/0312/sys/src/9/port/devpipe.c:154,1601990/0403/sys/src/9/port/devpipe.c:154,160
1990/0227    
static void 
pipeiput(Queue *q, Block *bp) 
{ 
	flowctl(q); 
1990/0403    
	FLOWCTL(q); 
1990/0227    
	PUTNEXT(q, bp); 
} 
 
1990/0312/sys/src/9/port/devpipe.c:168,1731990/0403/sys/src/9/port/devpipe.c:168,177
1990/0227    
	lock(q); 
	if(q->next) 
		pipeiput(q->next, bp); 
1990/0403    
	else{ 
		print("pipeoput losing block\n"); 
		freeb(bp); 
	} 
1990/0227    
	unlock(q); 
} 
 
1990/0403/sys/src/9/port/devpipe.c:129,1351990/0513/sys/src/9/port/devpipe.c:129,137 (short | long)
1990/0227    
		postnote(u->p, 1, "sys: write on closed pipe", NExit); 
		error(0, Egreg); 
	} 
1990/0312    
	return streamwrite(c, va, n, 0); 
1990/0513    
	n = streamwrite(c, va, n, 0); 
	poperror(); 
	return n; 
1990/0227    
} 
 
void 
1990/0513/sys/src/9/port/devpipe.c:92,981990/0617/sys/src/9/port/devpipe.c:92,97 (short | long)
1990/0227    
void 
pipecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	print("pipecreate\n"); 
	error(0, Egreg); 
} 
 
1990/0513/sys/src/9/port/devpipe.c:99,1051990/0617/sys/src/9/port/devpipe.c:98,103
1990/0227    
void 
piperemove(Chan *c) 
{ 
	print("piperemove\n"); 
	error(0, Egreg); 
} 
 
1990/0513/sys/src/9/port/devpipe.c:106,1131990/0617/sys/src/9/port/devpipe.c:104,110
1990/0227    
void 
pipewstat(Chan *c, char *db) 
{ 
	print("pipewstat\n"); 
	error(0, Egreg); 
1990/0617    
	error(0, Eperm); 
1990/0227    
} 
 
void 
1990/0617/sys/src/9/port/devpipe.c:32,371990/0629/sys/src/9/port/devpipe.c:32,39 (short | long)
1990/0227    
pipeattach(char *spec) 
{ 
	Chan *c; 
1990/0629    
	int i; 
 
1990/0227    
	/* 
	 *  make the first stream 
	 */ 
1990/0617/sys/src/9/port/devpipe.c:59,661990/0629/sys/src/9/port/devpipe.c:61,79
1990/0227    
	/* 
	 *  attach it to the first 
	 */ 
1990/0629    
	c->stream->devq->ptr = (Stream *)nc->stream; 
	nc->stream->devq->ptr = (Stream *)c->stream; 
1990/0227    
	c->stream->devq->other->next = nc->stream->devq; 
	nc->stream->devq->other->next = c->stream->devq; 
1990/0629    
 
	/* 
	 *  up the inuse count of each stream to reflect the 
	 *  pointer from the other stream. 
	 */ 
	if(streamenter(c->stream)<0) 
		panic("pipeattach"); 
	if(streamenter(nc->stream)<0) 
		panic("pipeattach"); 
1990/0227    
	return nc; 
} 
 
1990/0617/sys/src/9/port/devpipe.c:110,1161990/0629/sys/src/9/port/devpipe.c:123,139
1990/0227    
void 
pipeclose(Chan *c) 
{ 
	streamclose(c); 
1990/0629    
	Stream *other; 
 
	other = (Stream *)c->stream->devq->ptr; 
 
	if(waserror()){ 
		streamexit(other, 0); 
		nexterror(); 
	} 
	streamclose(c);		/* close this stream */ 
	streamexit(other, 0);	/* release stream for other half of pipe */ 
	poperror(); 
1990/0227    
} 
 
long 
1990/0617/sys/src/9/port/devpipe.c:164,1771990/0629/sys/src/9/port/devpipe.c:187,193
1990/0227    
static void 
pipeoput(Queue *q, Block *bp) 
{ 
	lock(q); 
	if(q->next) 
		pipeiput(q->next, bp); 
1990/0403    
	else{ 
		print("pipeoput losing block\n"); 
		freeb(bp); 
	} 
1990/0227    
	unlock(q); 
1990/0629    
	PUTNEXT(q, bp); 
1990/0227    
} 
 
/* 
1990/0617/sys/src/9/port/devpipe.c:193,2211990/0629/sys/src/9/port/devpipe.c:209,215
1990/0227    
	 *  send a hangup 
	 */ 
	q = q->other; 
	lock(q); 
	if(q->next){ 
		bp = allocb(0); 
		bp->type = M_HANGUP; 
		pipeiput(q->next, bp); 
	} 
	unlock(q); 
                 
	/* 
	 *  disconnect (possible livelock?) 
	 */ 
	for(;;){ 
		lock(q); 
		if(q->next){ 
			if(!canlock(q->next->other)){ 
				unlock(q); 
				continue; 
			} 
			q->next->other->next = 0; 
			unlock(q->next->other); 
			q->next = 0; 
		} 
		unlock(q); 
		break; 
	} 
1990/0629    
	bp = allocb(0); 
	bp->type = M_HANGUP; 
	PUTNEXT(q, bp); 
1990/0227    
} 
1990/0629/sys/src/9/port/devpipe.c:87,961990/0801/sys/src/9/port/devpipe.c:87,93 (short | long)
1990/0227    
void 
pipestat(Chan *c, char *db) 
{ 
	Dir dir; 
                 
	devdir(c, c->qid, "pipe", 0, 0, &dir); 
	convD2M(&dir, db); 
1990/0801    
	streamstat(c, db, "pipe"); 
1990/0227    
} 
 
Chan * 
1990/0801/sys/src/9/port/devpipe.c:8,451990/1009/sys/src/9/port/devpipe.c:8,84 (short | long)
1990/0227    
#include	"devtab.h" 
#include	"fcall.h" 
 
1990/1009    
typedef struct Pipe	Pipe; 
 
struct Pipe 
{ 
	Ref; 
	int	debug; 
	Pipe	*next; 
}; 
 
struct Pipealloc 
{ 
	Lock; 
	Pipe *pipe; 
	Pipe *free; 
} pipealloc; 
 
1990/0227    
static void pipeiput(Queue*, Block*); 
static void pipeoput(Queue*, Block*); 
static void pipestclose(Queue *); 
1990/0403    
Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "pipe" }; 
1990/0227    
 
1990/1009    
Dirtab pipedir[]={ 
	"data",		Sdataqid,	0,			0600, 
	"ctl",		Sctlqid,	0,			0600, 
	"data1",	Sdataqid,	0,			0600, 
	"ctl1",		Sctlqid,	0,			0600, 
}; 
#define NPIPEDIR 4 
 
1990/0227    
void 
pipeinit(void) 
{ 
} 
 
1990/1009    
/* 
 *  allocate structures for conf.npipe pipes 
 */ 
1990/0227    
void 
pipereset(void) 
{ 
1990/1009    
	Pipe *p, *ep; 
 
	pipealloc.pipe = ialloc(conf.npipe * sizeof(Pipe), 0); 
	ep = &pipealloc.pipe[conf.npipe-1]; 
	for(p = pipealloc.pipe; p < ep; p++) 
		p->next = p+1; 
	pipealloc.free = pipealloc.pipe; 
1990/0227    
} 
 
/* 
 *  allocate both streams 
 * 
 *  a subsequent clone will get them the second stream 
1990/1009    
 *  create a pipe, no streams are created until an open 
1990/0227    
 */ 
Chan* 
pipeattach(char *spec) 
{ 
1990/1009    
	Pipe *p; 
1990/0227    
	Chan *c; 
1990/0629    
	int i; 
 
1990/0227    
	/* 
	 *  make the first stream 
	 */ 
	c = devattach('|', spec); 
	c->qid = STREAMQID(0, Sdataqid); 
	streamnew(c, &pipeinfo); 
1990/1009    
 
	lock(&pipealloc); 
	if(pipealloc.free == 0){ 
		unlock(&pipealloc); 
		error(0, Enopipe); 
	} 
	p = pipealloc.free; 
	pipealloc.free = p->next; 
	p->ref = 1; 
	unlock(&pipealloc); 
 
	c->qid = CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0); 
1990/0227    
	return c; 
} 
 
1990/0801/sys/src/9/port/devpipe.c:46,871990/1009/sys/src/9/port/devpipe.c:85,118
1990/0227    
Chan* 
pipeclone(Chan *c, Chan *nc) 
{ 
	/* 
	 *  make the second stream  
	 */ 
1990/1009    
	Pipe *p; 
 
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/0227    
	nc = devclone(c, nc); 
	if(waserror()){ 
		close(nc); 
		nexterror(); 
	} 
	nc->qid = STREAMQID(1, Sdataqid); 
	streamnew(nc, &pipeinfo); 
	poperror(); 
1990/1009    
	incref(p); 
	return nc; 
} 
1990/0227    
 
	/* 
	 *  attach it to the first 
	 */ 
1990/0629    
	c->stream->devq->ptr = (Stream *)nc->stream; 
	nc->stream->devq->ptr = (Stream *)c->stream; 
1990/0227    
	c->stream->devq->other->next = nc->stream->devq; 
	nc->stream->devq->other->next = c->stream->devq; 
1990/1009    
int 
pipegen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) 
{ 
	int id; 
1990/0629    
 
	/* 
	 *  up the inuse count of each stream to reflect the 
	 *  pointer from the other stream. 
	 */ 
	if(streamenter(c->stream)<0) 
		panic("pipeattach"); 
	if(streamenter(nc->stream)<0) 
		panic("pipeattach"); 
1990/0227    
	return nc; 
1990/1009    
	id = STREAMID(c->qid); 
	if(i > 1) 
		id++; 
	if(tab==0 || i>=ntab) 
		return -1; 
	tab += i; 
	devdir(c, STREAMQID(id, tab->qid), tab->name, tab->length, tab->perm, dp); 
	return 1; 
1990/0227    
} 
 
1990/1009    
 
1990/0227    
int 
pipewalk(Chan *c, char *name) 
{ 
	print("pipewalk\n"); 
	error(0, Egreg); 
1990/1009    
	return devwalk(c, name, pipedir, NPIPEDIR, pipegen); 
1990/0227    
} 
 
void 
1990/0801/sys/src/9/port/devpipe.c:90,991990/1009/sys/src/9/port/devpipe.c:121,180
1990/0801    
	streamstat(c, db, "pipe"); 
1990/0227    
} 
 
1990/1009    
/* 
 *  if the stream doesn't exist, create it 
 */ 
1990/0227    
Chan * 
pipeopen(Chan *c, int omode) 
{ 
	c->mode = omode; 
1990/1009    
	Pipe *p; 
	Stream *local, *remote; 
 
	if(CHDIR & c->qid){ 
		if(omode != OREAD) 
			error(0, Ebadarg); 
		c->mode = omode; 
		c->flag |= COPEN; 
		c->offset = 0; 
		return c; 
	} 
 
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
	remote = 0; 
	if(waserror()){ 
		unlock(p); 
		if(remote) 
			streamclose1(remote); 
		nexterror(); 
	} 
	lock(p); 
	streamopen(c, &pipeinfo); 
	local = c->stream; 
	if(local->devq->ptr == 0){ 
		/* 
		 *  First stream opened, create the other end also 
		 */ 
		remote = streamnew(c->type, c->dev, STREAMID(c->qid)^1, &pipeinfo, 1); 
 
		/* 
		 *  connect the device ends of both streams 
		 */ 
		local->devq->ptr = remote; 
		remote->devq->ptr = local; 
		local->devq->other->next = remote->devq; 
		remote->devq->other->next = local->devq; 
 
		/* 
		 *  increment the inuse count to reflect the 
		 *  pointer from the other stream. 
		 */ 
		if(streamenter(local)<0) 
			panic("pipeattach"); 
	} 
	unlock(p); 
	poperror(); 
 
	c->mode = omode&~OTRUNC; 
1990/0227    
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
1990/0801/sys/src/9/port/devpipe.c:118,1441990/1009/sys/src/9/port/devpipe.c:199,254
1990/0227    
} 
 
void 
1990/1009    
pipeexit(Pipe *p) 
{ 
	decref(p); 
	if(p->ref <= 0){ 
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
} 
 
void 
1990/0227    
pipeclose(Chan *c) 
{ 
1990/0629    
	Stream *other; 
1990/1009    
	Stream *remote; 
	Stream *local; 
	Pipe *p; 
1990/0629    
 
	other = (Stream *)c->stream->devq->ptr; 
1990/1009    
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/0629    
 
	if(waserror()){ 
		streamexit(other, 0); 
		nexterror(); 
1990/1009    
	/* 
	 *  take care of assosiated streams 
	 */ 
	if(local = c->stream){ 
		remote = (Stream *)c->stream->devq->ptr; 
		if(waserror()){ 
			streamexit(remote, 0); 
			pipeexit(p); 
			nexterror(); 
		} 
		streamclose(c);		/* close this stream */ 
		streamexit(remote, 0);	/* release stream for other half of pipe */ 
		poperror(); 
1990/0629    
	} 
	streamclose(c);		/* close this stream */ 
	streamexit(other, 0);	/* release stream for other half of pipe */ 
	poperror(); 
1990/1009    
	pipeexit(p); 
1990/0227    
} 
 
long 
piperead(Chan *c, void *va, long n) 
{ 
	return streamread(c, va, n); 
1990/1009    
	if(CHDIR&c->qid) 
		return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen); 
	else 
		return streamread(c, va, n); 
1990/0227    
} 
 
1990/1009    
/* 
 *  a write to a closed pipe causes a note to be sent to 
 *  the process. 
 */ 
1990/0227    
long 
pipewrite(Chan *c, void *va, long n) 
{ 
1990/1009/sys/src/9/port/devpipe.c:201,2081990/1011/sys/src/9/port/devpipe.c:201,209 (short | long)
1990/0227    
void 
1990/1009    
pipeexit(Pipe *p) 
{ 
	decref(p); 
	if(p->ref <= 0){ 
1990/1011    
	if(decref(p) < 0) 
		panic("pipeexit"); 
	if(p->ref == 0){ 
1990/1009    
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
1990/1009/sys/src/9/port/devpipe.c:220,2371990/1011/sys/src/9/port/devpipe.c:221,232
1990/1009    
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/0629    
 
1990/1009    
	/* 
	 *  take care of assosiated streams 
1990/1011    
	 *  take care of associated streams 
1990/1009    
	 */ 
	if(local = c->stream){ 
		remote = (Stream *)c->stream->devq->ptr; 
		if(waserror()){ 
			streamexit(remote, 0); 
			pipeexit(p); 
			nexterror(); 
		} 
		streamclose(c);		/* close this stream */ 
		streamexit(remote, 0);	/* release stream for other half of pipe */ 
		poperror(); 
1990/0629    
	} 
1990/1009    
	pipeexit(p); 
1990/0227    
} 
1990/1011/sys/src/9/port/devpipe.c:75,811990/1013/sys/src/9/port/devpipe.c:75,82 (short | long)
1990/1009    
	} 
	p = pipealloc.free; 
	pipealloc.free = p->next; 
	p->ref = 1; 
1990/1013    
	if(incref(p) != 1) 
		panic("pipeattach"); 
1990/1009    
	unlock(&pipealloc); 
 
	c->qid = CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0); 
1990/1011/sys/src/9/port/devpipe.c:89,951990/1013/sys/src/9/port/devpipe.c:90,97
1990/1009    
 
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/0227    
	nc = devclone(c, nc); 
1990/1009    
	incref(p); 
1990/1013    
	if(incref(p) <= 1) 
		panic("pipeclone"); 
1990/1009    
	return nc; 
} 
1990/0227    
 
1990/1013/sys/src/9/port/devpipe.c:75,821990/1104/sys/src/9/port/devpipe.c:75,84 (short | long)
1990/1009    
	} 
	p = pipealloc.free; 
	pipealloc.free = p->next; 
1990/1013    
	if(incref(p) != 1) 
1990/1104    
	if(++(p->ref) != 1){ 
		print("pipattach pipe half %d ref %d\n", p - pipealloc.pipe, p->ref); 
1990/1013    
		panic("pipeattach"); 
1990/1104    
	} 
1990/1009    
	unlock(&pipealloc); 
 
	c->qid = CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0); 
1990/1013/sys/src/9/port/devpipe.c:201,2191990/1104/sys/src/9/port/devpipe.c:203,208
1990/0227    
} 
 
void 
1990/1009    
pipeexit(Pipe *p) 
{ 
1990/1011    
	if(decref(p) < 0) 
		panic("pipeexit"); 
	if(p->ref == 0){ 
1990/1009    
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
} 
                 
void 
1990/0227    
pipeclose(Chan *c) 
{ 
1990/1009    
	Stream *remote; 
1990/1013/sys/src/9/port/devpipe.c:230,2361990/1104/sys/src/9/port/devpipe.c:219,235
1990/1009    
		streamclose(c);		/* close this stream */ 
		streamexit(remote, 0);	/* release stream for other half of pipe */ 
1990/0629    
	} 
1990/1009    
	pipeexit(p); 
1990/1104    
 
	lock(p); 
	if(--(p->ref) < 0) 
		panic("pipeexit"); 
	if(p->ref == 0){ 
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
	unlock(p); 
1990/0227    
} 
 
long 
1990/1104/sys/src/9/port/devpipe.c:27,331990/1113/sys/src/9/port/devpipe.c:27,40 (short | long)
1990/0227    
static void pipeiput(Queue*, Block*); 
static void pipeoput(Queue*, Block*); 
static void pipestclose(Queue *); 
1990/0403    
Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "pipe" }; 
1990/1113    
Qinfo pipeinfo = 
{ 
	pipeiput, 
	pipeoput, 
	0, 
	pipestclose, 
	"pipe" 
}; 
1990/0227    
 
1990/1009    
Dirtab pipedir[]={ 
	"data",		Sdataqid,	0,			0600, 
1990/1113/sys/src/9/port/devpipe.c:82,911990/1115/sys/src/9/port/devpipe.c:82,89 (short | long)
1990/1009    
	} 
	p = pipealloc.free; 
	pipealloc.free = p->next; 
1990/1104    
	if(++(p->ref) != 1){ 
		print("pipattach pipe half %d ref %d\n", p - pipealloc.pipe, p->ref); 
1990/1115    
	if(incref(p) != 1) 
1990/1013    
		panic("pipeattach"); 
1990/1104    
	} 
1990/1009    
	unlock(&pipealloc); 
 
	c->qid = CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0); 
1990/1113/sys/src/9/port/devpipe.c:210,2151990/1115/sys/src/9/port/devpipe.c:208,226
1990/0227    
} 
 
void 
1990/1115    
pipeexit(Pipe *p) 
{ 
	if(decref(p) < 0) 
		panic("pipeexit"); 
	if(p->ref == 0){ 
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
} 
 
void 
1990/0227    
pipeclose(Chan *c) 
{ 
1990/1009    
	Stream *remote; 
1990/1113/sys/src/9/port/devpipe.c:217,2221990/1115/sys/src/9/port/devpipe.c:228,238
1990/1009    
	Pipe *p; 
1990/0629    
 
1990/1009    
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/1115    
	lock(p); 
	if(waserror()){ 
		unlock(p); 
		nexterror(); 
	} 
1990/0629    
 
1990/1009    
	/* 
1990/1011    
	 *  take care of associated streams 
1990/1113/sys/src/9/port/devpipe.c:226,2421990/1115/sys/src/9/port/devpipe.c:242,250
1990/1009    
		streamclose(c);		/* close this stream */ 
		streamexit(remote, 0);	/* release stream for other half of pipe */ 
1990/0629    
	} 
1990/1104    
                 
	lock(p); 
	if(--(p->ref) < 0) 
		panic("pipeexit"); 
	if(p->ref == 0){ 
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
	unlock(p); 
1990/1115    
	poperror(); 
	pipeexit(p); 
1990/0227    
} 
 
long 
1990/1115/sys/src/9/port/devpipe.c:179,1841990/11161/sys/src/9/port/devpipe.c:179,191 (short | long)
1990/1009    
		 */ 
		if(streamenter(local)<0) 
			panic("pipeattach"); 
1990/11161    
	} else { 
		/* 
		 *  increment the inuse count of the other 
		 *  stream 
		 */ 
		if(streamenter(local->devq->ptr)<0) 
			panic("pipeattach2"); 
1990/1009    
	} 
	unlock(p); 
	poperror(); 
1990/1115/sys/src/9/port/devpipe.c:208,2261990/11161/sys/src/9/port/devpipe.c:215,220
1990/0227    
} 
 
void 
1990/1115    
pipeexit(Pipe *p) 
{ 
	if(decref(p) < 0) 
		panic("pipeexit"); 
	if(p->ref == 0){ 
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
} 
                 
void 
1990/0227    
pipeclose(Chan *c) 
{ 
1990/1009    
	Stream *remote; 
1990/1115/sys/src/9/port/devpipe.c:228,2381990/11161/sys/src/9/port/devpipe.c:222,227
1990/1009    
	Pipe *p; 
1990/0629    
 
1990/1009    
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/1115    
	lock(p); 
	if(waserror()){ 
		unlock(p); 
		nexterror(); 
	} 
1990/0629    
 
1990/1009    
	/* 
1990/1011    
	 *  take care of associated streams 
1990/1115/sys/src/9/port/devpipe.c:242,2501990/11161/sys/src/9/port/devpipe.c:231,248
1990/1009    
		streamclose(c);		/* close this stream */ 
		streamexit(remote, 0);	/* release stream for other half of pipe */ 
1990/0629    
	} 
1990/1104    
	unlock(p); 
1990/1115    
	poperror(); 
	pipeexit(p); 
1990/11161    
 
	/* 
	 *  free the structure 
	 */ 
	if(decref(p) == 0){ 
		lock(&pipealloc); 
		p->next = pipealloc.free; 
		pipealloc.free = p; 
		unlock(&pipealloc); 
	} 
	if(p->ref < 0) 
		panic("pipeexit"); 
1990/0227    
} 
 
long 
1990/11161/sys/src/9/port/devpipe.c:178,1911990/1118/sys/src/9/port/devpipe.c:178,184 (short | long)
1990/1009    
		 *  pointer from the other stream. 
		 */ 
		if(streamenter(local)<0) 
			panic("pipeattach"); 
1990/11161    
	} else { 
		/* 
		 *  increment the inuse count of the other 
		 *  stream 
		 */ 
		if(streamenter(local->devq->ptr)<0) 
			panic("pipeattach2"); 
1990/1118    
			panic("pipeopen"); 
1990/1009    
	} 
	unlock(p); 
	poperror(); 
1990/11161/sys/src/9/port/devpipe.c:217,2241990/1118/sys/src/9/port/devpipe.c:210,215
1990/0227    
void 
pipeclose(Chan *c) 
{ 
1990/1009    
	Stream *remote; 
	Stream *local; 
	Pipe *p; 
1990/0629    
 
1990/1009    
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/11161/sys/src/9/port/devpipe.c:226,2361990/1118/sys/src/9/port/devpipe.c:217,224
1990/1009    
	/* 
1990/1011    
	 *  take care of associated streams 
1990/1009    
	 */ 
	if(local = c->stream){ 
		remote = (Stream *)c->stream->devq->ptr; 
1990/1118    
	if(c->stream) 
1990/1009    
		streamclose(c);		/* close this stream */ 
		streamexit(remote, 0);	/* release stream for other half of pipe */ 
1990/0629    
	} 
1990/11161    
 
	/* 
	 *  free the structure 
1990/11161/sys/src/9/port/devpipe.c:313,3181990/1118/sys/src/9/port/devpipe.c:301,307
1990/0227    
pipestclose(Queue *q) 
{ 
	Block *bp; 
1990/1118    
	Stream *remote; 
1990/0227    
 
	/* 
	 *  point to the bit-bucket and let any in-progress 
1990/11161/sys/src/9/port/devpipe.c:328,3311990/1118/sys/src/9/port/devpipe.c:317,326
1990/0629    
	bp = allocb(0); 
	bp->type = M_HANGUP; 
	PUTNEXT(q, bp); 
1990/1118    
 
	/* 
	 *  release stream for other half of pipe 
	 */ 
	remote = RD(q)->ptr; 
	streamexit(remote, 0); 
1990/0227    
} 
1990/1118/sys/src/9/port/devpipe.c:37,461990/11211/sys/src/9/port/devpipe.c:37,46 (short | long)
1990/1113    
}; 
1990/0227    
 
1990/1009    
Dirtab pipedir[]={ 
	"data",		Sdataqid,	0,			0600, 
	"ctl",		Sctlqid,	0,			0600, 
	"data1",	Sdataqid,	0,			0600, 
	"ctl1",		Sctlqid,	0,			0600, 
1990/11211    
	"data",		{Sdataqid},	0,			0600, 
	"ctl",		{Sctlqid},	0,			0600, 
	"data1",	{Sdataqid},	0,			0600, 
	"ctl1",		{Sctlqid},	0,			0600, 
1990/1009    
}; 
#define NPIPEDIR 4 
 
1990/1118/sys/src/9/port/devpipe.c:78,841990/11211/sys/src/9/port/devpipe.c:78,84
1990/1009    
	lock(&pipealloc); 
	if(pipealloc.free == 0){ 
		unlock(&pipealloc); 
		error(0, Enopipe); 
1990/11211    
		error(Enopipe); 
1990/1009    
	} 
	p = pipealloc.free; 
	pipealloc.free = p->next; 
1990/1118/sys/src/9/port/devpipe.c:86,921990/11211/sys/src/9/port/devpipe.c:86,92
1990/1013    
		panic("pipeattach"); 
1990/1009    
	unlock(&pipealloc); 
 
	c->qid = CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0); 
1990/11211    
	c->qid = (Qid){CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0), 0}; 
1990/0227    
	return c; 
} 
 
1990/1118/sys/src/9/port/devpipe.c:95,1011990/11211/sys/src/9/port/devpipe.c:95,101
1990/0227    
{ 
1990/1009    
	Pipe *p; 
 
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/11211    
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2]; 
1990/0227    
	nc = devclone(c, nc); 
1990/1013    
	if(incref(p) <= 1) 
		panic("pipeclone"); 
1990/1118/sys/src/9/port/devpipe.c:107,1191990/11211/sys/src/9/port/devpipe.c:107,119
1990/1009    
{ 
	int id; 
1990/0629    
 
1990/1009    
	id = STREAMID(c->qid); 
1990/11211    
	id = STREAMID(c->qid.path); 
1990/1009    
	if(i > 1) 
		id++; 
	if(tab==0 || i>=ntab) 
		return -1; 
	tab += i; 
	devdir(c, STREAMQID(id, tab->qid), tab->name, tab->length, tab->perm, dp); 
1990/11211    
	devdir(c, (Qid){STREAMQID(id, tab->qid.path),0}, tab->name, tab->length, tab->perm, dp); 
1990/1009    
	return 1; 
1990/0227    
} 
 
1990/1118/sys/src/9/port/devpipe.c:139,1471990/11211/sys/src/9/port/devpipe.c:139,147
1990/1009    
	Pipe *p; 
	Stream *local, *remote; 
 
	if(CHDIR & c->qid){ 
1990/11211    
	if(c->qid.path & CHDIR){ 
1990/1009    
		if(omode != OREAD) 
			error(0, Ebadarg); 
1990/11211    
			error(Ebadarg); 
1990/1009    
		c->mode = omode; 
		c->flag |= COPEN; 
		c->offset = 0; 
1990/1118/sys/src/9/port/devpipe.c:148,1541990/11211/sys/src/9/port/devpipe.c:148,154
1990/1009    
		return c; 
	} 
 
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/11211    
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2]; 
1990/1009    
	remote = 0; 
	if(waserror()){ 
		unlock(p); 
1990/1118/sys/src/9/port/devpipe.c:163,1691990/11211/sys/src/9/port/devpipe.c:163,169
1990/1009    
		/* 
		 *  First stream opened, create the other end also 
		 */ 
		remote = streamnew(c->type, c->dev, STREAMID(c->qid)^1, &pipeinfo, 1); 
1990/11211    
		remote = streamnew(c->type, c->dev, STREAMID(c->qid.path)^1, &pipeinfo, 1); 
1990/1009    
 
		/* 
		 *  connect the device ends of both streams 
1990/1118/sys/src/9/port/devpipe.c:192,2101990/11211/sys/src/9/port/devpipe.c:192,210
1990/0227    
void 
pipecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	error(0, Egreg); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
void 
piperemove(Chan *c) 
{ 
	error(0, Egreg); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
void 
pipewstat(Chan *c, char *db) 
{ 
1990/0617    
	error(0, Eperm); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
1990/1118/sys/src/9/port/devpipe.c:211,2241990/11211/sys/src/9/port/devpipe.c:211,228
1990/0227    
pipeclose(Chan *c) 
{ 
1990/1009    
	Pipe *p; 
1990/11211    
	Stream *remote; 
1990/0629    
 
1990/1009    
	p = &pipealloc.pipe[STREAMID(c->qid)/2]; 
1990/11211    
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2]; 
1990/0629    
 
1990/1009    
	/* 
1990/1011    
	 *  take care of associated streams 
1990/1009    
	 */ 
1990/1118    
	if(c->stream) 
1990/1009    
		streamclose(c);		/* close this stream */ 
1990/11211    
	if(c->stream){ 
		remote = c->stream->devq->ptr; 
		if(streamclose(c) <= 0) 
			streamexit(remote, 0); 
	} 
1990/11161    
 
	/* 
	 *  free the structure 
1990/1118/sys/src/9/port/devpipe.c:236,2421990/11211/sys/src/9/port/devpipe.c:240,246
1990/0227    
long 
piperead(Chan *c, void *va, long n) 
{ 
1990/1009    
	if(CHDIR&c->qid) 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/1009    
		return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen); 
	else 
		return streamread(c, va, n); 
1990/1118/sys/src/9/port/devpipe.c:251,2571990/11211/sys/src/9/port/devpipe.c:255,261
1990/0227    
{ 
	if(waserror()){ 
		postnote(u->p, 1, "sys: write on closed pipe", NExit); 
		error(0, Egreg); 
1990/11211    
		error(Egreg); 
1990/0227    
	} 
1990/0513    
	n = streamwrite(c, va, n, 0); 
	poperror(); 
1990/1118/sys/src/9/port/devpipe.c:258,2751990/11211/sys/src/9/port/devpipe.c:262,267
1990/0513    
	return n; 
1990/0227    
} 
 
void 
pipeuserstr(Error *e, char *buf) 
{ 
	consuserstr(e, buf); 
} 
                 
void 
pipeerrstr(Error *e, char *buf) 
{ 
	rooterrstr(e, buf); 
} 
                 
/* 
 *  stream stuff 
 */ 
1990/1118/sys/src/9/port/devpipe.c:317,3261990/11211/sys/src/9/port/devpipe.c:309,312
1990/0629    
	bp = allocb(0); 
	bp->type = M_HANGUP; 
	PUTNEXT(q, bp); 
1990/1118    
                 
	/* 
	 *  release stream for other half of pipe 
	 */ 
	remote = RD(q)->ptr; 
	streamexit(remote, 0); 
1990/0227    
} 
1990/11211/sys/src/9/port/devpipe.c:78,831991/0125/sys/src/9/port/devpipe.c:78,84 (short | long)
1990/1009    
	lock(&pipealloc); 
	if(pipealloc.free == 0){ 
		unlock(&pipealloc); 
1991/0125    
		close(c); 
1990/11211    
		error(Enopipe); 
1990/1009    
	} 
	p = pipealloc.free; 
1991/0125/sys/src/9/port/devpipe.c:307,3121991/0302/sys/src/9/port/devpipe.c:307,314 (short | long)
1990/0227    
	 *  send a hangup 
	 */ 
	q = q->other; 
1991/0302    
	if(q->next == 0) 
		return; 
1990/0629    
	bp = allocb(0); 
	bp->type = M_HANGUP; 
	PUTNEXT(q, bp); 
1991/0302/sys/src/9/port/devpipe.c:221,2281991/0314/sys/src/9/port/devpipe.c:221,230 (short | long)
1990/1009    
	 */ 
1990/11211    
	if(c->stream){ 
		remote = c->stream->devq->ptr; 
		if(streamclose(c) <= 0) 
			streamexit(remote, 0); 
1991/0314    
		if(streamclose(c) <= 0){ 
			if(remote) 
				streamexit(remote, 0); 
		} 
1990/11211    
	} 
1990/11161    
 
	/* 
1991/0314/sys/src/9/port/devpipe.c:241,2471991/0411/sys/src/9/port/devpipe.c:241,247 (short | long)
1990/0227    
} 
 
long 
piperead(Chan *c, void *va, long n) 
1991/0411    
piperead(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/1009    
		return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen); 
1991/0314/sys/src/9/port/devpipe.c:254,2601991/0411/sys/src/9/port/devpipe.c:254,260
1990/1009    
 *  the process. 
 */ 
1990/0227    
long 
pipewrite(Chan *c, void *va, long n) 
1991/0411    
pipewrite(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
	if(waserror()){ 
		postnote(u->p, 1, "sys: write on closed pipe", NExit); 
1991/0411/sys/src/9/port/devpipe.c:125,1301991/0419/sys/src/9/port/devpipe.c:125,136 (short | long)
1990/1009    
	return devwalk(c, name, pipedir, NPIPEDIR, pipegen); 
1990/0227    
} 
 
1991/0419    
Chan* 
pipeclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
 
1990/0227    
void 
pipestat(Chan *c, char *db) 
{ 
1991/0419/sys/src/9/port/devpipe.c:125,1361991/0427/sys/src/9/port/devpipe.c:125,130 (short | long)
1990/1009    
	return devwalk(c, name, pipedir, NPIPEDIR, pipegen); 
1990/0227    
} 
 
1991/0419    
Chan* 
pipeclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
                 
1990/0227    
void 
pipestat(Chan *c, char *db) 
{ 
1991/0427/sys/src/9/port/devpipe.c:275,2811991/0920/sys/src/9/port/devpipe.c:275,282 (short | long)
1990/0227    
static void 
pipeiput(Queue *q, Block *bp) 
{ 
1990/0403    
	FLOWCTL(q); 
1991/0920    
	if(bp->type != M_HANGUP) 
		FLOWCTL(q); 
1990/0227    
	PUTNEXT(q, bp); 
} 
 
1991/0920/sys/src/9/port/devpipe.c:114,1201991/1109/sys/src/9/port/devpipe.c:114,120 (short | long)
1990/1009    
	if(tab==0 || i>=ntab) 
		return -1; 
	tab += i; 
1990/11211    
	devdir(c, (Qid){STREAMQID(id, tab->qid.path),0}, tab->name, tab->length, tab->perm, dp); 
1991/1109    
	devdir(c, (Qid){STREAMQID(id, tab->qid.path),0}, tab->name, tab->length, eve, tab->perm, dp); 
1990/1009    
	return 1; 
1990/0227    
} 
 
1991/1109/sys/src/9/port/devpipe.c:193,1981991/1115/sys/src/9/port/devpipe.c:193,199 (short | long)
1990/0227    
void 
pipecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	USED(c, name, omode, perm); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
1991/1109/sys/src/9/port/devpipe.c:199,2041991/1115/sys/src/9/port/devpipe.c:200,206
1990/0227    
void 
piperemove(Chan *c) 
{ 
1991/1115    
	USED(c); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
1991/1109/sys/src/9/port/devpipe.c:205,2101991/1115/sys/src/9/port/devpipe.c:207,213
1990/0227    
void 
pipewstat(Chan *c, char *db) 
{ 
1991/1115    
	USED(c, db); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
1991/1115/sys/src/9/port/devpipe.c:13,191991/1227/sys/src/9/port/devpipe.c:13,19 (short | long)
1990/1009    
struct Pipe 
{ 
	Ref; 
	int	debug; 
1991/1227    
	QLock; 
1990/1009    
	Pipe	*next; 
}; 
 
1991/1115/sys/src/9/port/devpipe.c:88,931991/1227/sys/src/9/port/devpipe.c:88,94
1990/1009    
	unlock(&pipealloc); 
 
1990/11211    
	c->qid = (Qid){CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0), 0}; 
1991/1227    
	c->dev = 0; 
1990/0227    
	return c; 
} 
 
1991/1115/sys/src/9/port/devpipe.c:150,1701991/1227/sys/src/9/port/devpipe.c:151,168
1990/1009    
	} 
 
1990/11211    
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2]; 
1990/1009    
	remote = 0; 
	if(waserror()){ 
		unlock(p); 
		if(remote) 
			streamclose1(remote); 
1991/1227    
		qunlock(p); 
1990/1009    
		nexterror(); 
	} 
	lock(p); 
1991/1227    
	qlock(p); 
1990/1009    
	streamopen(c, &pipeinfo); 
	local = c->stream; 
	if(local->devq->ptr == 0){ 
		/* 
		 *  First stream opened, create the other end also 
1991/1227    
		 *  first open, create the other end also 
1990/1009    
		 */ 
1990/11211    
		remote = streamnew(c->type, c->dev, STREAMID(c->qid.path)^1, &pipeinfo, 1); 
1991/1227    
		remote = streamnew(c->type, c->dev, STREAMID(c->qid.path)^1, &pipeinfo,1); 
1990/1009    
 
		/* 
		 *  connect the device ends of both streams 
1991/1115/sys/src/9/port/devpipe.c:173,1871991/1227/sys/src/9/port/devpipe.c:171,183
1990/1009    
		remote->devq->ptr = local; 
		local->devq->other->next = remote->devq; 
		remote->devq->other->next = local->devq; 
                 
1991/1227    
	} else if(local->opens == 1){ 
1990/1009    
		/* 
		 *  increment the inuse count to reflect the 
		 *  pointer from the other stream. 
1991/1227    
		 *  keep other side around till last close of this side 
1990/1009    
		 */ 
		if(streamenter(local)<0) 
1990/1118    
			panic("pipeopen"); 
1991/1227    
		streamenter(local->devq->ptr); 
1990/1009    
	} 
	unlock(p); 
1991/1227    
	qunlock(p); 
1990/1009    
	poperror(); 
 
	c->mode = omode&~OTRUNC; 
1991/1115/sys/src/9/port/devpipe.c:220,2331991/1227/sys/src/9/port/devpipe.c:216,231
1990/11211    
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2]; 
1990/0629    
 
1990/1009    
	/* 
1990/1011    
	 *  take care of associated streams 
1991/1227    
	 *  take care of local and remote streams 
1990/1009    
	 */ 
1990/11211    
	if(c->stream){ 
1991/1227    
		qlock(p); 
1990/11211    
		remote = c->stream->devq->ptr; 
1991/0314    
		if(streamclose(c) <= 0){ 
1991/1227    
		if(streamclose(c) == 0){ 
1991/0314    
			if(remote) 
				streamexit(remote, 0); 
		} 
1991/1227    
		qunlock(p); 
1990/11211    
	} 
1990/11161    
 
	/* 
1991/1115/sys/src/9/port/devpipe.c:284,2911991/1227/sys/src/9/port/devpipe.c:282,288
1990/0227    
} 
 
/* 
 *  send the block to the other side without letting the connection 
 *  disappear in mid put. 
1991/1227    
 *  send the block to the other side 
1990/0227    
 */ 
static void 
pipeoput(Queue *q, Block *bp) 
1991/1115/sys/src/9/port/devpipe.c:300,3061991/1227/sys/src/9/port/devpipe.c:297,302
1990/0227    
pipestclose(Queue *q) 
{ 
	Block *bp; 
1990/1118    
	Stream *remote; 
1990/0227    
 
	/* 
	 *  point to the bit-bucket and let any in-progress 
Too many diffs (26 > 25). Stopping.


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