Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/gnot/devpipe.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname gnot/devpipe.c 1990/03091
## diff -e /dev/null /n/bootesdump/1990/03091/sys/src/9/68020/devpipe.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#include	"devtab.h"
#include	"fcall.h"

static void pipeiput(Queue*, Block*);
static void pipeoput(Queue*, Block*);
static void pipestclose(Queue *);
Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "process" };

void
pipeinit(void)
{
}

void
pipereset(void)
{
}

/*
 *  allocate both streams
 *
 *  a subsequent clone will get them the second stream
 */
Chan*
pipeattach(char *spec)
{
	Chan *c;
	/*
	 *  make the first stream
	 */
	c = devattach('|', spec);
	c->qid = STREAMQID(0, Sdataqid);
	streamnew(c, &pipeinfo);
	return c;
}

Chan*
pipeclone(Chan *c, Chan *nc)
{
	/*
	 *  make the second stream 
	 */
	nc = devclone(c, nc);
	if(waserror()){
		close(nc);
		nexterror();
	}
	nc->qid = STREAMQID(1, Sdataqid);
	streamnew(nc, &pipeinfo);
	poperror();

	/*
	 *  attach it to the first
	 */
	c->stream->devq->other->next = nc->stream->devq;
	nc->stream->devq->other->next = c->stream->devq;
	return nc;
}

int
pipewalk(Chan *c, char *name)
{
	print("pipewalk\n");
	error(0, Egreg);
}

void
pipestat(Chan *c, char *db)
{
	Dir dir;

	devdir(c, c->qid, "pipe", 0, 0, &dir);
	convD2M(&dir, db);
}

