kbdfs: simplify ctlproc by putting 9p handling in its own coroutine
This commit is contained in:
parent
c39aecc111
commit
241cd31448
1 changed files with 159 additions and 180 deletions
|
@ -19,7 +19,6 @@ enum {
|
||||||
|
|
||||||
Rawon= 0,
|
Rawon= 0,
|
||||||
Rawoff,
|
Rawoff,
|
||||||
Kbdflush,
|
|
||||||
|
|
||||||
STACK = 8*1024,
|
STACK = 8*1024,
|
||||||
};
|
};
|
||||||
|
@ -83,27 +82,30 @@ char Einuse[] = "file in use";
|
||||||
char Enonexist[] = "file does not exist";
|
char Enonexist[] = "file does not exist";
|
||||||
char Ebadspec[] = "bad attach specifier";
|
char Ebadspec[] = "bad attach specifier";
|
||||||
char Ewalk[] = "walk in non directory";
|
char Ewalk[] = "walk in non directory";
|
||||||
char Efront[] = "the front fell off";
|
char Ephase[] = "the front fell off";
|
||||||
|
char Eintr[] = "interrupted";
|
||||||
|
|
||||||
int scanfd;
|
int scanfd;
|
||||||
int ledsfd;
|
int ledsfd;
|
||||||
int consfd;
|
int consfd;
|
||||||
|
|
||||||
int kbdopen;
|
int kbdopen;
|
||||||
int consopen;
|
|
||||||
int consctlopen;
|
int consctlopen;
|
||||||
|
|
||||||
int debug;
|
int debug;
|
||||||
|
|
||||||
Channel *keychan; /* Key */
|
Channel *keychan; /* chan(Key) */
|
||||||
|
|
||||||
Channel *reqchan; /* Req* */
|
Channel *kbdreqchan; /* chan(Req*) */
|
||||||
Channel *ctlchan; /* int */
|
Channel *consreqchan; /* chan(Req*) */
|
||||||
|
|
||||||
Channel *rawchan; /* Rune */
|
Channel *ctlchan; /* chan(int) */
|
||||||
Channel *runechan; /* Rune */
|
|
||||||
Channel *linechan; /* char * */
|
Channel *rawchan; /* chan(Rune) */
|
||||||
Channel *kbdchan; /* char* */
|
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.
|
* The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
|
||||||
|
@ -366,7 +368,7 @@ keyproc(void *)
|
||||||
nb = 0;
|
nb = 0;
|
||||||
while(recv(keychan, &key) > 0){
|
while(recv(keychan, &key) > 0){
|
||||||
if(key.down && key.r)
|
if(key.down && key.r)
|
||||||
nbsend(rawchan, &key.r);
|
send(rawchan, &key.r);
|
||||||
|
|
||||||
rb[0] = 0;
|
rb[0] = 0;
|
||||||
for(i=0; i<nb && cb[i] != key.c; i++)
|
for(i=0; i<nb && cb[i] != key.c; i++)
|
||||||
|
@ -389,7 +391,7 @@ keyproc(void *)
|
||||||
}
|
}
|
||||||
rb[0] = 'k';
|
rb[0] = 'k';
|
||||||
}
|
}
|
||||||
if(rb[0]){
|
if(rb[0] && kbdopen){
|
||||||
s = utfconv(rb, nb+1);
|
s = utfconv(rb, nb+1);
|
||||||
if(nbsendp(kbdchan, s) <= 0)
|
if(nbsendp(kbdchan, s) <= 0)
|
||||||
free(s);
|
free(s);
|
||||||
|
@ -551,6 +553,7 @@ lineproc(void *aux)
|
||||||
Rune rb[256], r;
|
Rune rb[256], r;
|
||||||
Channel *cook;
|
Channel *cook;
|
||||||
int nr, done;
|
int nr, done;
|
||||||
|
char *s;
|
||||||
|
|
||||||
cook = aux;
|
cook = aux;
|
||||||
|
|
||||||
|
@ -585,34 +588,115 @@ lineproc(void *aux)
|
||||||
fprint(1, "%C", r);
|
fprint(1, "%C", r);
|
||||||
}
|
}
|
||||||
} while(!done && nr < nelem(rb));
|
} 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
|
* Reads Tread and Tflush requests from reqchan and responds
|
||||||
* relay data between 9p and rawchan / kbdchan.
|
* 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
|
void
|
||||||
ctlproc(void *)
|
ctlproc(void *)
|
||||||
{
|
{
|
||||||
struct {
|
Channel *cook, *aconsr[2], *akbdr[2];
|
||||||
Req *h;
|
enum { ACTL, ARUNE, AEND };
|
||||||
Req **t;
|
Alt a[AEND+1];
|
||||||
} qcons, qkbd, *q;
|
|
||||||
enum { Areq, Actl, Arune, Aline, Akbd, Aend };
|
|
||||||
Alt a[Aend+1];
|
|
||||||
Req *req;
|
|
||||||
Fid *fid;
|
|
||||||
Rune r;
|
Rune r;
|
||||||
char *s, *b, *p, *e;
|
int c, raw;
|
||||||
int c, n, raw;
|
char *s;
|
||||||
Channel *cook;
|
|
||||||
|
|
||||||
threadsetname("ctlproc");
|
threadsetname("ctlproc");
|
||||||
|
|
||||||
cook = chancreate(sizeof(Rune), 0);
|
|
||||||
|
|
||||||
if(scanfd >= 0)
|
if(scanfd >= 0)
|
||||||
proccreate(scanproc, nil, STACK); /* scanfd -> keychan */
|
proccreate(scanproc, nil, STACK); /* scanfd -> keychan */
|
||||||
if(consfd >= 0)
|
if(consfd >= 0)
|
||||||
|
@ -620,156 +704,59 @@ ctlproc(void *)
|
||||||
|
|
||||||
threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */
|
threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */
|
||||||
threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */
|
threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */
|
||||||
threadcreate(lineproc, cook, STACK); /* cook -> linechan */
|
|
||||||
|
aconsr[0] = consreqchan;
|
||||||
|
aconsr[1] = conschan;
|
||||||
|
threadcreate(reqproc, aconsr, STACK); /* consreqchan,conschan -> respond */
|
||||||
|
|
||||||
|
akbdr[0] = kbdreqchan;
|
||||||
|
akbdr[1] = kbdchan;
|
||||||
|
threadcreate(reqproc, akbdr, STACK); /* kbdreqchan,kbdchan -> respond */
|
||||||
|
|
||||||
|
cook = chancreate(sizeof(Rune), 0);
|
||||||
|
threadcreate(lineproc, cook, STACK); /* cook -> conschan */
|
||||||
|
|
||||||
raw = 0;
|
raw = 0;
|
||||||
|
|
||||||
b = p = e = nil;
|
a[ACTL].c = ctlchan;
|
||||||
|
a[ACTL].v = &c;
|
||||||
|
a[ACTL].op = CHANRCV;
|
||||||
|
|
||||||
qcons.h = nil;
|
a[ARUNE].c = runechan;
|
||||||
qcons.t = &qcons.h;
|
a[ARUNE].v = &r;
|
||||||
qkbd.h = nil;
|
a[ARUNE].op = CHANRCV;
|
||||||
qkbd.t = &qkbd.h;
|
|
||||||
|
|
||||||
memset(a, 0, sizeof a);
|
a[AEND].op = CHANEND;
|
||||||
|
|
||||||
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[Arune].c = runechan;
|
|
||||||
a[Arune].v = &r;
|
|
||||||
a[Arune].op = CHANRCV;
|
|
||||||
|
|
||||||
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(;;){
|
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)){
|
switch(alt(a)){
|
||||||
case Areq:
|
case ACTL:
|
||||||
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:
|
|
||||||
switch(c){
|
switch(c){
|
||||||
case Rawoff:
|
case Rawoff:
|
||||||
case Rawon:
|
case Rawon:
|
||||||
if(raw = (c == Rawon)){
|
if(raw = (c == Rawon)){
|
||||||
while(s = nbrecvp(linechan))
|
r = 0;
|
||||||
free(s);
|
nbsend(cook, &r);
|
||||||
r = '\0';
|
|
||||||
send(cook, &r);
|
|
||||||
free(b);
|
|
||||||
b = nil;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case Kbdflush:
|
|
||||||
while(s = nbrecvp(kbdchan))
|
|
||||||
free(s);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ARUNE:
|
||||||
case Arune:
|
|
||||||
if(kbdopen){
|
if(kbdopen){
|
||||||
s = emalloc9p(UTFmax+2);
|
s = emalloc9p(UTFmax+2);
|
||||||
s[0] = 'c';
|
s[0] = 'c';
|
||||||
s[1+runetochar(s+1, &r)] = 0;
|
s[1+runetochar(s+1, &r)] = 0;
|
||||||
goto Havekbd;
|
if(nbsendp(kbdchan, s) <= 0)
|
||||||
|
free(s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(raw){
|
if(raw){
|
||||||
s = emalloc9p(UTFmax+1);
|
s = emalloc9p(UTFmax+1);
|
||||||
s[runetochar(s, &r)] = 0;
|
s[runetochar(s, &r)] = 0;
|
||||||
} else {
|
if(nbsendp(conschan, s) <= 0)
|
||||||
nbsend(cook, &r);
|
free(s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* no break */
|
nbsend(cook, &r);
|
||||||
|
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1011,10 +998,6 @@ fsopen(Req *r)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
kbdopen++;
|
kbdopen++;
|
||||||
sendul(ctlchan, Kbdflush);
|
|
||||||
break;
|
|
||||||
case Qcons:
|
|
||||||
consopen++;
|
|
||||||
break;
|
break;
|
||||||
case Qconsctl:
|
case Qconsctl:
|
||||||
consctlopen++;
|
consctlopen++;
|
||||||
|
@ -1055,19 +1038,18 @@ fsread(Req *r)
|
||||||
f = r->fid;
|
f = r->fid;
|
||||||
switch((ulong)f->qid.path){
|
switch((ulong)f->qid.path){
|
||||||
default:
|
default:
|
||||||
respond(r, Efront);
|
respond(r, Ephase);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Qroot:
|
case Qroot:
|
||||||
r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset,
|
r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset,
|
||||||
r->ifcall.count, r->ifcall.count);
|
r->ifcall.count, r->ifcall.count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qkbd:
|
case Qkbd:
|
||||||
case Qcons:
|
sendp(kbdreqchan, r);
|
||||||
sendp(reqchan, r);
|
return;
|
||||||
|
case Qcons:
|
||||||
|
sendp(consreqchan, r);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Qkbmap:
|
case Qkbmap:
|
||||||
kbmapread(r);
|
kbmapread(r);
|
||||||
return;
|
return;
|
||||||
|
@ -1085,7 +1067,7 @@ fswrite(Req *r)
|
||||||
f = r->fid;
|
f = r->fid;
|
||||||
switch((ulong)f->qid.path){
|
switch((ulong)f->qid.path){
|
||||||
default:
|
default:
|
||||||
respond(r, Efront);
|
respond(r, Ephase);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Qcons:
|
case Qcons:
|
||||||
|
@ -1134,8 +1116,10 @@ fsflush(Req *r)
|
||||||
{
|
{
|
||||||
switch((ulong)r->oldreq->fid->qid.path) {
|
switch((ulong)r->oldreq->fid->qid.path) {
|
||||||
case Qkbd:
|
case Qkbd:
|
||||||
|
sendp(kbdreqchan, r);
|
||||||
|
return;
|
||||||
case Qcons:
|
case Qcons:
|
||||||
sendp(reqchan, r);
|
sendp(consreqchan, r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
respond(r, nil);
|
respond(r, nil);
|
||||||
|
@ -1156,11 +1140,7 @@ fsdestroyfid(Fid *f)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Qkbd:
|
case Qkbd:
|
||||||
if(--kbdopen == 0)
|
kbdopen--;
|
||||||
sendul(ctlchan, Kbdflush);
|
|
||||||
break;
|
|
||||||
case Qcons:
|
|
||||||
consopen--;
|
|
||||||
break;
|
break;
|
||||||
case Qconsctl:
|
case Qconsctl:
|
||||||
if(--consctlopen == 0)
|
if(--consctlopen == 0)
|
||||||
|
@ -1278,16 +1258,15 @@ threadmain(int argc, char** argv)
|
||||||
if((consfd = open(*argv, OREAD)) < 0)
|
if((consfd = open(*argv, OREAD)) < 0)
|
||||||
fprint(2, "%s: warning: can't open %s: %r\n", argv0, *argv);
|
fprint(2, "%s: warning: can't open %s: %r\n", argv0, *argv);
|
||||||
|
|
||||||
keychan = chancreate(sizeof(Key), 8);
|
consreqchan = chancreate(sizeof(Req*), 0);
|
||||||
reqchan = chancreate(sizeof(Req*), 0);
|
kbdreqchan = chancreate(sizeof(Req*), 0);
|
||||||
ctlchan = chancreate(sizeof(int), 0);
|
|
||||||
rawchan = chancreate(sizeof(Rune), 16);
|
|
||||||
runechan = chancreate(sizeof(Rune), 32);
|
|
||||||
linechan = chancreate(sizeof(char*), 16);
|
|
||||||
kbdchan = chancreate(sizeof(char*), 16);
|
|
||||||
|
|
||||||
if(!(keychan && reqchan && ctlchan && rawchan && runechan && linechan && kbdchan))
|
keychan = chancreate(sizeof(Key), 8);
|
||||||
sysfatal("allocating chans");
|
ctlchan = chancreate(sizeof(int), 0);
|
||||||
|
rawchan = chancreate(sizeof(Rune), 0);
|
||||||
|
runechan = chancreate(sizeof(Rune), 32);
|
||||||
|
conschan = chancreate(sizeof(char*), 16);
|
||||||
|
kbdchan = chancreate(sizeof(char*), 16);
|
||||||
|
|
||||||
elevate();
|
elevate();
|
||||||
procrfork(ctlproc, nil, STACK, RFNAMEG|RFNOTEG);
|
procrfork(ctlproc, nil, STACK, RFNAMEG|RFNOTEG);
|
||||||
|
|
Loading…
Reference in a new issue