int sunsrvudp(SunSrv *srv, char *address) { int fd; char adir[40]; Arg *arg; fd = announce(address, adir); if(fd < 0) return -1; arg = emalloc(sizeof(Arg)); arg->fd = fd; arg->srv = srv; arg->creply = chancreate(sizeof(SunMsg*), 10); arg->csync = chancreate(sizeof(void*), 10); proccreate(sunudpread, arg, SunStackSize); proccreate(sunudpwrite, arg, SunStackSize); recvp(arg->csync); recvp(arg->csync); chanfree(arg->csync); free(arg); return 0; }
void pipectl(void *v) { Window *w; Event *e; w = v; proccreate(wineventproc, w, STACK); windormant(w); winsetaddr(w, "0", 0); for(;;){ e = recvp(w->cevent); switch(e->c1){ default: Unknown: fprint(2, "unknown message %c%c\n", e->c1, e->c2); break; case 'E': /* write to body; can't affect us */ break; case 'F': /* generated by our actions; ignore */ break; case 'K': /* ignore */ break; case 'M': switch(e->c2){ case 'x': case 'X': execevent(w, e, pipecommand); break; case 'l': /* reflect all searches back to acme */ case 'L': if(e->flag & 2) recvp(w->cevent); winwriteevent(w, e); break; case 'I': /* modify away; we don't care */ case 'i': case 'D': case 'd': break; default: goto Unknown; } } } }
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 etherwriteproc(void *a) { Ether *e = a; Buf *bp; Channel *wc; threadsetname("etherwrite"); wc = e->wc; while(e->exiting == 0){ bp = recvp(wc); if(bp == nil || e->exiting != 0){ free(bp); break; } e->nout++; if(e->bwrite(e, bp) < 0) e->noerrs++; if(isloopback(e, bp) && e->exiting == 0) sendp(e->rc, bp); /* send to input queue */ else freebuf(e, bp); } deprint(2, "%s: writeproc exiting\n", argv0); closedev(e->dev); }
void bcastmsg(Channel *q, Wmsg *m) { Worker *w, marker; void *a; a = m->arg; /* * Use a marker to mark the end of the queue. * This prevents workers from getting the * broadcast and putting themselves back on the * queue before the broadcast has finished */ marker.eventc = nil; /* Only markers have eventc == nil */ sendp(q, &marker); while((w = recvp(q)) != &marker){ if(w->eventc == nil){ /* somebody else's marker, put it back */ sendp(q, w); }else{ if(a) m->arg = strdup(a); send(w->eventc, m); } } free(a); m->arg = nil; }
static Rpc* convgetrpc(Conv *c, int want) { for(;;){ if(c->hangup){ flog("convgetrpc: hangup"); werrstr("hangup"); return nil; } if(c->rpc.op == RpcUnknown){ recvp(c->rpcwait); if(c->hangup){ flog("convgetrpc: hangup"); werrstr("hangup"); return nil; } if(c->rpc.op == RpcUnknown) continue; } if(want < 0 || c->rpc.op == want) return &c->rpc; rpcrespond(c, "phase in state '%s' want '%s'", c->state, rpcname[want]); } /* not reached */ }
void newpipethread(void*) { Window *w; while(w = recvp(newpipechan)) threadcreate(pipectl, w, STACK); }
static void sunRpcRequestThread(void *v) { uchar *p, *ep; Channel *c; SunSrv *srv = v; SunMsg *m; SunProg *pg; SunStatus ok; while((m = recvp(srv->crequest)) != nil){ /* could look up in cache here? */ if(srv->chatty) fprint(2, "sun msg %p count %d\n", m, m->count); m->srv = srv; p = m->data; ep = p+m->count; if(sunRpcUnpack(p, ep, &p, &m->rpc) != SunSuccess){ fprint(2, "in: %.*H unpack failed\n", m->count, m->data); sunMsgDrop(m); continue; } if(srv->chatty) fprint(2, "in: %B\n", &m->rpc); if(srv->alwaysReject){ if(srv->chatty) fprint(2, "\trejecting\n"); sunMsgReplyError(m, SunAuthTooWeak); continue; } if(!m->rpc.iscall){ sunMsgReplyError(m, SunGarbageArgs); continue; } if((pg = sunFindProg(srv, m, &m->rpc, &c)) == nil){ /* sunFindProg sent error */ continue; } p = m->rpc.data; ep = p+m->rpc.ndata; m->call = nil; if((ok = sunCallUnpackAlloc(pg, m->rpc.proc<<1, p, ep, &p, &m->call)) != SunSuccess){ sunMsgReplyError(m, ok); continue; } m->call->rpc = m->rpc; if(srv->chatty) fprint(2, "\t%C\n", m->call); m->pg = pg; sendp(c, m); } }
void fsysproc(void *v) { int n; Xfid *x; Fid *f; Fcall t; uchar *buf; threadsetname("fsysproc"); USED(v); x = nil; for(;;){ buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */ n = read9pmsg(sfd, buf, messagesize); if(n <= 0){ if(closing) break; error("i/o error on server channel"); } if(x == nil){ sendp(cxfidalloc, nil); x = recvp(cxfidalloc); } x->buf = buf; if(convM2S(buf, n, &x->fcall) != n) error("convert error in convM2S"); if(DEBUG) fprint(2, "%F\n", &x->fcall); if(fcall[x->fcall.type] == nil) x = respond(x, &t, "bad fcall type"); else{ switch(x->fcall.type){ case Tversion: case Tauth: case Tflush: f = nil; break; case Tattach: f = newfid(x->fcall.fid); break; default: f = newfid(x->fcall.fid); if(!f->busy){ x->f = f; x = respond(x, &t, "fid not in use"); continue; } break; } x->f = f; x = (*fcall[x->fcall.type])(x, f); } } }
void nfs3proc(void *v) { Channel *c; SunMsg *m; c = v; threadsetname("nfs3"); while((m = recvp(c)) != nil) threadcreate(rnfs3, m, SunStackSize); }
void wrthread(void *v) { char *p; USED(v); while((p = recvp(cw)) != nil){ wr(p, nil); free(p); } }
static void sunRpcReplyThread(void *v) { SunMsg *m; SunSrv *srv = v; while((m = recvp(srv->creply)) != nil){ /* could record in cache here? */ sendp(m->creply, m); } }
void mount3proc(void *v) { Channel *c; SunMsg *m; threadsetname("mount1"); c = v; while((m=recvp(c)) != nil) threadcreate(rmount3, m, SunStackSize); }
void rdthread(void *v) { char *p, *buf2; buf2 = vtmalloc(blocksize); USED(v); while((p = recvp(cr)) != nil){ rd(p, buf2); free(p); } }
void dirthread(void *v) { Event *e; Window *w; w = v; while(e = recvp(w->cevent)) acmeevent(nil, w, e); threadexitsall(nil); }
void plumbsendthread(void *v) { Plumbmsg *m; USED(v); threadsetname("plumbsendthread"); while((m = recvp(cplumbsend)) != nil){ mkreply(nil, "Mail", m->data, m->attr, nil); plumbfree(m); } threadexits(nil); }
Waitmsg* twaitfor(int pid) { Waitreq r; Waitmsg *w; r.pid = pid; r.c = chancreate(sizeof(Waitmsg*), 1); send(twaitchan, &r); w = recvp(r.c); chanfree(r.c); return w; }
void plumbshowthread(void *v) { Plumbmsg *m; USED(v); threadsetname("plumbshowthread"); while((m = recvp(cplumbshow)) != nil){ showmesg(m->data, plumblookup(m->attr, "digest")); plumbfree(m); } threadexits(nil); }
static void sunudpwrite(void *v) { Arg arg = *(Arg*)v; SunMsgUdp *msg; sendp(arg.csync, 0); while((msg = recvp(arg.creply)) != nil){ if(udpwrite(arg.fd, &msg->udp, msg->msg.data, msg->msg.count) != msg->msg.count) fprint(2, "udpwrite: %r\n"); sunmsgdrop(&msg->msg); } }
/* this thread, in the main proc, allows fsysproc to get a window made without doing graphics */ void newwindowthread(void*) { Window *w; threadsetname("newwindowthread"); for(;;){ /* only fsysproc is talking to us, so synchronization is trivial */ recvp(cnewwindow); w = makenewwindow(nil); winsettag(w); sendp(cnewwindow, w); } }
void xfidctl(void *arg) { Xfid *x; void (*f)(Xfid*); threadsetname("xfidctlthread"); x = arg; for(;;){ f = (void(*)(Xfid*))recvp(x->c); (*f)(x); flushimage(display, 1); sendp(cxfidfree, x); } }
static void work(void *a) { Channel *portc; char *fn; Hub *h; int i; portc = a; threadsetname("work"); hubs = nil; /* * Receive requests for root hubs */ while((fn = recvp(portc)) != nil){ dprint(2, "%s: %s starting\n", argv0, fn); h = newhub(fn, nil); if(h == nil) fprint(2, "%s: %s: newhub failed: %r\n", argv0, fn); free(fn); } /* * Enumerate (and acknowledge after first enumeration). * Do NOT perform enumeration concurrently for the same * controller. new devices attached respond to a default * address (0) after reset, thus enumeration has to work * one device at a time at least before addresses have been * assigned. * Do not use hub interrupt endpoint because we * have to poll the root hub(s) in any case. */ for(;;){ Again: for(h = hubs; h != nil; h = h->next) for(i = 1; i <= h->nport; i++) if(enumhub(h, i) < 0){ /* changes in hub list; repeat */ goto Again; } if(portc != nil){ sendp(portc, nil); portc = nil; } sleep(pollms); if(mustdump) dump(); } }
void httpfilereadproc(void*) { Block *b; threadsetname("httpfilereadproc"); for(;;){ b = recvp(httpchan); if(b == nil) continue; if(getrange(b) == nil) sysfatal("getrange: %r"); sendp(finishchan, b); } }
void mesgthread(void *v) { Event *e; Article *m; m = v; while(!m->dead && (e = recvp(m->w->cevent))) acmeevent(m, m->w, e); //fprint(2, "msg %p exits\n", m); unlink(m); free(m->w); free(m); threadexits(nil); }
static void plumbwebthread(void*) { char *base; Plumbmsg *m; for(;;){ m = recvp(plumbchan); if(m == nil) threadexits(nil); base = plumblookup(m->attr, "baseurl"); if(base == nil) base = m->wdir; plumburl(m->data, base); plumbfree(m); } }
static void writethread(void *a) { char e[ERRMAX]; uchar *buf; int n; Ioproc *io; Req *r; Client *c; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "write%d", c->num); threadsetname(tmp); buf = emalloc(8192); io = c->writerproc; for(;;){ while(c->wq == nil){ if(c->moribund) goto Out; recvp(c->writerkick); if(c->moribund) goto Out; } r = c->wq; c->wq = r->aux; c->curw = r; n = iowrite(io, c->fd[1], r->ifcall.data, r->ifcall.count); c->curw = nil; if(chatty9p) fprint(2, "io->write returns %d\n", n); if(n >= 0){ r->ofcall.count = n; respond(r, nil); }else{ rerrstr(e, sizeof e); respond(r, e); } } Out: free(buf); die(c); }
static void statusreader(void *u) { Areader *a; Channel *c; Packser *pk; Serialport *p; Serial *ser; int cl; p = u; ser = p->s; threadsetname("statusreader thread"); /* big buffering, fewer bytes lost */ c = chancreate(sizeof(Packser *), 128); a = emallocz(sizeof(Areader), 1); a->p = p; a->c = c; incref(ser->dev); proccreate(epreader, a, 16*1024); while((pk = recvp(c)) != nil){ memmove(p->data, pk->b, pk->nb); p->ndata = pk->nb; free(pk); dsprint(2, "serial %p: status reader %d \n", p, p->ndata); /* consume it all */ while(p->ndata != 0){ dsprint(2, "serial %p: status reader to consume: %d\n", p, p->ndata); cl = recvul(p->w4data); if(cl < 0) break; cl = sendul(p->gotdata, 1); if(cl < 0) break; } } shutdownchan(c); devctl(ser->dev, "detach"); closedev(ser->dev); usbfsdel(&p->fs); }
void editcmd(Text *ct, Rune *r, uint n) { char *err; if(n == 0) return; if(2*n > RBUFSIZE){ warning(nil, "string too long\n"); return; } allwindows(alleditinit, nil); if(cmdstartp) free(cmdstartp); cmdstartp = runemalloc(n+2); runemove(cmdstartp, r, n); if(r[n] != '\n') cmdstartp[n++] = '\n'; cmdstartp[n] = '\0'; cmdendp = cmdstartp+n; cmdp = cmdstartp; if(ct->w == nil) curtext = nil; else curtext = &ct->w->body; resetxec(); if(editerrc == nil){ editerrc = chancreate(sizeof(char*), 0); lastpat = allocstring(0); } threadcreate(editthread, nil, STACK); err = recvp(editerrc); editing = Inactive; if(err != nil){ if(err[0] != '\0') warning(nil, "Edit: %s\n", err); free(err); } /* update everyone whose edit log has data */ allwindows(allupdate, nil); }
void threadmain(int argc, char *argv[]) { char buf[512]; int fd; Channel *c; progname = "plumber"; ARGBEGIN{ case 'p': plumbfile = ARGF(); break; }ARGEND user = getenv("user"); home = getenv("home"); if(user==nil || home==nil) error("can't initialize $user or $home: %r"); if(plumbfile == nil){ sprint(buf, "%s/lib/plumbing", home); plumbfile = estrdup(buf); } fd = open(plumbfile, OREAD); if(fd < 0) error("can't open rules file %s: %r", plumbfile); if(setjmp(parsejmp)) error("parse error"); rules = readrules(plumbfile, fd); close(fd); /* * Start all processes and threads from other proc * so we (main pid) can return to user. */ c = chancreate(sizeof(void*), 0); proccreate(mainproc, c, 8192); recvp(c); chanfree(c); threadexits(nil); }
void waitproc(void *v) { Channel *c; Waitmsg *w; int i; Job *j; c = v; for(;;) { w = recvp(c); for(i=0; i<njob; i++) { j = &job[i]; if(j->pid == w->pid) { j->pid = 0; j->runend = time(0) - time0; break; } } free(w); } }