diff options
author | jh <jh@FreeBSD.org> | 2010-11-03 16:19:35 +0000 |
---|---|---|
committer | jh <jh@FreeBSD.org> | 2010-11-03 16:19:35 +0000 |
commit | 6604019e2651e5c8091a892c712c67a1c4278903 (patch) | |
tree | 7de24b408f50a5fed2c0731b48fa1deaf109deb6 /sys/geom | |
parent | 177b41b47d00bee38872e7f187a336e26b8286fd (diff) | |
download | FreeBSD-src-6604019e2651e5c8091a892c712c67a1c4278903.zip FreeBSD-src-6604019e2651e5c8091a892c712c67a1c4278903.tar.gz |
Extend the g_eventlock mutex coverage in one_event() to include setting
of the EV_DONE flag and use the mutex to protect against losing wakeups
in g_waitfor_event().
Reported by: davidxu
Tested by: davidxu
Discussed on: freebsd-current
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/geom_event.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/sys/geom/geom_event.c b/sys/geom/geom_event.c index 5ac52d4..44890aa 100644 --- a/sys/geom/geom_event.c +++ b/sys/geom/geom_event.c @@ -220,11 +220,12 @@ one_event(void) mtx_lock(&g_eventlock); TAILQ_REMOVE(&g_events, ep, events); ep->flag &= ~EV_INPROGRESS; - mtx_unlock(&g_eventlock); if (ep->flag & EV_WAKEUP) { ep->flag |= EV_DONE; + mtx_unlock(&g_eventlock); wakeup(ep); } else { + mtx_unlock(&g_eventlock); g_free(ep); } g_topology_unlock(); @@ -365,11 +366,14 @@ g_waitfor_event(g_event_t *func, void *arg, int flag, ...) va_end(ap); if (error) return (error); - do - tsleep(ep, PRIBIO, "g_waitfor_event", hz); - while (!(ep->flag & EV_DONE)); + + mtx_lock(&g_eventlock); + while (!(ep->flag & EV_DONE)) + msleep(ep, &g_eventlock, PRIBIO, "g_waitfor_event", hz); if (ep->flag & EV_CANCELED) error = EAGAIN; + mtx_unlock(&g_eventlock); + g_free(ep); return (error); } |