ref: 6c8de2713c34622799504f9817afe6876c5621cf
parent: aea866a49300a5e31e737d8fe54763711e693f05
author: Jacob Moody <moody@posixcafe.org>
date: Sun Aug 21 18:24:45 EDT 2022
rio: kbdtap deadlocks are verboden This should make kbdtap related deadlocks impossible. The tap thread has been rewritten to use one alt which always allows for the window handling code to nofiy us regardless if we're send'ing or recv'ing. We also move the start/stop messages to their own channel and can the reset code for now.
--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -121,12 +121,6 @@
uchar qfull; /* filled the queue; no more recording until client comes back */
};
-enum{
- Tapon = 'b',
- Tapoff = 'e',
- Tapreset = 'r',
-};
-
struct Window
{
Ref;
@@ -322,8 +316,15 @@
int snarffd;
int gotscreen;
int servekbd;
-Channel *fromtap; /* input from kbd tap program to window */
-Channel *totap; /* our keyboard input to tap program */
+
+enum{
+ Tapon = 'b',
+ Tapoff = 'e',
+};
+Channel *ctltap; /* on/off messages */
+Channel *fromtap; /* input from kbd tap program to window */
+Channel *totap; /* our keyboard input to tap program */
+Channel *wintap; /* tell the tapthread which Window to send to */
Window *input;
QLock all; /* BUG */
Filsys *filsys;
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -198,6 +198,8 @@
error("can't find keyboard");
totap = chancreate(sizeof(char*), 32);
fromtap = chancreate(sizeof(char*), 32);
+ wintap = chancreate(sizeof(Window*), 0);
+ ctltap = chancreate(sizeof(Window*), 0);
proccreate(keyboardtap, nil, STACK);
wscreen = allocscreen(screen, background, 0);
@@ -339,62 +341,93 @@
void
keyboardtap(void*)
{
- char *s;
- Channel *out;
+ char *s, *ctl;
+ Window *w, *cur;
int mode;
- enum { Kdev, Ktap, NALT};
+ enum { Awin, Actl, Afrom, Adev, Ato, Ainp, NALT };
enum { Mnorm, Mtap };
threadsetname("keyboardtap");
static Alt alts[NALT+1];
- alts[Kdev].c = kbdchan;
- alts[Kdev].v = &s;
- alts[Kdev].op = CHANRCV;
- alts[Ktap].c = fromtap;
- alts[Ktap].v = &s;
- alts[Ktap].op = CHANRCV;
+ /* ctl */
+ alts[Awin].c = wintap;
+ alts[Awin].v = &w;
+ alts[Awin].op = CHANRCV;
+ alts[Actl].c = ctltap;
+ alts[Actl].v = &ctl;
+ alts[Actl].op = CHANRCV;
+ /* kbd input */
+ alts[Afrom].c = fromtap;
+ alts[Afrom].v = &s;
+ alts[Afrom].op = CHANRCV;
+ alts[Adev].c = kbdchan;
+ alts[Adev].v = &s;
+ alts[Adev].op = CHANRCV;
+ /* kbd output */
+ alts[Ato].c = totap;
+ alts[Ato].v = &s;
+ alts[Ato].op = CHANNOP;
+ alts[Ainp].c = nil;
+ alts[Ainp].v = &s;
+ alts[Ainp].op = CHANNOP;
alts[NALT].op = CHANEND;
- out = nil;
+ cur = nil;
mode = Mnorm;
for(;;)
switch(alt(alts)){
- case Ktap:
- switch(*s){
- case 'K': case 'k': case 'c':
+ case Awin:
+ cur = w;
+ if(cur != nil){
+ alts[Ainp].c = cur->ck;
break;
- case Tapreset:
- if(mode != Mtap)
- goto Next;
- goto Send;
- case Tapoff:
- mode = Mnorm;
- goto Next;
+ }
+ if(alts[Ainp].op != CHANNOP || alts[Ato].op != CHANNOP)
+ free(s);
+ goto Reset;
+ case Actl:
+ switch(*ctl){
case Tapon:
mode = Mtap;
- /* fallthrough */
- default:
- Next:
+ break;
+ case Tapoff:
+ mode = Mnorm;
+ break;
+ }
+ free(ctl);
+ break;
+ case Afrom:
+ if(cur == nil){
free(s);
- continue;
+ break;
}
- out = input == nil ? nil : input->ck;
- goto Send;
- case Kdev:
- switch(mode){
- case Mnorm:
- out = input == nil ? nil : input->ck;
+ alts[Afrom].op = CHANNOP;
+ alts[Adev].op = CHANNOP;
+ alts[Ato].op = CHANNOP;
+ alts[Ainp].op = CHANSND;
+ break;
+ case Adev:
+ if(mode == Mnorm && cur == nil){
+ free(s);
break;
- case Mtap:
- out = totap;
- break;
}
- Send:
+ alts[Afrom].op = CHANNOP;
+ alts[Adev].op = CHANNOP;
+ if(mode == Mnorm)
+ alts[Ainp].op = CHANSND;
+ else
+ alts[Ato].op = CHANSND;
+ break;
+ case Ainp:
if(*s == 'k' || *s == 'K')
shiftdown = utfrune(s+1, Kshift) != nil;
- if(out == nil || sendp(out, s) <= 0)
- free(s);
+ case Ato:
+ Reset:
+ alts[Ainp].op = CHANNOP;
+ alts[Ato].op = CHANNOP;
+ alts[Afrom].op = CHANRCV;
+ alts[Adev].op = CHANRCV;
break;
}
}
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -83,13 +83,14 @@
Channel *c;
if(input == nil){
+ sendp(wintap, w);
input = w;
return;
}
if(w == input)
return;
- chanprint(fromtap, "%c", Tapreset);
incref(input);
+ sendp(wintap, w);
c = chancreate(sizeof(Window*), 0);
wsendctlmesg(input, Repaint, ZR, c);
sendp(c, w); /* send the new input */
@@ -1304,6 +1305,7 @@
return;
w->deleted = TRUE;
if(w == input){
+ sendp(wintap, nil);
input = nil;
riosetcursor(nil);
}
--- a/sys/src/cmd/rio/xfid.c
+++ b/sys/src/cmd/rio/xfid.c
@@ -308,7 +308,7 @@
}
break;
case Qtap:
- chanprint(fromtap, "%c", Tapon);
+ chanprint(ctltap, "%c", Tapon);
break;
}
t.qid = x->f->qid;
@@ -365,7 +365,7 @@
w->wctlopen = FALSE;
break;
case Qtap:
- chanprint(fromtap, "%c", Tapoff);
+ chanprint(ctltap, "%c", Tapoff);
break;
}
wclose(w);