ref: f96bae7a1d09fede6a6c884c166c93ec37f4a60d
parent: dd454a23cfd5bf956f4d1be7b35ae6e5fd94be0a
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);
--
⑨