ref: bc4515d8003031b9b3b4a7d34b8fbd9bdfe1a439
parent: e056624897daf8446708a73bf7eecb136fb441eb
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Tue Jun 7 00:14:35 EDT 2011
kbdfs: simplify ctlproc by putting 9p handling in its own coroutine
--- a/sys/src/cmd/aux/kbdfs/kbdfs.c
+++ b/sys/src/cmd/aux/kbdfs/kbdfs.c
@@ -19,7 +19,6 @@
Rawon= 0,
Rawoff,
- Kbdflush,
STACK = 8*1024,
};
@@ -83,7 +82,8 @@
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;
@@ -90,21 +90,23 @@
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.
* A 'standard' keyboard doesn't produce anything above 0x58.
@@ -366,7 +368,7 @@
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 @@
}
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 @@
Rune rb[256], r;
Channel *cook;
int nr, done;
-
+ char *s;
+
cook = aux;
threadsetname("lineproc");@@ -585,34 +588,115 @@
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,157 +704,60 @@
threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */
threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */
- threadcreate(lineproc, cook, STACK); /* cook -> linechan */
- raw = 0;
+ aconsr[0] = consreqchan;
+ aconsr[1] = conschan;
+ threadcreate(reqproc, aconsr, STACK); /* consreqchan,conschan -> respond */
- b = p = e = nil;
+ akbdr[0] = kbdreqchan;
+ akbdr[1] = kbdchan;
+ threadcreate(reqproc, akbdr, STACK); /* kbdreqchan,kbdchan -> respond */
- qcons.h = nil;
- qcons.t = &qcons.h;
- qkbd.h = nil;
- qkbd.t = &qkbd.h;
+ cook = chancreate(sizeof(Rune), 0);
+ threadcreate(lineproc, cook, STACK); /* cook -> conschan */
- memset(a, 0, sizeof a);
+ raw = 0;
- a[Areq].c = reqchan;
- a[Areq].v = &req;
- a[Areq].op = CHANRCV;
+ a[ACTL].c = ctlchan;
+ a[ACTL].v = &c;
+ a[ACTL].op = CHANRCV;
- a[Actl].c = ctlchan;
- a[Actl].v = &c;
- a[Actl].op = CHANRCV;
+ a[ARUNE].c = runechan;
+ a[ARUNE].v = &r;
+ a[ARUNE].op = CHANRCV;
- a[Arune].c = runechan;
- a[Arune].v = &r;
- a[Arune].op = CHANRCV;
+ a[AEND].op = CHANEND;
- a[Aline].c = linechan;
- a[Aline].v = &s;
- a[Aline].op = CHANRCV;
-
- a[Akbd].c = kbdchan;
- a[Akbd].v = &s;
- a[Akbd].op = CHANRCV;
-
- 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;
- }
- }
+ nbsend(cook, &r);
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);
- break;
}
}
}
@@ -1011,11 +998,7 @@
return;
}
kbdopen++;
- sendul(ctlchan, Kbdflush);
break;
- case Qcons:
- consopen++;
- break;
case Qconsctl:
consctlopen++;
break;
@@ -1055,19 +1038,18 @@
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 @@
f = r->fid;
switch((ulong)f->qid.path){default:
- respond(r, Efront);
+ respond(r, Ephase);
return;
case Qcons:
@@ -1134,8 +1116,10 @@
{ 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,12 +1140,8 @@
}
break;
case Qkbd:
- if(--kbdopen == 0)
- sendul(ctlchan, Kbdflush);
+ kbdopen--;
break;
- case Qcons:
- consopen--;
- break;
case Qconsctl:
if(--consctlopen == 0)
sendul(ctlchan, Rawoff);
@@ -1278,16 +1258,15 @@
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);
--
⑨