diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2003-01-21 16:59:24 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2003-01-21 16:59:24 +0000 |
commit | e1f205a97630dcdfe7cbd9afc43901968de03786 (patch) | |
tree | e65c7eb61b5a0e5ab2fc0d99f78919f3867849f9 /sys/kern | |
parent | 51a25cabedd9e76a047e3ac7a28e0f4dab447ebf (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.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_watchdog.c | 116 |
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); +} |