diff options
author | joerg <joerg@FreeBSD.org> | 2004-09-23 21:12:21 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 2004-09-23 21:12:21 +0000 |
commit | f2a11c9f2e7cf0a8afeb91bd96c79df921c86dea (patch) | |
tree | 52a18f91be708d3a3f54c050bd331429d9ab8362 /sys/dev/fdc/fdc.c | |
parent | e7c39452fd145d2952a8d73e5ee20d81bdad504a (diff) | |
download | FreeBSD-src-f2a11c9f2e7cf0a8afeb91bd96c79df921c86dea.zip FreeBSD-src-f2a11c9f2e7cf0a8afeb91bd96c79df921c86dea.tar.gz |
Implement terminating the worker thread when the driver is about to
be deregistered.
Not yet tested, since by now, GEOM doesn't want us to deregister. PHK
wants to fix that RSN.
Diffstat (limited to 'sys/dev/fdc/fdc.c')
-rw-r--r-- | sys/dev/fdc/fdc.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 139285c..6df202c 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -761,8 +761,17 @@ fdc_worker(struct fdc_data *fdc) if (fdc->bp == NULL) msleep(&fdc->head, &fdc->fdc_mtx, PRIBIO, "-", hz); - } while (fdc->bp == NULL); + } while (fdc->bp == NULL && + (fdc->flags & FDC_KTHREAD_EXIT) == 0); mtx_unlock(&fdc->fdc_mtx); + + if (fdc->bp == NULL) + /* + * Nothing to do, worker thread has been + * requested to stop. + */ + return (0); + bp = fdc->bp; fd = fdc->fd = bp->bio_driver1; fdc->retry = 0; @@ -1118,7 +1127,8 @@ fdc_thread(void *arg) fdc = arg; int i; - for (;;) { + fdc->flags |= FDC_KTHREAD_ALIVE; + while ((fdc->flags & FDC_KTHREAD_EXIT) == 0) { i = fdc_worker(fdc); if (i && debugflags & 0x20) { if (fdc->bp != NULL) { @@ -1129,6 +1139,8 @@ fdc_thread(void *arg) } fdc->retry += i; } + fdc->flags &= ~(FDC_KTHREAD_EXIT | FDC_KTHREAD_ALIVE); + wakeup(&fdc->fdc_thread); } /* @@ -1624,7 +1636,13 @@ fdc_detach(device_t dev) if ((error = bus_generic_detach(dev))) return (error); - /* XXX: kill thread */ + /* kill worker thread */ + fdc->flags |= FDC_KTHREAD_EXIT; + mtx_lock(&fdc->fdc_mtx); + while ((fdc->flags & FDC_KTHREAD_ALIVE) != 0) + msleep(&fdc->fdc_thread, &fdc->fdc_mtx, PRIBIO, "fdcdet", 0); + mtx_unlock(&fdc->fdc_mtx); + /* reset controller, turn motor off */ fdout_wr(fdc, 0); |