Chan *
pipeopen(Chan *c, int omode)
{
	c->mode = omode;
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

void
pipecreate(Chan *c, char *name, int omode, ulong perm)
{
	print("pipecreate\n");
	error(0, Egreg);
}

void
piperemove(Chan *c)
{
	print("piperemove\n");
	error(0, Egreg);
}

void
pipewstat(Chan *c, char *db)
{
	print("pipewstat\n");
	error(0, Egreg);
}

void
pipeclose(Chan *c)
{
	streamclose(c);
}

long
piperead(Chan *c, void *va, long n)
{
	return streamread(c, va, n);
}

long
pipewrite(Chan *c, void *va, long n)
{
	if(waserror()){
		postnote(u->p, 1, "sys: write on closed pipe", NExit);
		error(0, Egreg);
	}
	return streamwrite(c, va, n);
}

void
pipeuserstr(Error *e, char *buf)
{
	consuserstr(e, buf);
}

void
pipeerrstr(Error *e, char *buf)
{
	rooterrstr(e, buf);
}

/*
 *  stream stuff
 */
/*
 *  send a block up stream to the process.
 *  sleep untill there's room upstream.
 */
static void
pipeiput(Queue *q, Block *bp)
{
	flowctl(q);
	PUTNEXT(q, bp);
}

/*
 *  send the block to the other side without letting the connection
 *  disappear in mid put.
 */
static void
pipeoput(Queue *q, Block *bp)
{
	lock(q);
	if(q->next)
		pipeiput(q->next, bp);
	unlock(q);
}

/*
 *  send a hangup and disconnect the streams
 */
static void
pipestclose(Queue *q)
{
	Block *bp;

	/*
	 *  point to the bit-bucket and let any in-progress
	 *  write's finish.
	 */
	q->put = nullput;
	wakeup(&q->r);

	/*
	 *  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;
	}
}
.
## diffname gnot/devpipe.c 1990/0312
## diff -e /n/bootesdump/1990/03091/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0312/sys/src/9/68020/devpipe.c
132c
	return streamwrite(c, va, n, 0);
.
## diffname gnot/devpipe.c 1990/0331
## diff -e /n/bootesdump/1990/0312/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0331/sys/src/9/68020/devpipe.c
170a
	else{
		print("pipeoput losing block\n");
		freeb(bp);
	}
.
157c
	if(q->next->len >= Streamhi)
		flowctl(q);
.
14c
Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "pipe" };
.
## diffname gnot/devpipe.c 1990/0403
## diff -e /n/bootesdump/1990/0331/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0403/sys/src/9/68020/devpipe.c
157,158c
	FLOWCTL(q);
.
## diffname gnot/devpipe.c 1990/0513
## diff -e /n/bootesdump/1990/0403/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0513/sys/src/9/68020/devpipe.c
132c
	n = streamwrite(c, va, n, 0);
	poperror();
	return n;
.
## diffname gnot/devpipe.c 1990/0617
## diff -e /n/bootesdump/1990/0513/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0617/sys/src/9/68020/devpipe.c
109,110c
	error(0, Eperm);
.
102d
95d
## diffname gnot/devpipe.c 1990/0620
## diff -e /n/bootesdump/1990/0617/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0620/sys/src/9/68020/devpipe.c
201,219d
196d
167,174c
	PUTNEXT(q, bp);
.
113c
	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 */
.
63a

	/*
	 *  up the inuse count of each stream to reflect the
	 *  pointer from the other stream.
	 */
	streamenter(c->stream);
	streamenter(nc->stream);
.
61a
	c->stream->devq->ptr = (Stream *)nc->stream;
	nc->stream->devq->ptr = (Stream *)c->stream;
.
34a
	int i;

.
## diffname gnot/devpipe.c 1990/0621
## diff -e /n/bootesdump/1990/0620/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0621/sys/src/9/68020/devpipe.c
209,213c
	bp = allocb(0);
	bp->type = M_HANGUP;
	PUTNEXT(q, bp);
.
133a
	poperror();
.
73,74c
	if(streamenter(c->stream)<0)
		panic("pipeattach");
	if(streamenter(nc->stream)<0)
		panic("pipeattach");
.
## diffname gnot/devpipe.c 1990/0801
## diff -e /n/bootesdump/1990/0621/sys/src/9/68020/devpipe.c /n/bootesdump/1990/0801/sys/src/9/68020/devpipe.c
90,93c
	streamstat(c, db, "pipe");
.
## diffname gnot/devpipe.c 1990/1009
## diff -e /n/bootesdump/1990/0801/sys/src/9/68020/devpipe.c /n/bootesdump/1990/1009/sys/src/9/68020/devpipe.c
141a
/*
 *  a write to a closed pipe causes a note to be sent to
 *  the process.
 */
.
139c
	if(CHDIR&c->qid)
		return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);
	else
		return streamread(c, va, n);
.
131,133c
	pipeexit(p);
.
127,129c
	/*
	 *  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();
.
125c
	p = &pipealloc.pipe[STREAMID(c->qid)/2];
.
123c
	Stream *remote;
	Stream *local;
	Pipe *p;
.
120a
pipeexit(Pipe *p)
{
	decref(p);
	if(p->ref <= 0){
		lock(&pipealloc);
		p->next = pipealloc.free;
		pipealloc.free = p;
		unlock(&pipealloc);
	}
}

void
.
96c
	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;
.
92a
/*
 *  if the stream doesn't exist, create it
 */
.
83,84c
	return devwalk(c, name, pipedir, NPIPEDIR, pipegen);
.
79a

.
69,77c
	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;
.
61,67c
int
pipegen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
{
	int id;
.
53,59c
	incref(p);
	return nc;
}
.
49,51c
	Pipe *p;

	p = &pipealloc.pipe[STREAMID(c->qid)/2];
.
41,42c

	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);
.
37,39d
35d
33a
	Pipe *p;
.
27,29c
 *  create a pipe, no streams are created until an open
.
23a
	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;
.
20a
/*
 *  allocate structures for conf.npipe pipes
 */
.
15a
Dirtab pipedir[]={
	"data",		Sdataqid,	0,			0600,
	"ctl",		Sctlqid,	0,			0600,
	"data1",	Sdataqid,	0,			0600,
	"ctl1",		Sctlqid,	0,			0600,
};
#define NPIPEDIR 4

.
10a
typedef struct Pipe	Pipe;

struct Pipe
{
	Ref;
	int	debug;
	Pipe	*next;
};

struct Pipealloc
{
	Lock;
	Pipe *pipe;
	Pipe *free;
} pipealloc;

.
## diffname gnot/devpipe.c 1990/1011
## diff -e /n/bootesdump/1990/1009/sys/src/9/68020/devpipe.c /n/bootesdump/1990/1011/sys/src/9/68020/devpipe.c
234d
227,231d
223c
	 *  take care of associated streams
