void decexec(void *a) { char buf[256]; Playfd *pfd; Pacbuf *pb; threadsetname("decexec"); pfd = a; close(pfd->cfd); /* read fd */ if(pfd->fd != 1){ dup(pfd->fd, 1); close(pfd->fd); } close(0); open("/dev/null", OREAD); close(2); open("/dev/null", OWRITE); strncpy(buf, pfd->filename, sizeof(buf)-1); buf[sizeof(buf)-1] = 0; free(pfd->filename); free(pfd); procexecl(nil, "/bin/play", "play", "-o", "/fd/1", buf, nil); if((pb = nbrecvp(spare)) == nil) pb = malloc(sizeof(Pacbuf)); pb->cmd = Error; pb->off = 0; pb->len = snprint(pb->data, sizeof(pb->data), "startplay: exec play failed"); sendp(full, pb); threadexits("exec"); }
static Buf* allocbuf(Ether *e) { Buf *bp; bp = nbrecvp(e->bc); if(bp == nil){ qlock(e); if(e->nabufs < Nbufs){ bp = emallocz(sizeof(Buf), 1); e->nabufs++; setmalloctag(bp, getcallerpc(&e)); deprint(2, "%s: %d buffers\n", argv0, e->nabufs); } qunlock(e); } if(bp == nil){ deprint(2, "%s: blocked waiting for allocbuf\n", argv0); bp = recvp(e->bc); } bp->rp = bp->data + Hdrsize; bp->ndata = 0; if(0)deprint(2, "%s: allocbuf %#p\n", argv0, bp); qlock(e); e->nbufs++; qunlock(e); return bp; }
static void etherfree(Ether *e) { int i; Buf *bp; if(e->free != nil) e->free(e); closedev(e->epin); closedev(e->epout); if(e->rc == nil){ /* not really started */ free(e); return; } for(i = 0; i < e->nconns; i++) if(e->conns[i] != nil){ while((bp = nbrecvp(e->conns[i]->rc)) != nil) free(bp); chanfree(e->conns[i]->rc); free(e->conns[i]); } shutdownchan(e->bc); shutdownchan(e->rc); shutdownchan(e->wc); e->epin = e->epout = nil; devctl(e->dev, "detach"); free(e); }
static void shutdownchan(Channel *c) { Packser *bp; while((bp=nbrecvp(c)) != nil) free(bp); chanfree(c); }
static void etherreadproc(void *a) { int i, n, nwants; Buf *bp, *dbp; Ether *e = a; threadsetname("etherread"); while(e->exiting == 0){ bp = nbrecvp(e->rc); if(bp == nil){ bp = allocbuf(e); /* leak() may think we leak */ if(e->bread(e, bp) < 0){ freebuf(e, bp); break; } if(bp->ndata == 0){ /* may be a short packet; continue */ if(0)dprint(2, "%s: read: short\n", argv0); freebuf(e, bp); continue; }else setbuftype(bp); } e->nin++; nwants = 0; for(i = 0; i < e->nconns; i++) nwants += cwantsbp(e->conns[i], bp); for(i = 0; nwants > 0 && i < e->nconns; i++) if(cwantsbp(e->conns[i], bp)){ n = bp->ndata; if(e->conns[i]->type == -2 && n > 64) n = 64; if(nwants-- == 1){ bp->ndata = n; dbp = bp; bp = nil; }else{ dbp = allocbuf(e); memmove(dbp->rp, bp->rp, n); dbp->ndata = n; dbp->type = bp->type; } if(nbsendp(e->conns[i]->rc, dbp) == 0){ deprint(2, "%s: (in) packet lost\n", argv0); e->nierrs++; freebuf(e, dbp); } } freebuf(e, bp); } deprint(2, "%s: writeproc exiting\n", argv0); etherexiting(e); closedev(e->dev); usbfsdel(&e->fs); }
Req* reqalloc(void) { Req *r; if(reqs == nil) reqs = chancreate(sizeof(Req*), 256); if(r = nbrecvp(reqs)) return r; r = malloc(sizeof(Req)); return r; }
int sendmsg(Channel *q, Wmsg *m) { Worker *w; while(w = nbrecvp(q)){ /* Test for markerdom (see bcastmsg) */ if(w->eventc){ send(w->eventc, m); return 1; } sendp(q, w); /* put back */ } return 0; }
void nbnstransactionfree(NbnsTransaction **tp) { NbnsTransaction **tp2; NbnsMessage *s; NbnsTransaction *t; t = *tp; if (t) { qlock(&transactionlist); while ((s = nbrecvp(t->c)) != nil) nbnsmessagefree(&s); for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next) ; if (*tp2) { *tp2 = t->next; free(t); } qunlock(&transactionlist); *tp = nil; } }
static void fsclunk(Usbfs *fs, Fid *fid) { int qt; int64_t qid; Buf *bp; Conn *c; Ether *e; e = fs->aux; qid = fid->qid.path & ~fs->qid; qt = qtype(qid); switch(qt){ case Qndata: case Qnctl: case Qnifstats: case Qnstats: case Qntype: if(fid->omode != ONONE){ c = getconn(e, qnum(qid), 0); if(c == nil) sysfatal("usb: ether: fsopen bug"); if(decref(c) == 0){ while((bp = nbrecvp(c->rc)) != nil) freebuf(e, bp); qlock(e); if(c->prom != 0) if(decref(&e->prom) == 0) prom(e, 0); c->prom = c->type = 0; qunlock(e); } } break; } etherdump(e); }
void pcmproc(void*) { Pmsg localstate, newstate, prevstate; int fd, n; Pacbuf *pb, *b; Alt a[3] = { {full, &pb, CHANRCV}, {playout, &pb, CHANRCV}, {nil, nil, CHANEND}, }; /* * This is the real-time proc. * It gets its input from two sources, full data/control buffers from the decproc * which mixes decoded data with control messages, and data buffers from the pcmproc's * (*this* proc's) own internal playout buffer. * When a command is received on the `full' channel containing a command that warrants * an immediate change of audio source (e.g., to silence or to another number), we just * toss everything in the pipeline -- i.e., the playout channel * Finally, we report all state changes using `playupdate' (another message channel) */ threadsetname("pcmproc"); close(srvfd[1]); fd = -1; localstate.cmd = 0; /* Force initial playupdate */ newstate.cmd = Stop; newstate.off = 0; // rtsched(); boost(); for(;;){ if(newstate.m != localstate.m){ playupdate(newstate, nil); localstate = newstate; } switch(alt(a)){ case 0: /* buffer received from decproc */ if((debug & DbgPcm) && localstate.m != prevstate.m){ fprint(2, "pcm, full: %s-%d, local state is %s-%d\n", statetxt[pb->cmd], pb->off, statetxt[localstate.cmd], localstate.off); prevstate.m = localstate.m; } switch(pb->cmd){ default: sysfatal("pcmproc: unknown newstate: %s-%d", statetxt[pb->cmd], pb->off); case Resume: a[1].op = CHANRCV; newstate.cmd = Play; break; case Pause: a[1].op = CHANNOP; newstate.cmd = Pause; if(fd >= 0){ close(fd); fd = -1; } break; case Stop: /* Dump all data in the buffer */ while(b = nbrecvp(playout)) if(b->cmd == Error){ playupdate(b->Pmsg, b->data); sendp(spare, b); }else sendp(empty, b); newstate.m = pb->m; a[1].op = CHANRCV; if(fd >= 0){ close(fd); fd = -1; } break; case Skip: /* Dump all data in the buffer, then fall through */ while(b = nbrecvp(playout)) if(b->cmd == Error){ playupdate(pb->Pmsg, pb->data); sendp(spare, pb); }else sendp(empty, b); a[1].op = CHANRCV; newstate.cmd = Play; case Error: case Play: /* deal with at playout, just requeue */ sendp(playout, pb); pb = nil; localstate = newstate; break; } /* If we still have a buffer, free it */ if(pb) sendp(spare, pb); break; case 1: /* internal buffer */ if((debug & DbgPlayer) && localstate.m != prevstate.m){ fprint(2, "pcm, playout: %s-%d, local state is %s-%d\n", statetxt[pb->cmd], pb->off, statetxt[localstate.cmd], localstate.off); prevstate.m = localstate.m; } switch(pb->cmd){ default: sysfatal("pcmproc: unknown newstate: %s-%d", statetxt[pb->cmd], pb->off); case Error: playupdate(pb->Pmsg, pb->data); localstate = newstate; sendp(spare, pb); break; case Play: if(fd < 0 && (fd = open("/dev/audio", OWRITE)) < 0){ a[1].op = CHANNOP; newstate.cmd = Pause; pb->cmd = Error; snprint(pb->data, sizeof(pb->data), "/dev/audio: %r"); playupdate(pb->Pmsg, pb->data); sendp(empty, pb); break; } /* play out this buffer */ totbytes += pb->len; totbuffers++; n = write(fd, pb->data, pb->len); if (n != pb->len){ if (debug & DbgPlayer) fprint(2, "pcmproc: file %d: %r\n", pb->off); if (n < 0) sysfatal("pcmproc: write: %r"); } newstate.m = pb->m; sendp(empty, pb); break; } break; } } }