From: qwx@sciops.net
To: 9front@9front.org
Subject: [9front] fix race condition on writes to #v/vgactl
Date: Tue, 16 Aug 2022 08:12:45 +0200 [thread overview]
Message-ID: <559C4D36E88CDC22C329548E7BBFDF3F@wopr.sciops.net> (raw)
Hello,
I've been experiencing a seemingly impossible kernel panic when
messing with vgactl. Occasionally, writing multiple commands to
/dev/vgactl rapidly may cause an assert to fail
(/sys/src/9/port/devdraw.c:/assert). The panic is perfectly
reproducible by sending `softscreen off' commands quickly (tested on
x61t):
; for(i in `{seq 10}) echo softscreen off >/dev/vgactl
The panic occurs within the first few iterations. Moving some locks
out of individual functions to hold them for the entire step fixes
this. The patch below works, but qunlock may be called without the
drawlock being held, I need to recheck and clean up before commiting
anything. Credit to moody for suggesting looking in this direction!
Thoughts?
Thanks,
qwx
diff 69352f66684cbc75e2cd68c80cd028324964c5aa uncommitted
--- a//sys/src/9/pc/devvga.c
+++ b//sys/src/9/pc/devvga.c
@@ -296,7 +296,8 @@
error(Ebadarg);
if(r.max.x > scr->width || r.max.y > scr->height)
error("physical screen bigger than virtual");
- deletescreenimage();
+ qlock(&drawlock);
+ _deletescreenimage();
setactualsize(scr, r);
goto Resized;
@@ -324,10 +325,11 @@
}
if(scr->gscreen == nil)
return;
+ qlock(&drawlock);
r = actualscreensize(scr);
chan = scr->gscreen->chan;
z = scr->gscreen->depth;
- deletescreenimage();
+ _deletescreenimage();
setscreensize(scr, scr->width, scr->height, z, chan, tilt);
setactualsize(scr, r);
/* no break */
@@ -339,8 +341,9 @@
hwblank = scr->blank != nil;
hwaccel = scr->fill != nil || scr->scroll != nil;
Resized:
- vgascreenwin(scr);
- resetscreenimage();
+ _vgascreenwin(scr);
+ _resetscreenimage();
+ qunlock(&drawlock);
return;
case CMlinear:
--- a//sys/src/9/pc/screen.c
+++ b//sys/src/9/pc/screen.c
@@ -64,17 +64,11 @@
void
setactualsize(VGAscr *scr, Rectangle r)
{
- qlock(&drawlock);
-
r.min = ZP;
r.max = tiltsize(scr->tilt, r.max);
- if(rectclip(&r, scr->gscreen->r) == 0){
- qunlock(&drawlock);
+ if(rectclip(&r, scr->gscreen->r) == 0)
return;
- }
scr->gscreen->clipr = r;
-
- qunlock(&drawlock);
}
static char*
@@ -136,11 +130,8 @@
{
char *err;
- qlock(&drawlock);
- if(waserror()){
- qunlock(&drawlock);
+ if(waserror())
nexterror();
- }
if(memimageinit() < 0)
error("memimageinit failed");
@@ -169,7 +160,6 @@
cursoron();
}
- qunlock(&drawlock);
poperror();
}
--- a//sys/src/9/pc/screen.h
+++ b//sys/src/9/pc/screen.h
@@ -151,6 +151,8 @@
/* devdraw.c */
extern void deletescreenimage(void);
extern void resetscreenimage(void);
+extern void _deletescreenimage(void);
+extern void _resetscreenimage(void);
extern void setscreenimageclipr(Rectangle);
extern void drawflush(void);
extern QLock drawlock;
@@ -157,6 +159,7 @@
/* vga.c */
extern void vgascreenwin(VGAscr*);
+extern void _vgascreenwin(VGAscr*);
extern void vgaimageinit(ulong);
extern void vgalinearpci(VGAscr*);
extern void vgalinearaddr(VGAscr*, uvlong, vlong);
--- a//sys/src/9/pc/vga.c
+++ b//sys/src/9/pc/vga.c
@@ -176,7 +176,7 @@
}
void
-vgascreenwin(VGAscr* scr)
+_vgascreenwin(VGAscr* scr)
{
Memimage *i;
Rectangle r;
@@ -183,8 +183,6 @@
Point p;
int h;
- qlock(&drawlock);
-
h = scr->memdefont->height;
r = scr->gscreen->r;
@@ -215,12 +213,16 @@
curpos = window.min;
flushmemscreen(r);
-
- qunlock(&drawlock);
-
vgascreenputs(kmesg.buf, kmesg.n);
-
screenputs = vgascreenputs;
+}
+
+void
+vgascreenwin(VGAscr* scr)
+{
+ qlock(&drawlock);
+ _vgascreenwin(scr);
+ qunlock(&drawlock);
}
/*
--- a//sys/src/9/port/devdraw.c
+++ b//sys/src/9/port/devdraw.c
@@ -947,9 +947,8 @@
}
void
-deletescreenimage(void)
+_deletescreenimage(void)
{
- dlock();
if(screenimage){
/* will be freed via screendimage; disable */
screenimage->clipr = ZR;
@@ -959,14 +958,27 @@
drawfreedimage(screendimage);
screendimage = nil;
}
+}
+
+void
+deletescreenimage(void)
+{
+ dlock();
+ _deletescreenimage();
dunlock();
}
void
+_resetscreenimage(void)
+{
+ initscreenimage();
+}
+
+void
resetscreenimage(void)
{
dlock();
- initscreenimage();
+ _resetscreenimage();
dunlock();
}
next reply other threads:[~2022-08-16 6:14 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-16 6:12 qwx [this message]
2022-08-16 20:44 ` qwx
2022-08-16 20:51 ` Jacob Moody
2022-08-16 23:02 ` Anthony Martin
2022-08-17 12:10 ` qwx
2022-08-17 12:17 ` ori
2022-08-17 20:21 ` qwx
2022-08-18 2:23 ` ori
2022-08-18 5:36 ` qwx
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=559C4D36E88CDC22C329548E7BBFDF3F@wopr.sciops.net \
--to=qwx@sciops.net \
--cc=9front@9front.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).