.
204,205c
	if(decref(p) < 0)
		panic("pipeexit");
	if(p->ref == 0){
.
## diffname gnot/devpipe.c 1990/1013
## diff -e /n/bootesdump/1990/1011/sys/src/9/68020/devpipe.c /n/bootesdump/1990/1013/sys/src/9/68020/devpipe.c
92c
	if(incref(p) <= 1)
		panic("pipeclone");
.
78c
	if(incref(p) != 1)
		panic("pipeattach");
.
## diffname gnot/devpipe.c 1990/1115
## diff -e /n/bootesdump/1990/1013/sys/src/9/68020/devpipe.c /n/bootesdump/1990/1115/sys/src/9/68020/devpipe.c
232a
	unlock(p);
	poperror();
.
223a
	lock(p);
	if(waserror()){
		unlock(p);
		nexterror();
	}
.
174c
			panic("pipeopen");
.
30c
Qinfo pipeinfo =
{
	pipeiput,
	pipeoput,
	0,
	pipestclose,
	"pipe"
};
.
## diffname gnot/devpipe.c 1990/11151
## diff -e /n/bootesdump/1990/1115/sys/src/9/68020/devpipe.c /n/bootesdump/1990/11151/sys/src/9/68020/devpipe.c
181c
			panic("pipeattach");
.
## diffname gnot/devpipe.c 1990/11161
## diff -e /n/bootesdump/1990/11151/sys/src/9/68020/devpipe.c /n/bootesdump/1990/11161/sys/src/9/68020/devpipe.c
245,247c

	/*
	 *  free the structure
	 */
	if(decref(p) == 0){
		lock(&pipealloc);
		p->next = pipealloc.free;
		pipealloc.free = p;
		unlock(&pipealloc);
	}
	if(p->ref < 0)
		panic("pipeexit");
.
231,235d
211,223d
## diffname gnot/devpipe.c 1990/1118
## diff -e /n/bootesdump/1990/11161/sys/src/9/68020/devpipe.c /n/bootesdump/1990/1118/sys/src/9/68020/devpipe.c
323a

	/*
	 *  release stream for other half of pipe
	 */
	remote = RD(q)->ptr;
	streamexit(remote, 0);
.
308a
	Stream *remote;
.
225,226d
222,223c
	if(c->stream)
.
213,214d
181c
			panic("pipeopen");
.
## diffname gnot/devpipe.c 1990/11211
## diff -e /n/bootesdump/1990/1118/sys/src/9/68020/devpipe.c /n/bootesdump/1990/11211/sys/src/9/68020/devpipe.c
320,325d
261,272d
254c
		error(Egreg);
.
239c
	if(c->qid.path & CHDIR)
.
220,221c
	if(c->stream){
		remote = c->stream->devq->ptr;
		if(streamclose(c) <= 0)
			streamexit(remote, 0);
	}
.
215c
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2];
.
213a
	Stream *remote;
.
207c
	error(Eperm);
.
201c
	error(Egreg);
.
195c
	error(Egreg);
.
166c
		remote = streamnew(c->type, c->dev, STREAMID(c->qid.path)^1, &pipeinfo, 1);
.
151c
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2];
.
144c
			error(Ebadarg);
.
142c
	if(c->qid.path & CHDIR){
.
116c
	devdir(c, (Qid){STREAMQID(id, tab->qid.path),0}, tab->name, tab->length, tab->perm, dp);
.
110c
	id = STREAMID(c->qid.path);
.
98c
	p = &pipealloc.pipe[STREAMID(c->qid.path)/2];
.
89c
	c->qid = (Qid){CHDIR|STREAMQID(2*(p - pipealloc.pipe), 0), 0};
.
81c
		error(Enopipe);
.
40,43c
	"data",		{Sdataqid},	0,			0600,
	"ctl",		{Sctlqid},	0,			0600,
	"data1",	{Sdataqid},	0,			0600,
	"ctl1",		{Sctlqid},	0,			0600,
.
## diffname gnot/devpipe.c 1990/1210 # deleted
## diff -e /n/bootesdump/1990/11211/sys/src/9/68020/devpipe.c /n/bootesdump/1990/1210/sys/src/9/68020/devpipe.c
1,312d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.