| plan 9 kernel history: overview | file list | diff list |
1993/0528/port/devpipe.c (diff list | history)
| port/devpipe.c on 1990/0227 | ||
| 1990/0227 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/0227 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1990/0227 | #include "devtab.h" | |
| 1993/0528 | #include "netif.h" | |
| 1990/0227 | ||
| 1990/1009 | typedef struct Pipe Pipe; struct Pipe { | |
| 1991/1227 | QLock; | |
| 1990/1009 | Pipe *next; | |
| 1993/0528 | int ref; | |
| 1992/0621 | ulong path; | |
| 1993/0528 | Queue *q[2]; int qref[2]; | |
| 1990/1009 | }; | |
| 1992/0621 | struct | |
| 1990/1009 | { Lock; | |
| 1992/0621 | Pipe *pipe; ulong path; | |
| 1990/1009 | } pipealloc; | |
| 1993/0528 | enum | |
| 1990/1113 | { | |
| 1993/0528 | Qdir, Qdata0, Qdata1, | |
| 1990/1113 | }; | |
| 1990/0227 | ||
| 1992/0621 | Dirtab pipedir[] = { | |
| 1993/0528 | "data", {Qdata0}, 0, 0600, "data1", {Qdata1}, 0, 0600, | |
| 1990/1009 | }; #define NPIPEDIR 4 | |
| 1990/0227 | void pipeinit(void) { } void pipereset(void) { } /* | |
| 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 | ||
| 1990/0227 | c = devattach('|', spec); | |
| 1993/0528 | p = malloc(sizeof(Pipe)); if(p == 0) exhausted("memory"); | |
| 1992/0621 | p->ref = 1; | |
| 1990/1009 | ||
| 1993/0528 | p->q[0] = qopen(64*1024, 0, 0); if(p->q[0] == 0){ free(p); exhausted("memory"); } p->q[0]->state &= ~Qmsg; p->q[1] = qopen(32*1024, 0, 0); if(p->q[1] == 0){ free(p->q[0]); free(p); exhausted("memory"); } p->q[1]->state &= ~Qmsg; | |
| 1990/1009 | lock(&pipealloc); | |
| 1992/0621 | p->path = ++pipealloc.path; p->next = pipealloc.pipe; pipealloc.pipe = p; | |
| 1990/1009 | unlock(&pipealloc); | |
| 1993/0528 | c->qid = (Qid){CHDIR|NETQID(2*p->path, Qdir), 0}; c->aux = p; | |
| 1991/1227 | c->dev = 0; | |
| 1990/0227 | return c; } Chan* pipeclone(Chan *c, Chan *nc) { | |
| 1990/1009 | Pipe *p; | |
| 1993/0528 | p = c->aux; | |
| 1990/0227 | nc = devclone(c, nc); | |
| 1993/0528 | qlock(p); p->ref++; qunlock(p); | |
| 1990/1009 | return nc; } | |
| 1990/0227 | ||
| 1990/1009 | int pipegen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) { int id; | |
| 1990/0629 | ||
| 1993/0528 | id = NETID(c->qid.path); | |
| 1990/1009 | if(i > 1) id++; if(tab==0 || i>=ntab) return -1; tab += i; | |
| 1993/0528 | devdir(c, (Qid){NETQID(id, tab->qid.path),0}, tab->name, tab->length, eve, tab->perm, dp); | |
| 1990/1009 | return 1; | |
| 1990/0227 | } | |
| 1990/1009 | ||
| 1990/0227 | int pipewalk(Chan *c, char *name) { | |
| 1990/1009 | return devwalk(c, name, pipedir, NPIPEDIR, pipegen); | |
| 1990/0227 | } void pipestat(Chan *c, char *db) { | |
| 1993/0528 | Pipe *p; Dir dir; p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdir: devdir(c, c->qid, ".", 2*DIRLEN, eve, CHDIR|0555, &dir); break; case Qdata0: devdir(c, c->qid, "data", p->q[0]->len, eve, 0660, &dir); break; case Qdata1: devdir(c, c->qid, "data1", p->q[1]->len, eve, 0660, &dir); break; default: panic("pipestat"); } convD2M(&dir, db); | |
| 1990/0227 | } | |
| 1990/1009 | /* * if the stream doesn't exist, create it */ | |
| 1990/0227 | Chan * pipeopen(Chan *c, int omode) { | |
| 1990/1009 | Pipe *p; | |
| 1990/11211 | if(c->qid.path & CHDIR){ | |
| 1990/1009 | if(omode != OREAD) | |
| 1990/11211 | error(Ebadarg); | |
| 1990/1009 | c->mode = omode; c->flag |= COPEN; c->offset = 0; return c; } | |
| 1993/0528 | p = c->aux; | |
| 1991/1227 | qlock(p); | |
| 1993/0528 | switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]++; break; case Qdata1: p->qref[1]++; break; | |
| 1990/1009 | } | |
| 1991/1227 | qunlock(p); | |
| 1990/1009 | ||
| 1993/0501 | c->mode = omode&~OTRUNC; | |
| 1990/0227 | c->flag |= COPEN; c->offset = 0; return c; } void pipecreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1991/1115 | USED(c, name, omode, perm); | |
| 1990/11211 | error(Egreg); | |
| 1990/0227 | } void piperemove(Chan *c) { | |
| 1991/1115 | USED(c); | |
| 1990/11211 | error(Egreg); | |
| 1990/0227 | } void pipewstat(Chan *c, char *db) { | |
| 1991/1115 | USED(c, db); | |
| 1990/11211 | error(Eperm); | |
| 1990/0227 | } void pipeclose(Chan *c) { | |
| 1992/0621 | Pipe *p, *f, **l; | |
| 1990/0629 | ||
| 1993/0528 | p = c->aux; qlock(p); | |
| 1990/0629 | ||
| 1990/1009 | /* | |
| 1993/0528 | * closing either side hangs up the stream | |
| 1990/1009 | */ | |
| 1993/0528 | switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]--; if(p->qref[0] == 0){ qclose(p->q[0]); qhangup(p->q[1]); | |
| 1991/0314 | } | |
| 1993/0528 | break; case Qdata1: p->qref[1]--; if(p->qref[1] == 0){ qclose(p->q[1]); qhangup(p->q[0]); } break; | |
| 1990/11211 | } | |
| 1990/11161 | /* | |
| 1993/0528 | * if both sides are closed, they are reusable | |
| 1990/11161 | */ | |
| 1993/0528 | if(p->qref[0] == 0 && p->qref[1] == 0){ qreopen(p->q[0]); qreopen(p->q[1]); } /* * free the structure on last close */ p->ref--; if(p->ref == 0){ qunlock(p); | |
| 1990/11161 | lock(&pipealloc); | |
| 1992/0621 | l = &pipealloc.pipe; for(f = *l; f; f = f->next) { if(f == p) { *l = p->next; break; } | |
| 1992/0625 | l = &f->next; | |
| 1992/0621 | } | |
| 1990/11161 | unlock(&pipealloc); | |
| 1993/0528 | free(p->q[0]); free(p->q[1]); | |
| 1992/0621 | free(p); | |
| 1990/11161 | } | |
| 1993/0528 | qunlock(p); | |
| 1990/0227 | } long | |
| 1991/0411 | piperead(Chan *c, void *va, long n, ulong offset) | |
| 1990/0227 | { | |
| 1993/0528 | Pipe *p; | |
| 1992/0711 | USED(offset); | |
| 1992/0621 | ||
| 1993/0528 | p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdir: return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen); case Qdata0: return qread(p->q[0], va, n); case Qdata1: return qread(p->q[1], va, n); default: panic("piperead"); } return -1; /* not reached */ | |
| 1990/0227 | } | |
| 1990/1009 | /* * a write to a closed pipe causes a note to be sent to * the process. */ | |
| 1990/0227 | long | |
| 1991/0411 | pipewrite(Chan *c, void *va, long n, ulong offset) | |
| 1990/0227 | { | |
| 1993/0528 | Pipe *p; | |
| 1992/0711 | USED(offset); | |
| 1992/0821 | ||
| 1993/0528 | p = c->aux; | |
| 1992/0821 | ||
| 1993/0528 | switch(NETTYPE(c->qid.path)){ case Qdata0: return qwrite(p->q[1], va, n); case Qdata1: return qwrite(p->q[0], va, n); default: panic("piperead"); | |
| 1990/0227 | } | |
| 1990/0513 | return n; | |
| 1990/0227 | } | |