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 | |
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')
-rw-r--r-- | sys/dev/fdc/fdc.c | 24 | ||||
-rw-r--r-- | sys/dev/fdc/fdcvar.h | 2 |
2 files changed, 23 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); diff --git a/sys/dev/fdc/fdcvar.h b/sys/dev/fdc/fdcvar.h index 5ecf912..acba77e 100644 --- a/sys/dev/fdc/fdcvar.h +++ b/sys/dev/fdc/fdcvar.h @@ -46,6 +46,8 @@ struct fdc_data { #define FDC_HAS_FIFO 0x10 #define FDC_NEEDS_RESET 0x20 #define FDC_NODMA 0x40 +#define FDC_KTHREAD_EXIT 0x1000 /* request worker thread to stop */ +#define FDC_KTHREAD_ALIVE 0x2000 /* worker thread is alive */ struct fd_data *fd; /* The active drive */ int retry; int fdout; /* mirror of the w/o digital output reg */ |