diff options
author | imp <imp@FreeBSD.org> | 2006-05-24 17:22:53 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2006-05-24 17:22:53 +0000 |
commit | 0e7d1a9250a0f4df024a7beb83bcf76fbe1aff5a (patch) | |
tree | d428cd95d5913542d75cd8403de6b6970f25d70b /sys/dev/pccbb | |
parent | beb934bdcded880bc8e41e5b1eba911a1b95d810 (diff) | |
download | FreeBSD-src-0e7d1a9250a0f4df024a7beb83bcf76fbe1aff5a.zip FreeBSD-src-0e7d1a9250a0f4df024a7beb83bcf76fbe1aff5a.tar.gz |
Fix a race when detaching the cbb worker thread. There were a couple
of cases where we didn't take out the lock before setting or clearing
a bit. This apparently can lead to a race at kldunload time (at least
on my Turion64 laptop, never saw it on my Sony Vaio).
Diffstat (limited to 'sys/dev/pccbb')
-rw-r--r-- | sys/dev/pccbb/pccbb.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c index a9bf97a..387795f 100644 --- a/sys/dev/pccbb/pccbb.c +++ b/sys/dev/pccbb/pccbb.c @@ -330,7 +330,8 @@ cbb_detach(device_t brdev) mtx_lock(&sc->mtx); bus_teardown_intr(brdev, sc->irq_res, sc->intrhand); sc->flags |= CBB_KTHREAD_DONE; - if (sc->flags & CBB_KTHREAD_RUNNING) { + while (sc->flags & CBB_KTHREAD_RUNNING) { + DEVPRINTF((sc->dev, "Waiting for thread to die\n")); cv_broadcast(&sc->cv); msleep(sc->event_thread, &sc->mtx, PWAIT, "cbbun", 0); } @@ -481,7 +482,9 @@ cbb_event_thread(void *arg) int err; int not_a_card = 0; + mtx_lock(&sc->mtx); sc->flags |= CBB_KTHREAD_RUNNING; + mtx_unlock(&sc->mtx); while ((sc->flags & CBB_KTHREAD_DONE) == 0) { /* * We take out Giant here because we need it deep, @@ -538,7 +541,10 @@ cbb_event_thread(void *arg) err = cv_timedwait(&sc->cv, &sc->mtx, 1 * hz); mtx_unlock(&sc->mtx); } + DEVPRINTF((sc->dev, "Thread terminating\n")); + mtx_lock(&sc->mtx); sc->flags &= ~CBB_KTHREAD_RUNNING; + mtx_unlock(&sc->mtx); kthread_exit(0); } |