static void pipeclose(Chan *c) { Pipe *p; p = c->aux; qlock(&p->l); if(c->flag & COPEN){ /* * closing either side hangs up the stream */ switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]--; if(p->qref[0] == 0){ qhangup(p->q[1], 0); qclose(p->q[0]); } break; case Qdata1: p->qref[1]--; if(p->qref[1] == 0){ qhangup(p->q[0], 0); qclose(p->q[1]); } break; } } /* * if both sides are closed, they are reusable */ 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->l); freepipe(p); } else qunlock(&p->l); }
/* * create a pipe, no streams are created until an open */ static struct chan *pipeattach(char *spec) { ERRSTACK(2); Pipe *p; struct chan *c; c = devattach(devname(), spec); p = kzmalloc(sizeof(Pipe), 0); if (p == 0) error(ENOMEM, ERROR_FIXME); if (waserror()) { freepipe(p); nexterror(); } p->pipedir = kzmalloc(sizeof(pipedir), 0); if (p->pipedir == 0) error(ENOMEM, ERROR_FIXME); memmove(p->pipedir, pipedir, sizeof(pipedir)); kstrdup(&p->user, current->user); kref_init(&p->ref, pipe_release, 1); qlock_init(&p->qlock); p->q[0] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0); if (p->q[0] == 0) error(ENOMEM, ERROR_FIXME); p->q[1] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0); if (p->q[1] == 0) error(ENOMEM, ERROR_FIXME); poperror(); spin_lock(&(&pipealloc)->lock); p->path = ++pipealloc.path; spin_unlock(&(&pipealloc)->lock); c->qid.path = NETQID(2 * p->path, Qdir); c->qid.vers = 0; c->qid.type = QTDIR; c->aux = p; c->dev = 0; /* taps. */ SLIST_INIT(&p->data_taps[0]); /* already = 0; set to be futureproof */ SLIST_INIT(&p->data_taps[1]); spinlock_init(&p->tap_lock); return c; }
/* * create a pipe, no streams are created until an open */ static Chan* pipeattach(char *spec) { Pipe *p; Chan *c; c = devattach('|', spec); p = malloc(sizeof(Pipe)); if(p == 0) error(Enomem); if(waserror()){ freepipe(p); nexterror(); } p->pipedir = malloc(sizeof(pipedir)); if (p->pipedir == 0) error(Enomem); memmove(p->pipedir, pipedir, sizeof(pipedir)); kstrdup(&p->user, up->env->user); p->ref = 1; p->q[0] = qopen(pipealloc.pipeqsize, 0, 0, 0); if(p->q[0] == 0) error(Enomem); p->q[1] = qopen(pipealloc.pipeqsize, 0, 0, 0); if(p->q[1] == 0) error(Enomem); poperror(); lock(&pipealloc.l); p->path = ++pipealloc.path; unlock(&pipealloc.l); c->qid.path = NETQID(2*p->path, Qdir); c->qid.vers = 0; c->qid.type = QTDIR; c->aux = p; c->dev = 0; return c; }
static void pipe_release(struct kref *kref) { Pipe *pipe = container_of(kref, Pipe, ref); freepipe(pipe); }