diff options
| author | dyoung <dyoung@NetBSD.org> | 2007-12-16 21:07:45 +0000 |
|---|---|---|
| committer | dyoung <dyoung@NetBSD.org> | 2007-12-16 21:07:45 +0000 |
| commit | 10bb018ab235fff40669c3252b0263ff50dacb88 (patch) | |
| tree | 77508927e35688a7a8a0e8f85b63b719f0c63445 /sys/dev/sysmon | |
| parent | 471ee9702cbac06638ab5ddd6a96a5d8885c9bba (diff) | |
In sysmon_wdog_unregister(), do not return until all of the watchdog
timer's users are gone. A signal cancels the unregister:
sysmon_wdog_unregister() leaves the watchdog registered.
The only user of sysmon_wdog_unregister() that I can find is in
elansc(4), so this looks like a safe change to make.
Diffstat (limited to 'sys/dev/sysmon')
| -rw-r--r-- | sys/dev/sysmon/sysmon_wdog.c | 36 | ||||
| -rw-r--r-- | sys/dev/sysmon/sysmonvar.h | 4 |
2 files changed, 31 insertions, 9 deletions
diff --git a/sys/dev/sysmon/sysmon_wdog.c b/sys/dev/sysmon/sysmon_wdog.c index 1272ef9eefe..86ddbadcfa0 100644 --- a/sys/dev/sysmon/sysmon_wdog.c +++ b/sys/dev/sysmon/sysmon_wdog.c @@ -1,4 +1,4 @@ -/* $NetBSD: sysmon_wdog.c,v 1.23 2007/12/15 04:58:39 dyoung Exp $ */ +/* $NetBSD: sysmon_wdog.c,v 1.24 2007/12/16 21:07:45 dyoung Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -41,12 +41,13 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.23 2007/12/15 04:58:39 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sysmon_wdog.c,v 1.24 2007/12/16 21:07:45 dyoung Exp $"); #include <sys/param.h> #include <sys/conf.h> #include <sys/errno.h> #include <sys/fcntl.h> +#include <sys/condvar.h> #include <sys/mutex.h> #include <sys/callout.h> #include <sys/kernel.h> @@ -59,6 +60,7 @@ static LIST_HEAD(, sysmon_wdog) sysmon_wdog_list = LIST_HEAD_INITIALIZER(&sysmon_wdog_list); static int sysmon_wdog_count; static kmutex_t sysmon_wdog_list_mtx, sysmon_wdog_mtx; +static kcondvar_t sysmon_wdog_cv; static struct sysmon_wdog *sysmon_armed_wdog; static callout_t sysmon_wdog_callout; static void *sysmon_wdog_sdhook; @@ -68,12 +70,14 @@ void sysmon_wdog_release(struct sysmon_wdog *); int sysmon_wdog_setmode(struct sysmon_wdog *, int, u_int); void sysmon_wdog_ktickle(void *); void sysmon_wdog_shutdown(void *); +void sysmon_wdog_ref(struct sysmon_wdog *); void sysmon_wdog_init(void) { mutex_init(&sysmon_wdog_list_mtx, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sysmon_wdog_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); + cv_init(&sysmon_wdog_cv, "wdogref"); } /* @@ -299,14 +303,23 @@ sysmon_wdog_register(struct sysmon_wdog *smw) * * Unregister a watchdog device. */ -void +int sysmon_wdog_unregister(struct sysmon_wdog *smw) { + int rc = 0; mutex_enter(&sysmon_wdog_list_mtx); - sysmon_wdog_count--; - LIST_REMOVE(smw, smw_list); + while (smw->smw_refcnt > 0 && rc == 0) { + aprint_debug("%s: %d users remain\n", smw->smw_name, + smw->smw_refcnt); + rc = cv_wait_sig(&sysmon_wdog_cv, &sysmon_wdog_list_mtx); + } + if (rc == 0) { + sysmon_wdog_count--; + LIST_REMOVE(smw, smw_list); + } mutex_exit(&sysmon_wdog_list_mtx); + return rc; } /* @@ -346,6 +359,15 @@ sysmon_wdog_release(struct sysmon_wdog *smw) mutex_enter(&sysmon_wdog_list_mtx); KASSERT(smw->smw_refcnt != 0); smw->smw_refcnt--; + cv_signal(&sysmon_wdog_cv); + mutex_exit(&sysmon_wdog_list_mtx); +} + +void +sysmon_wdog_ref(struct sysmon_wdog *smw) +{ + mutex_enter(&sysmon_wdog_list_mtx); + smw->smw_refcnt++; mutex_exit(&sysmon_wdog_list_mtx); } @@ -396,12 +418,12 @@ sysmon_wdog_setmode(struct sysmon_wdog *smw, int mode, u_int period) if ((mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { sysmon_armed_wdog = NULL; smw->smw_tickler = (pid_t) -1; - smw->smw_refcnt--; + sysmon_wdog_release(smw); if ((omode & WDOG_MODE_MASK) == WDOG_MODE_KTICKLE) callout_stop(&sysmon_wdog_callout); } else { sysmon_armed_wdog = smw; - smw->smw_refcnt++; + sysmon_wdog_ref(smw); if ((mode & WDOG_MODE_MASK) == WDOG_MODE_KTICKLE) { callout_reset(&sysmon_wdog_callout, WDOG_PERIOD_TO_TICKS(smw->smw_period) / 2, diff --git a/sys/dev/sysmon/sysmonvar.h b/sys/dev/sysmon/sysmonvar.h index 8cb0f190464..231f777b649 100644 --- a/sys/dev/sysmon/sysmonvar.h +++ b/sys/dev/sysmon/sysmonvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: sysmonvar.h,v 1.22 2007/11/20 17:24:32 xtraeme Exp $ */ +/* $NetBSD: sysmonvar.h,v 1.23 2007/12/16 21:07:46 dyoung Exp $ */ /*- * Copyright (c) 2000 Zembu Labs, Inc. @@ -137,7 +137,7 @@ int sysmonclose_wdog(dev_t, int, int, struct lwp *); int sysmonioctl_wdog(dev_t, u_long, void *, int, struct lwp *); int sysmon_wdog_register(struct sysmon_wdog *); -void sysmon_wdog_unregister(struct sysmon_wdog *); +int sysmon_wdog_unregister(struct sysmon_wdog *); void sysmon_wdog_init(void); |
