diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-06-07 04:14:35 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-06-07 04:14:35 +0000 |
commit | 241cd314480142a7281e677aaeb180f7b65f0664 (patch) | |
tree | a49c966dd35eea7877fe73199062d0e2e40088dd | |
parent | c39aecc11186aa7ec7e4981614bfa3765d4af99e (diff) | |
download | plan9front-241cd314480142a7281e677aaeb180f7b65f0664.tar.xz |
kbdfs: simplify ctlproc by putting 9p handling in its own coroutine
-rw-r--r-- | sys/src/cmd/aux/kbdfs/kbdfs.c | 327 |
1 files changed, 153 insertions, 174 deletions
diff --git a/sys/src/cmd/aux/kbdfs/kbdfs.c b/sys/src/cmd/aux/kbdfs/kbdfs.c index 004e99e76..fce22aa2a 100644 --- a/sys/src/cmd/aux/kbdfs/kbdfs.c +++ b/sys/src/cmd/aux/kbdfs/kbdfs.c @@ -19,7 +19,6 @@ enum { Rawon= 0, Rawoff, - Kbdflush, STACK = 8*1024, }; @@ -83,27 +82,30 @@ char Einuse[] = "file in use"; char Enonexist[] = "file does not exist"; char Ebadspec[] = "bad attach specifier"; char Ewalk[] = "walk in non directory"; -char Efront[] = "the front fell off"; +char Ephase[] = "the front fell off"; +char Eintr[] = "interrupted"; int scanfd; int ledsfd; int consfd; int kbdopen; -int consopen; int consctlopen; int debug; -Channel *keychan; /* Key */ +Channel *keychan; /* chan(Key) */ -Channel *reqchan; /* Req* */ -Channel *ctlchan; /* int */ +Channel *kbdreqchan; /* chan(Req*) */ +Channel *consreqchan; /* chan(Req*) */ -Channel *rawchan; /* Rune */ -Channel *runechan; /* Rune */ -Channel *linechan; /* char * */ -Channel *kbdchan; /* char* */ +Channel *ctlchan; /* chan(int) */ + +Channel *rawchan; /* chan(Rune) */ +Channel *runechan; /* chan(Rune) */ + +Channel *conschan; /* chan(char*) */ +Channel *kbdchan; /* chan(char*) */ /* * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard. @@ -366,7 +368,7 @@ keyproc(void *) nb = 0; while(recv(keychan, &key) > 0){ if(key.down && key.r) - nbsend(rawchan, &key.r); + send(rawchan, &key.r); rb[0] = 0; for(i=0; i<nb && cb[i] != key.c; i++) @@ -389,7 +391,7 @@ keyproc(void *) } rb[0] = 'k'; } - if(rb[0]){ + if(rb[0] && kbdopen){ s = utfconv(rb, nb+1); if(nbsendp(kbdchan, s) <= 0) free(s); @@ -551,7 +553,8 @@ lineproc(void *aux) Rune rb[256], r; Channel *cook; int nr, done; - + char *s; + cook = aux; threadsetname("lineproc"); @@ -585,34 +588,115 @@ lineproc(void *aux) fprint(1, "%C", r); } } while(!done && nr < nelem(rb)); - sendp(linechan, utfconv(rb, nr)); + s = utfconv(rb, nr); + if(nbsendp(conschan, s) <= 0) + free(s); } } /* - * Queue reads to cons and kbd, flushing and - * relay data between 9p and rawchan / kbdchan. + * Reads Tread and Tflush requests from reqchan and responds + * to them with data received on the string channel. + */ +void +reqproc(void *aux) +{ + enum { AREQ, ASTR, AEND }; + Alt a[AEND+1]; + Channel **ac; + Req *r, *q, **qq; + char *s, *p, *e; + int n; + + threadsetname("reqproc"); + + s = nil; + p = nil; + + q = nil; + qq = &q; + + ac = aux; + a[AREQ].c = ac[0]; /* chan(Req*) */ + a[AREQ].v = &r; + a[ASTR].c = ac[1]; /* chan(char*) */ + a[ASTR].v = &s; + a[AEND].op = CHANEND; + + for(;;){ + a[AREQ].op = CHANRCV; + a[ASTR].op = (q != nil && s == nil) ? CHANRCV : CHANNOP; + switch(alt(a)){ + case AREQ: + if(r->ifcall.type == Tflush){ + Req **rr, **xx; + + for(rr = &q; *rr; rr=xx){ + xx = &((*rr)->aux); + if(*rr == r->oldreq){ + if((*rr = *xx) == nil) + qq = rr; + respond(r->oldreq, Eintr); + break; + } + } + respond(r, nil); + continue; + } else if(r->ifcall.type != Tread){ + respond(r, Ephase); + continue; + } + r->aux = nil; + *qq = r; + qq = &r->aux; + + if(0){ + case ASTR: + p = s; + } else if(s == nil) + continue; + if((r = q) == nil) + continue; + if((q = q->aux) == nil) + qq = &q; + + e = s + strlen(s); + if(p == s && r->fid->qid.path == Qkbd) + e++; /* send terminating \0 if its kbd file */ + + n = e - p; + if(n > r->ifcall.count) + n = r->ifcall.count; + + r->ofcall.count = n; + memmove(r->ofcall.data, p, n); + respond(r, nil); + + p += n; + if(p >= e){ + free(s); + s = nil; + } + } + } +} + +/* + * Keep track of rawing state and distribute the runes from + * runechan to the right channels depending on the state. */ void ctlproc(void *) { - struct { - Req *h; - Req **t; - } qcons, qkbd, *q; - enum { Areq, Actl, Arune, Aline, Akbd, Aend }; - Alt a[Aend+1]; - Req *req; - Fid *fid; + Channel *cook, *aconsr[2], *akbdr[2]; + enum { ACTL, ARUNE, AEND }; + Alt a[AEND+1]; Rune r; - char *s, *b, *p, *e; - int c, n, raw; - Channel *cook; + int c, raw; + char *s; threadsetname("ctlproc"); - cook = chancreate(sizeof(Rune), 0); - if(scanfd >= 0) proccreate(scanproc, nil, STACK); /* scanfd -> keychan */ if(consfd >= 0) @@ -620,156 +704,59 @@ ctlproc(void *) threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */ threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */ - threadcreate(lineproc, cook, STACK); /* cook -> linechan */ - - raw = 0; - - b = p = e = nil; - - qcons.h = nil; - qcons.t = &qcons.h; - qkbd.h = nil; - qkbd.t = &qkbd.h; - memset(a, 0, sizeof a); + aconsr[0] = consreqchan; + aconsr[1] = conschan; + threadcreate(reqproc, aconsr, STACK); /* consreqchan,conschan -> respond */ - a[Areq].c = reqchan; - a[Areq].v = &req; - a[Areq].op = CHANRCV; + akbdr[0] = kbdreqchan; + akbdr[1] = kbdchan; + threadcreate(reqproc, akbdr, STACK); /* kbdreqchan,kbdchan -> respond */ - a[Actl].c = ctlchan; - a[Actl].v = &c; - a[Actl].op = CHANRCV; + cook = chancreate(sizeof(Rune), 0); + threadcreate(lineproc, cook, STACK); /* cook -> conschan */ - a[Arune].c = runechan; - a[Arune].v = &r; - a[Arune].op = CHANRCV; + raw = 0; - a[Aline].c = linechan; - a[Aline].v = &s; - a[Aline].op = CHANRCV; + a[ACTL].c = ctlchan; + a[ACTL].v = &c; + a[ACTL].op = CHANRCV; - a[Akbd].c = kbdchan; - a[Akbd].v = &s; - a[Akbd].op = CHANRCV; + a[ARUNE].c = runechan; + a[ARUNE].v = &r; + a[ARUNE].op = CHANRCV; - a[Aend].op = CHANEND; + a[AEND].op = CHANEND; for(;;){ - s = nil; - - if(kbdopen){ - a[Arune].op = qkbd.h ? CHANRCV : CHANNOP; - a[Akbd].op = qkbd.h ? CHANRCV : CHANNOP; - a[Aline].op = CHANNOP; - }else{ - a[Arune].op = (b == nil) ? CHANRCV : CHANNOP; - a[Akbd].op = CHANRCV; - a[Aline].op = (b == nil) ? CHANRCV : CHANNOP; - } - switch(alt(a)){ - case Areq: - fid = req->fid; - if(req->ifcall.type == Tflush){ - Req **rr; - - fid = req->oldreq->fid; - q = fid->qid.path == Qcons ? &qcons : &qkbd; - for(rr = &q->h; *rr && *rr != req->oldreq; rr = &((*rr)->aux)) - ; - if(*rr == req->oldreq){ - if((*rr = req->oldreq->aux) == nil) - q->t = rr; - req->oldreq->aux = nil; - respond(req->oldreq, "interrupted"); - } - respond(req, nil); - } else if(req->ifcall.type == Tread){ - q = fid->qid.path == Qcons ? &qcons : &qkbd; - req->aux = nil; - *q->t = req; - q->t = &req->aux; - goto Havereq; - } else - respond(req, Efront); - break; - - case Actl: + case ACTL: switch(c){ case Rawoff: case Rawon: if(raw = (c == Rawon)){ - while(s = nbrecvp(linechan)) - free(s); - r = '\0'; - send(cook, &r); - free(b); - b = nil; + r = 0; + nbsend(cook, &r); } - break; - case Kbdflush: - while(s = nbrecvp(kbdchan)) - free(s); - break; } break; - - case Arune: + case ARUNE: if(kbdopen){ s = emalloc9p(UTFmax+2); s[0] = 'c'; s[1+runetochar(s+1, &r)] = 0; - goto Havekbd; + if(nbsendp(kbdchan, s) <= 0) + free(s); + break; } - if(raw){ s = emalloc9p(UTFmax+1); s[runetochar(s, &r)] = 0; - } else { - nbsend(cook, &r); + if(nbsendp(conschan, s) <= 0) + free(s); break; } - /* no break */ - - case Aline: - b = s; - p = s; - e = s + strlen(s); - - Havereq: - while(b && (req = qcons.h)){ - if((qcons.h = req->aux) == nil) - qcons.t = &qcons.h; - n = e - p; - if(req->ifcall.count < n) - n = req->ifcall.count; - req->ofcall.count = n; - memmove(req->ofcall.data, p, n); - respond(req, nil); - p += n; - if(p >= e){ - free(b); - b = nil; - } - } - break; - - case Akbd: - Havekbd: - if(req = qkbd.h){ - if((qkbd.h = req->aux) == nil) - qkbd.t = &qkbd.h; - n = strlen(s) + 1; - if(n > req->ifcall.count) - respond(req, Eshort); - else { - req->ofcall.count = n; - memmove(req->ofcall.data, s, n); - respond(req, nil); - } - } - free(s); + nbsend(cook, &r); break; } } @@ -1011,10 +998,6 @@ fsopen(Req *r) return; } kbdopen++; - sendul(ctlchan, Kbdflush); - break; - case Qcons: - consopen++; break; case Qconsctl: consctlopen++; @@ -1055,19 +1038,18 @@ fsread(Req *r) f = r->fid; switch((ulong)f->qid.path){ default: - respond(r, Efront); + respond(r, Ephase); return; - case Qroot: r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset, r->ifcall.count, r->ifcall.count); break; - case Qkbd: + sendp(kbdreqchan, r); + return; case Qcons: - sendp(reqchan, r); + sendp(consreqchan, r); return; - case Qkbmap: kbmapread(r); return; @@ -1085,7 +1067,7 @@ fswrite(Req *r) f = r->fid; switch((ulong)f->qid.path){ default: - respond(r, Efront); + respond(r, Ephase); return; case Qcons: @@ -1134,8 +1116,10 @@ fsflush(Req *r) { switch((ulong)r->oldreq->fid->qid.path) { case Qkbd: + sendp(kbdreqchan, r); + return; case Qcons: - sendp(reqchan, r); + sendp(consreqchan, r); return; } respond(r, nil); @@ -1156,11 +1140,7 @@ fsdestroyfid(Fid *f) } break; case Qkbd: - if(--kbdopen == 0) - sendul(ctlchan, Kbdflush); - break; - case Qcons: - consopen--; + kbdopen--; break; case Qconsctl: if(--consctlopen == 0) @@ -1278,17 +1258,16 @@ threadmain(int argc, char** argv) if((consfd = open(*argv, OREAD)) < 0) fprint(2, "%s: warning: can't open %s: %r\n", argv0, *argv); + consreqchan = chancreate(sizeof(Req*), 0); + kbdreqchan = chancreate(sizeof(Req*), 0); + keychan = chancreate(sizeof(Key), 8); - reqchan = chancreate(sizeof(Req*), 0); ctlchan = chancreate(sizeof(int), 0); - rawchan = chancreate(sizeof(Rune), 16); + rawchan = chancreate(sizeof(Rune), 0); runechan = chancreate(sizeof(Rune), 32); - linechan = chancreate(sizeof(char*), 16); + conschan = chancreate(sizeof(char*), 16); kbdchan = chancreate(sizeof(char*), 16); - if(!(keychan && reqchan && ctlchan && rawchan && runechan && linechan && kbdchan)) - sysfatal("allocating chans"); - elevate(); procrfork(ctlproc, nil, STACK, RFNAMEG|RFNOTEG); threadpostmountsrv(&fs, srv, mtpt, MBEFORE); |