summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>2004-09-23 21:12:21 +0000
committerjoerg <joerg@FreeBSD.org>2004-09-23 21:12:21 +0000
commitf2a11c9f2e7cf0a8afeb91bd96c79df921c86dea (patch)
tree52a18f91be708d3a3f54c050bd331429d9ab8362
parente7c39452fd145d2952a8d73e5ee20d81bdad504a (diff)
downloadFreeBSD-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.
-rw-r--r--sys/dev/fdc/fdc.c24
-rw-r--r--sys/dev/fdc/fdcvar.h2
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 */
OpenPOWER on IntegriCloud