summaryrefslogtreecommitdiff
path: root/sys/src/cmd/rio
diff options
context:
space:
mode:
authorJacob Moody <moody@posixcafe.org>2022-08-21 22:24:45 +0000
committerJacob Moody <moody@posixcafe.org>2022-08-21 22:24:45 +0000
commit6c8de2713c34622799504f9817afe6876c5621cf (patch)
tree53c0c2158472165514455977924695ffa8de1934 /sys/src/cmd/rio
parentaea866a49300a5e31e737d8fe54763711e693f05 (diff)
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.
Diffstat (limited to 'sys/src/cmd/rio')
-rw-r--r--sys/src/cmd/rio/dat.h17
-rw-r--r--sys/src/cmd/rio/rio.c105
-rw-r--r--sys/src/cmd/rio/wind.c4
-rw-r--r--sys/src/cmd/rio/xfid.c4
4 files changed, 83 insertions, 47 deletions
diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h
index 6d9ba8495..bca6cfc79 100644
--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -121,12 +121,6 @@ struct Mouseinfo
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 nwindow;
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;
diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c
index 982272183..d3cd581de 100644
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -198,6 +198,8 @@ threadmain(int argc, char *argv[])
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 @@ killprocs(void)
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:
- free(s);
- continue;
+ break;
+ case Tapoff:
+ mode = Mnorm;
+ break;
}
- out = input == nil ? nil : input->ck;
- goto Send;
- case Kdev:
- switch(mode){
- case Mnorm:
- out = input == nil ? nil : input->ck;
+ free(ctl);
+ break;
+ case Afrom:
+ if(cur == nil){
+ free(s);
break;
- case Mtap:
- out = totap;
+ }
+ 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;
}
- 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;
}
}
diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c
index d6e6c3ff6..0bb63c83a 100644
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -83,13 +83,14 @@ wcurrent(Window *w)
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 @@ wclunk(Window *w)
return;
w->deleted = TRUE;
if(w == input){
+ sendp(wintap, nil);
input = nil;
riosetcursor(nil);
}
diff --git a/sys/src/cmd/rio/xfid.c b/sys/src/cmd/rio/xfid.c
index 383d2cee7..cd7f57387 100644
--- a/sys/src/cmd/rio/xfid.c
+++ b/sys/src/cmd/rio/xfid.c
@@ -308,7 +308,7 @@ xfidopen(Xfid *x)
}
break;
case Qtap:
- chanprint(fromtap, "%c", Tapon);
+ chanprint(ctltap, "%c", Tapon);
break;
}
t.qid = x->f->qid;
@@ -365,7 +365,7 @@ xfidclose(Xfid *x)
w->wctlopen = FALSE;
break;
case Qtap:
- chanprint(fromtap, "%c", Tapoff);
+ chanprint(ctltap, "%c", Tapoff);
break;
}
wclose(w);