summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/sdvirtio.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-08-24 12:52:34 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-08-24 12:52:34 +0200
commit80a5bfc1d812618d4f6a16eb29026f412df7b56c (patch)
treead8ef92deab8f1131c37e41c534fa15ed067bcc6 /sys/src/9/pc/sdvirtio.c
parent8e5dd37eba4a206f875f6957aece99774933429e (diff)
sdvirtio: be more carefull at wakeup
wakeup cannot access r->sleep once we set r->done because the sleeper might just return at this point making r invalid. make a copy of the sleep rendez pointer before setting r->done.
Diffstat (limited to 'sys/src/9/pc/sdvirtio.c')
-rw-r--r--sys/src/9/pc/sdvirtio.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/sys/src/9/pc/sdvirtio.c b/sys/src/9/pc/sdvirtio.c
index 982ac51e9..2ccc3dbce 100644
--- a/sys/src/9/pc/sdvirtio.c
+++ b/sys/src/9/pc/sdvirtio.c
@@ -218,6 +218,7 @@ viointerrupt(Ureg *, void *arg)
{
int id, free, m;
struct Rock *r;
+ Rendez *z;
Vqueue *q;
Vdev *vd;
@@ -231,8 +232,10 @@ viointerrupt(Ureg *, void *arg)
id = q->usedent[q->lastused++ & m].id;
if(r = q->rock[id]){
q->rock[id] = nil;
- r->done = 1;
- wakeup(r->sleep);
+ z = r->sleep;
+ r->done = 1; /* hands off */
+ if(z != nil)
+ wakeup(z);
}
do {
free = id;