void keyboardthread(void *) { Rune r; Timer *timer; Text *t; enum { KTimer, KKey, NKALT }; static Alt alts[NKALT+1]; alts[KTimer].c = nil; alts[KTimer].v = nil; alts[KTimer].op = CHANNOP; alts[KKey].c = keyboardctl->c; alts[KKey].v = &r; alts[KKey].op = CHANRCV; alts[NKALT].op = CHANEND; timer = nil; typetext = nil; threadsetname("keyboardthread"); for(;;){ switch(alt(alts)){ case KTimer: timerstop(timer); t = typetext; if(t!=nil && t->what==Tag){ winlock(t->w, 'K'); wincommit(t->w, t); winunlock(t->w); flushimage(display, 1); } alts[KTimer].c = nil; alts[KTimer].op = CHANNOP; break; case KKey: casekeyboard: typetext = rowtype(&row, r, mouse->xy); t = typetext; if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright)) /* scrolling doesn't change activecol */ activecol = t->col; if(t!=nil && t->w!=nil) t->w->body.file->curtext = &t->w->body; if(timer != nil) timercancel(timer); if(t!=nil && t->what==Tag) { timer = timerstart(500); alts[KTimer].c = timer->c; alts[KTimer].op = CHANRCV; }else{ timer = nil; alts[KTimer].c = nil; alts[KTimer].op = CHANNOP; } if(nbrecv(keyboardctl->c, &r) > 0) goto casekeyboard; flushimage(display, 1); break; } } }
static void execthread(void *a) { Client *c; int p; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "exec%d", c->num); threadsetname(tmp); c->execpid = chancreate(sizeof(ulong), 0); proccreate(execproc, c, STACK); p = recvul(c->execpid); chanfree(c->execpid); c->execpid = nil; close(c->fd[1]); c->fd[1] = c->fd[0]; if(p != -1){ c->pid = p; c->activethread = 2; threadcreate(readthread, c, STACK); threadcreate(writethread, c, STACK); if(c->execreq) respond(c->execreq, nil); }else{ if(c->execreq) respond(c->execreq, c->err); } }
static void execproc(void *a) { int i, fd; Client *c; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "execproc%d", c->num); threadsetname(tmp); if(pipe(c->fd) < 0){ rerrstr(c->err, sizeof c->err); sendul(c->execpid, -1); return; } rfork(RFFDG); fd = c->fd[1]; close(c->fd[0]); dup(fd, 0); dup(fd, 1); for(i=3; i<100; i++) /* should do better */ close(i); strcpy(c->err, "exec failed"); procexecl(c->execpid, "/bin/rc", "rc", "-c", c->cmd, nil); }
static void writeproc(void *v) { Channel *sync; void **a; char *s; long np; int fd, i, n; threadsetname("writeproc"); a = v; sync = a[0]; fd = (uintptr)a[1]; s = a[2]; np =(uintptr)a[3]; free(a); for(i=0; i<np; i+=n){ n = np-i; if(n > BUFSIZE) n = BUFSIZE; if(write(fd, s+i, n) != n) break; } close(fd); sendul(sync, i); }
static void icachewriteproc(void *v) { int ret; uint bsize; ISect *is; Index *ix; u8int *buf; ix = mainindex; is = v; threadsetname("icachewriteproc:%s", is->part->name); bsize = 1<<is->blocklog; buf = emalloc(Bufsize+bsize); buf = (u8int*)(((uintptr)buf+bsize-1)&~(uintptr)(bsize-1)); for(;;){ trace(TraceProc, "icachewriteproc recv"); recv(is->writechan, 0); trace(TraceWork, "start"); ret = icachewritesect(ix, is, buf); trace(TraceProc, "icachewriteproc send"); trace(TraceWork, "finish"); sendul(is->writedonechan, ret); } }
void listenthread(void *arg) { Conn *c; Ioproc *io; io = ioproc(); USED(arg); threadsetname("listen %s", adir); for(;;){ c = emalloc(sizeof(Conn)); c->fd = iolisten(io, adir, c->dir); if(c->fd < 0){ if(verbose) fprint(2, "%T listen: %r\n"); close(afd); free(c); return; } c->inc = chancreate(sizeof(void*), 0); c->internal = chancreate(sizeof(void*), 0); c->inq = qalloc(); c->outq = qalloc(); c->outqdead = chancreate(sizeof(void*), 0); if(verbose) fprint(2, "%T incoming call on %s\n", c->dir); threadcreate(connthread, c, STACK); } }
static void periodicThread(void *a) { Periodic *p = a; vlong t, ct, ts; /* times in ms. */ threadsetname("periodic"); ct = nsec() / 1000000; t = ct + p->msec; /* call p->f at or after this time */ for(;;){ ts = t - ct; /* ms. to next cycle's start */ if(ts > 1000) ts = 1000; /* bound sleep duration */ if(ts > 0) sleep(ts); /* wait for cycle's start */ qlock(&p->lk); if(p->die){ qunlock(&p->lk); break; } ct = nsec() / 1000000; if(t <= ct){ /* due to call p->f? */ p->f(p->a); ct = nsec() / 1000000; while(t <= ct) /* advance t to future cycle start */ t += p->msec; } qunlock(&p->lk); } periodicFree(p); }
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 execproc(void *v) { Channel *sync; Exec *e; int p[2], q[2]; char *cmd; threadsetname("execproc"); e = v; p[0] = e->p[0]; p[1] = e->p[1]; q[0] = e->q[0]; q[1] = e->q[1]; cmd = e->cmd; sync = e->sync; rfork(RFFDG); free(e); dup(p[0], 0); close(p[0]); close(p[1]); if(q[0]){ dup(q[1], 1); close(q[0]); close(q[1]); } if(!procstderr) close(2); procexecl(sync, "/bin/rc", "rc", "-c", cmd, 0); error("can't exec"); }
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"); }
void delaykickroundproc(void *v) { Round *r = v; int n; threadsetname("delaykickproc %s", r->name); qlock(&r->lock); for(;;){ while(r->delaykick == 0){ trace(TraceProc, "sleep"); rsleep(&r->delaywait); } n = r->next; qunlock(&r->lock); trace(TraceProc, "waitround 0x%ux", (uint)n); sleep(r->delaytime); qlock(&r->lock); if(n == r->next){ trace(TraceProc, "kickround 0x%ux", (uint)n); _kickround(r, 1); } trace(TraceProc, "finishround 0x%ux", (uint)n); } }
void syncthread0(void *a) { Queue *q; Syncpath *s; threadsetname("syncthread"); startclient(); q = a; for(;;){ s = qrecv(q); assert(s->state == SyncStart); syncstat(s); if(s->state == SyncError){ Err: syncfinish(s); continue; } synctriage(s); if(s->state == SyncError) goto Err; if(s->triage != DoNothing) tralog("%P %s%s: [%$] [%$]", s->p, s->conflict ? "conflict " : "", workstr(s, s->triage), s->a.s, s->b.s); qsend(s->sync->triageq, s); } }
static void readthread(void *a) { uint8_t *buf; int n; Client *c; Ioproc *io; Msg *m; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "read%d", c->num); threadsetname(tmp); buf = emalloc(8192); io = c->readerproc; while((n = ioread(io, c->fd[0], buf, 8192)) >= 0){ m = emalloc(sizeof(Msg)+n); m->rp = (uint8_t*)&m[1]; m->ep = m->rp + n; if(n) memmove(m->rp, buf, n); queuemsg(c, m); matchmsgs(c); } queuemsg(c, Zmsg); free(buf); die(c); }
void cdstatusproc(void *v) { Drive *d; Toc t; Cdstatus s; t.changetime = ~0; t.nchange = ~0; threadsetname("cdstatusproc"); d = v; DPRINT(2, "cdstatus %d\n", getpid()); for(;;) { ping(d); //DPRINT(2, "d %d %d t %d %d\n", d->scsi->changetime, d->scsi->nchange, t.changetime, t.nchange); if(playstatus(d, &s) == 0) send(d->cstatus, &s); if(d->scsi->changetime != t.changetime || d->scsi->nchange != t.nchange) { if(gettoc(d->scsi, &t) == 0) { DPRINT(2, "sendtoc...\n"); if(debug) dumptoc(&t); send(d->ctocdisp, &t); } else DPRINT(2, "error: %r\n"); } sleep(1000); } }
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); } } }
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); }
void volumeproc(void *arg) { int fd, n, nf, nnf, i, nlines; static char buf[1024]; char *lines[32]; char *fields[8]; char *subfields[8]; Channel *ctl; int volume, minvolume, maxvolume, nvolume; ctl = arg; threadsetname("volumeproc"); fd = open(volumefile, OREAD); if(fd < 0){ fprint(2, "%s: %r\n", volumefile); threadexits(nil); } for(;;){ n = read(fd, buf, sizeof buf -1); if(n == 0) continue; if(n < 0){ fprint(2, "volumeproc: read: %r\n"); threadexits("volumeproc"); } buf[n] = '\0'; nlines = getfields(buf, lines, nelem(lines), 1, "\n"); for(i = 0; i < nlines; i++){ nf = tokenize(lines[i], fields, nelem(fields)); if(nf == 0) continue; if(nf != 6 || strcmp(fields[0], "volume") || strcmp(fields[1], "out")) continue; minvolume = strtol(fields[3], nil, 0); maxvolume = strtol(fields[4], nil, 0); if(minvolume >= maxvolume) continue; nnf = tokenize(fields[2], subfields, nelem(subfields)); if(nnf <= 0 || nnf > 8){ fprint(2, "volume format error\n"); threadexits(nil); } volume = 0; nvolume = 0; for(i = 0; i < nnf; i++){ volume += strtol(subfields[i], nil, 0); nvolume++; } volume /= nvolume; volume = 100*(volume - minvolume)/(maxvolume-minvolume); chanprint(ctl, "volume value %d", volume); } } }
void nfs3proc(void *v) { Channel *c; SunMsg *m; c = v; threadsetname("nfs3"); while((m = recvp(c)) != nil) threadcreate(rnfs3, m, SunStackSize); }
void mount3proc(void *v) { Channel *c; SunMsg *m; threadsetname("mount1"); c = v; while((m=recvp(c)) != nil) threadcreate(rmount3, m, SunStackSize); }
void keyboardthread(void *) { Timer *timer; Text *t; Rune r; static Alt alts[NKALT+1]; alts[KTimer].c = nil; alts[KTimer].v = nil; alts[KTimer].op = CHANNOP; alts[KKey].c = keyboardctl->c; alts[KKey].v = &r; alts[KKey].op = CHANRCV; alts[NKALT].op = CHANEND; timer = nil; threadsetname("keyboardthread"); for(;;){ switch(alt(alts)){ case KTimer: timerstop(timer); alts[KTimer].c = nil; alts[KTimer].op = CHANNOP; break; case KKey: casekeyboard: typetext = rowwhich(&row, mouse->xy, r, TRUE); t = typetext; if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright)) /* scrolling doesn't change activecol */ activecol = t->col; if(timer != nil) timercancel(timer); if(t!=nil){ texttype(t, r); timer = timerstart(500); alts[KTimer].c = timer->c; alts[KTimer].op = CHANRCV; }else{ timer = nil; alts[KTimer].c = nil; alts[KTimer].op = CHANNOP; } if(nbrecv(keyboardctl->c, &r) > 0) goto casekeyboard; flushimage(display, 1); break; } } }
void cddbproc(void *v) { Drive *d; Toc t; threadsetname("cddbproc"); d = v; while(recv(d->cdbreq, &t)) if(cddbfilltoc(&t) == 0) send(d->cdbreply, &t); }
static void icachewritecoord(void *v) { int i, err; Index *ix; AState as; USED(v); threadsetname("icachewritecoord"); ix = mainindex; iwrite.as = icachestate(); for(;;){ trace(TraceProc, "icachewritecoord sleep"); waitforkick(&iwrite.round); trace(TraceWork, "start"); as = icachestate(); if(as.arena==iwrite.as.arena && as.aa==iwrite.as.aa){ /* will not be able to do anything more than last flush - kick disk */ trace(TraceProc, "icachewritecoord kick dcache"); kickdcache(); trace(TraceProc, "icachewritecoord kicked dcache"); goto SkipWork; /* won't do anything; don't bother rewriting bloom filter */ } iwrite.as = as; trace(TraceProc, "icachewritecoord start flush"); if(iwrite.as.arena){ for(i=0; i<ix->nsects; i++) send(ix->sects[i]->writechan, 0); if(ix->bloom) send(ix->bloom->writechan, 0); err = 0; for(i=0; i<ix->nsects; i++) err |= recvul(ix->sects[i]->writedonechan); if(ix->bloom) err |= recvul(ix->bloom->writedonechan); trace(TraceProc, "icachewritecoord donewrite err=%d", err); if(err == 0){ setatailstate(&iwrite.as); } } SkipWork: icacheclean(nil); /* wake up anyone waiting */ trace(TraceWork, "finish"); addstat(StatIcacheFlush, 1); } }
void acmeerrorproc(void *) { char *buf; int n; threadsetname("acmeerrorproc"); buf = emalloc(8192+1); while((n=read(errorfd, buf, 8192)) >= 0){ buf[n] = '\0'; sendp(cerr, estrdup(buf)); } }
void plumbproc(void *) { Plumbmsg *m; threadsetname("plumbproc"); for(;;){ m = plumbrecv(plumbwebfd); if(m == nil) threadexits(nil); sendp(cplumb, m); } }
void plumbsendproc(void* v) { Plumbmsg *m; threadsetname("plumbsendproc"); for(;;){ m = plumbrecvfid(plumbsendmailfd); sendp(cplumbsend, m); if(m == nil) threadexits(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); }
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 statusreader(void *u) { Serialport *p; Serial *ser; p = u; ser = p->s; threadsetname("statusreaderproc"); while(plreadstatus(p) >= 0) ; fprint(2, "serial: statusreader exiting\n"); closedev(ser->dev); }
static void _ioproc(void *arg) { Rune r; Keyboardctl *kc; kc = arg; threadsetname("kbdproc"); for(;;) { if(_displayrdkbd(display, &r) < 0) threadexits("read error"); send(kc->c, &r); } }
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); } }