summaryrefslogtreecommitdiff
path: root/sys/dev/sysmon
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sysmon')
-rw-r--r--sys/dev/sysmon/sysmon_wdog.c36
-rw-r--r--sys/dev/sysmon/sysmonvar.h4
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);