ref: 211e5d36cc5b2c2dea557f04d99a8519f906781d
parent: aab506c9903a54bb77d7978ef09c1307d9aacabc
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Thu Aug 9 00:03:03 EDT 2012
page: simplify locking, avoid eenter deadlock on resize
--- a/sys/src/cmd/page.c
+++ b/sys/src/cmd/page.c
@@ -116,6 +116,7 @@
0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
};
+void showpage1(Page *);
void showpage(Page *);
void drawpage(Page *);
Point pagesize(Page *);
@@ -149,7 +150,7 @@
qunlock(&pagelock);
if(up && current == up)
- showpage(p);
+ showpage1(p);
return p;
}
@@ -817,7 +818,8 @@
int fd;
if(p->open && p->image == nil){- if((fd = openpage(p)) >= 0){+ fd = openpage(p);
+ if(fd >= 0){pagegen++;
if((p->image = readimage(display, fd, 1)) == nil)
fprint(2, "readimage: %r\n");
@@ -881,10 +883,11 @@
if(size.x && size.y && newwin){newwin = 0;
resizewin(size);
+ } else {+ lockdisplay(display);
+ drawpage(p);
+ unlockdisplay(display);
}
- lockdisplay(display);
- drawpage(p);
- unlockdisplay(display);
}
qunlock(p);
}
@@ -1125,8 +1128,13 @@
return cmds[i].m;
}
+/*
+ * spawn new proc to load a run of pages starting with p
+ * the display should *not* be locked as it gets called
+ * from recursive page load.
+ */
void
-showpage(Page *p)
+showpage1(Page *p)
{static int nproc;
int oviewgen;
@@ -1148,7 +1156,29 @@
}
}
+/* recursive display lock, called from main proc only */
void
+drawlock(int dolock){+ static int ref = 0;
+ if(dolock){+ if(ref++ == 0)
+ lockdisplay(display);
+ } else {+ if(--ref == 0)
+ unlockdisplay(display);
+ }
+}
+
+
+void
+showpage(Page *p)
+{+ drawlock(0);
+ showpage1(p);
+ drawlock(1);
+}
+
+void
shownext(void)
{Page *p;
@@ -1178,7 +1208,7 @@
if(p == nil)
return;
- esetcursor(&reading);
+ drawlock(0);
qlock(p);
if((fd = openpage(p)) < 0)
goto Out;
@@ -1194,7 +1224,7 @@
close(fd);
Out:
qunlock(p);
- esetcursor(nil);
+ drawlock(1);
}
void
@@ -1213,6 +1243,7 @@
ps.y += 24;
} else
ps = subpt(screen->r.max, screen->r.min);
+ drawlock(0);
if((fd = p->fd) < 0){if(p->open != popenfile)
return;
@@ -1238,14 +1269,16 @@
exits(0);
}
close(fd);
+ drawlock(1);
}
+
void
eresized(int new)
{Page *p;
- lockdisplay(display);
+ drawlock(1);
if(new && getwindow(display, Refnone) == -1)
sysfatal("getwindow: %r"); if(p = current){@@ -1254,7 +1287,7 @@
qunlock(p);
}
}
- unlockdisplay(display);
+ drawlock(0);
}
int cohort = -1;
@@ -1279,7 +1312,7 @@
exits("usage");}
-int
+void
docmd(int i, Mouse *m)
{char buf[NPATH], *s;
@@ -1294,11 +1327,11 @@
rotate = 0;
Unload:
viewgen++;
- unlockdisplay(display);
- esetcursor(&reading);
+ drawlock(0);
unloadpages(0);
- showpage(current);
- return 0;
+ showpage1(current);
+ drawlock(1);
+ break;
case Cupsidedown:
rotate += 90;
case Crotate90:
@@ -1320,7 +1353,7 @@
case Czoomin:
case Czoomout:
if(current == nil || !canqlock(current))
- return 1;
+ break;
o = subpt(m->xy, screen->r.min);
if(i == Czoomin){ if(zoom < 0x40000000){@@ -1335,10 +1368,10 @@
}
drawpage(current);
qunlock(current);
- return 1;
+ break;
case Cwrite:
if(current == nil || !canqlock(current))
- return 1;
+ break;
if(current->image){s = nil;
if(current->up && current->up != root)
@@ -1360,29 +1393,25 @@
}
}
qunlock(current);
- return 1;
+ break;
case Cext:
if(current == nil || !canqlock(current))
- return 1;
+ break;
showext(current);
qunlock(current);
- return 1;
+ break;
case Cnext:
- unlockdisplay(display);
shownext();
- return 0;
+ break;
case Cprev:
- unlockdisplay(display);
showprev();
- return 0;
+ break;
case Czerox:
- unlockdisplay(display);
zerox(current);
- return 0;
+ break;
case Cquit:
exits(0);
}
- return 1;
}
void
@@ -1445,6 +1474,8 @@
ground = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
display->locking = 1;
unlockdisplay(display);
+ drawlock(1);
+
einit(Ekeyboard|Emouse);
eplumb(Eplumb, "image");
memset(&m, 0, sizeof(m));
@@ -1451,7 +1482,6 @@
if((nullfd = open("/dev/null", ORDWR)) < 0) sysfatal("open: %r");current = root = addpage(nil, "", nil, nil, -1);
-
if(*argv == nil && !imode)
addpage(root, "stdin", popenfile, strdup("/fd/0"), -1);for(; *argv; argv++)
@@ -1458,10 +1488,12 @@
addpage(root, shortname(*argv), popenfile, strdup(*argv), -1);
for(;;){+ drawlock(0);
i=event(&e);
+ drawlock(1);
+
switch(i){case Emouse:
- lockdisplay(display);
m = e.mouse;
if(m.buttons & 1){ if(current && canqlock(current)){@@ -1478,8 +1510,7 @@
o = m.xy;
i = emenuhit(2, &m, &cmdmenu);
m.xy = o;
- if(!docmd(i, &m))
- continue;
+ docmd(i, &m);
} else if(m.buttons & 4){ if(root->down){Page *x;
@@ -1488,15 +1519,11 @@
pagemenu.lasthit = pageindex(current);
x = pageat(emenuhit(3, &m, &pagemenu));
qunlock(&pagelock);
- unlockdisplay(display);
showpage(x);
- continue;
}
}
- unlockdisplay(display);
break;
case Ekeyboard:
- lockdisplay(display);
switch(e.kbdc){case Kup:
if(current == nil || !canqlock(current))
@@ -1509,8 +1536,7 @@
if(prevpage(current))
pos.y = 0;
qunlock(current);
- if(!docmd(Cprev, &m))
- continue;
+ docmd(Cprev, &m);
break;
case Kdown:
if(current == nil || !canqlock(current))
@@ -1524,8 +1550,7 @@
if(nextpage(current))
pos.y = 0;
qunlock(current);
- if(!docmd(Cnext, &m))
- continue;
+ docmd(Cnext, &m);
break;
default:
for(i = 0; i<nelem(cmds); i++)
@@ -1534,8 +1559,7 @@
(cmds[i].k3 == e.kbdc))
break;
if(i < nelem(cmds)){- if(!docmd(i, &m))
- continue;
+ docmd(i, &m);
break;
}
if((e.kbdc < 0x20) ||
@@ -1543,14 +1567,9 @@
(e.kbdc & 0xFF00) == Spec)
break;
snprint(buf, sizeof(buf), "%C", (Rune)e.kbdc);
- i = eenter("Go to", buf, sizeof(buf), &m);- if(i > 0){- unlockdisplay(display);
+ if(eenter("Go to", buf, sizeof(buf), &m) > 0)showpage(findpage(buf));
- continue;
- }
}
- unlockdisplay(display);
break;
case Eplumb:
pm = e.v;
--
⑨