diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-08-24 12:52:34 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-08-24 12:52:34 +0200 |
commit | 80a5bfc1d812618d4f6a16eb29026f412df7b56c (patch) | |
tree | ad8ef92deab8f1131c37e41c534fa15ed067bcc6 /sys/src/9/pc/sdvirtio.c | |
parent | 8e5dd37eba4a206f875f6957aece99774933429e (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.c | 7 |
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; |