summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-01-21 16:59:24 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-01-21 16:59:24 +0000
commite1f205a97630dcdfe7cbd9afc43901968de03786 (patch)
treee65c7eb61b5a0e5ab2fc0d99f78919f3867849f9 /sys/kern
parent51a25cabedd9e76a047e3ac7a28e0f4dab447ebf (diff)
add kern.watchdog sysctl and generic watchdog interface;
based on feedback and discussions with mickey, henric, fgsch and jakob. ok art@, mickey@, jakob@, henric@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sysctl.c6
-rw-r--r--sys/kern/kern_watchdog.c116
2 files changed, 121 insertions, 1 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 49b128dec3a..977d730a384 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.78 2003/01/15 23:41:56 millert Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.79 2003/01/21 16:59:23 markus Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -269,6 +269,7 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
case KERN_SEMINFO:
case KERN_SHMINFO:
case KERN_INTRCNT:
+ case KERN_WATCHDOG:
break;
default:
return (ENOTDIR); /* overloaded */
@@ -480,6 +481,9 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
#endif
case KERN_INTRCNT:
return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
+ case KERN_WATCHDOG:
+ return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
+ newp, newlen));
default:
return (EOPNOTSUPP);
}
diff --git a/sys/kern/kern_watchdog.c b/sys/kern/kern_watchdog.c
new file mode 100644
index 00000000000..8ace7b27c57
--- /dev/null
+++ b/sys/kern/kern_watchdog.c
@@ -0,0 +1,116 @@
+/* $OpenBSD: kern_watchdog.c,v 1.1 2003/01/21 16:59:23 markus Exp $ */
+
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+void wdog_init(void);
+void wdog_tickle(void *arg);
+void wdog_shutdown(void *arg);
+int (*wdog_ctl_cb)(void *, int) = NULL;
+void *wdog_ctl_cb_arg = NULL;
+int wdog_period = 0;
+int wdog_auto = 1;
+struct timeout wdog_timeout;
+
+void
+wdog_init(void)
+{
+ timeout_set(&wdog_timeout, wdog_tickle, NULL);
+ shutdownhook_establish(wdog_shutdown, NULL);
+}
+
+void
+wdog_register(void *cb_arg, int (*cb)(void *, int))
+{
+ if (wdog_ctl_cb != NULL)
+ return;
+ wdog_init();
+ wdog_ctl_cb = cb;
+ wdog_ctl_cb_arg = cb_arg;
+}
+
+void
+wdog_tickle(void *arg)
+{
+ if (wdog_ctl_cb == NULL)
+ return;
+ (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, wdog_period);
+ timeout_add(&wdog_timeout, wdog_period * hz / 2);
+}
+
+void
+wdog_shutdown(void *arg)
+{
+ if (wdog_ctl_cb == NULL)
+ return;
+ timeout_del(&wdog_timeout);
+ (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, 0);
+}
+
+int
+sysctl_wdog(name, namelen, oldp, oldlenp, newp, newlen)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+{
+ int error, period;
+
+ if (wdog_ctl_cb == NULL)
+ return (EOPNOTSUPP);
+
+ switch (name[0]) {
+ case KERN_WATCHDOG_PERIOD:
+ period = wdog_period;
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &period);
+ if (error)
+ return (error);
+ if (newp) {
+ timeout_del(&wdog_timeout);
+ wdog_period = (*wdog_ctl_cb)(wdog_ctl_cb_arg, period);
+ }
+ break;
+ case KERN_WATCHDOG_AUTO:
+ error = sysctl_int(oldp, oldlenp, newp, newlen, &wdog_auto);
+ if (error)
+ return (error);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ timeout_del(&wdog_timeout);
+ if (wdog_auto && wdog_period > 0) {
+ (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, wdog_period);
+ timeout_add(&wdog_timeout, wdog_period * hz / 2);
+ }
+ return (error);
+}