summaryrefslogtreecommitdiffstats
path: root/sys/dev/pccbb
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2006-05-24 17:22:53 +0000
committerimp <imp@FreeBSD.org>2006-05-24 17:22:53 +0000
commit0e7d1a9250a0f4df024a7beb83bcf76fbe1aff5a (patch)
treed428cd95d5913542d75cd8403de6b6970f25d70b /sys/dev/pccbb
parentbeb934bdcded880bc8e41e5b1eba911a1b95d810 (diff)
downloadFreeBSD-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.c8
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);
}
OpenPOWER on IntegriCloud