Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Add a software watchdog timer facility. Because this slightly



details:   https://anonhg.NetBSD.org/src/rev/0378484a60d5
branches:  trunk
changeset: 572658:0378484a60d5
user:      smb <smb%NetBSD.org@localhost>
date:      Sun Jan 09 22:51:32 2005 +0000

description:
Add a software watchdog timer facility.  Because this slightly
changes the "tickle" model of wdogctl(8), it was modified as well;
while I was in there, I cleaned up the argument parsing.

The code was reviewed by simonb@.

diffstat:

 distrib/sets/lists/man/mi    |    4 +-
 sbin/wdogctl/wdogctl.8       |   28 +++++-
 sbin/wdogctl/wdogctl.c       |  181 +++++++++++++++++++++++++++++++-----------
 share/man/man4/Makefile      |    6 +-
 share/man/man4/swwdog.4      |   76 ++++++++++++++++++
 sys/dev/sysmon/files.sysmon  |    6 +-
 sys/dev/sysmon/swwdog.c      |  159 +++++++++++++++++++++++++++++++++++++
 sys/dev/sysmon/sysmon_wdog.c |    5 +-
 sys/sys/wdog.h               |    3 +-
 9 files changed, 406 insertions(+), 62 deletions(-)

diffs (truncated from 709 to 300 lines):

diff -r 62e801bfb0a9 -r 0378484a60d5 distrib/sets/lists/man/mi
--- a/distrib/sets/lists/man/mi Sun Jan 09 22:24:04 2005 +0000
+++ b/distrib/sets/lists/man/mi Sun Jan 09 22:51:32 2005 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.748 2005/01/09 05:53:16 snj Exp $
+# $NetBSD: mi,v 1.749 2005/01/09 22:51:32 smb Exp $
 ./etc/mtree/set.man                            man-sys-root
 ./usr/share/info/am-utils.info                 man-amd-info            info
 ./usr/share/info/as.info                       man-computil-info       bfd,info
@@ -1227,6 +1227,7 @@
 ./usr/share/man/cat4/sun3/ms.0                 man-sys-catman          .cat
 ./usr/share/man/cat4/sv.0                      man-sys-catman          .cat
 ./usr/share/man/cat4/sw.0                      man-sys-catman          .cat
+./usr/share/man/cat4/swwdog.0                  man-sys-catman          .cat
 ./usr/share/man/cat4/sysbeep.0                 man-sys-catman          .cat
 ./usr/share/man/cat4/systrace.0                        man-sys-catman          .cat
 ./usr/share/man/cat4/tap.0                     man-sys-catman          .cat
@@ -3411,6 +3412,7 @@
 ./usr/share/man/man4/sun3/ms.4                 man-sys-man             .man
 ./usr/share/man/man4/sv.4                      man-sys-man             .man
 ./usr/share/man/man4/sw.4                      man-sys-man             .man
+./usr/share/man/man4/swwdog.4                  man-sys-man             .man
 ./usr/share/man/man4/sysbeep.4                 man-sys-man             .man
 ./usr/share/man/man4/systrace.4                        man-sys-man             .man
 ./usr/share/man/man4/tap.4                     man-sys-man             .man
diff -r 62e801bfb0a9 -r 0378484a60d5 sbin/wdogctl/wdogctl.8
--- a/sbin/wdogctl/wdogctl.8    Sun Jan 09 22:24:04 2005 +0000
+++ b/sbin/wdogctl/wdogctl.8    Sun Jan 09 22:51:32 2005 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: wdogctl.8,v 1.8 2003/02/25 10:35:12 wiz Exp $
+.\"    $NetBSD: wdogctl.8,v 1.9 2005/01/09 22:51:32 smb Exp $
 .\"
 .\" Copyright (c) 2000 Zembu Labs, Inc.
 .\" All rights reserved.
@@ -50,6 +50,13 @@
 .Op Fl p Ar seconds
 .Ar timer
 .Nm
+.Fl e
+.Op Fl A
+.Op Fl p Ar seconds
+.Ar timer
+.Nm
+.Fl t
+.Nm
 .Fl d
 .Sh DESCRIPTION
 .Nm
@@ -67,8 +74,8 @@
 .Pp
 The
 .Nx
-kernel provides two basic modes in which watchdog timers may
-operate: kernel tickle mode and user tickle mode.
+kernel provides three basic modes in which watchdog timers may
+operate: kernel tickle mode, user tickle mode, and external tickle mode.
 In kernel tickle mode, a timer in the kernel refreshes the watchdog timer.
 In user tickle mode,
 .Nm
@@ -80,8 +87,15 @@
 on a heavily loaded system, the timer may
 expire accidentally, even though user programs may be making
 (very slow) progress.
+A user-mode timer is disarmed (if possible) when the device is closed.
 .Pp
-In both modes, an attempt is made to refresh the watchdog timer
+External-mode watchdogs are similar to user-mode watchdogs, except
+that the tickle must be done explicitly by a separate invocation of
+the program with the
+.Fl t
+option.
+.Pp
+In the first two modes, an attempt is made to refresh the watchdog timer
 in one half the timer's configured period.
 That is, if the watchdog timer has a period of 30 seconds, a refresh attempt
 is made every 15 seconds.
@@ -107,6 +121,10 @@
 Arm
 .Ar timer
 in user tickle mode.
+.It Fl e
+Arm
+.Ar timer
+in external tickle mode.
 .It Fl A
 When arming a timer, this flag indicates that an audible alarm is
 to sound when the watchdog timer expires and resets the system.
@@ -124,6 +142,8 @@
 If the selected timer can not be disabled,
 an error message will be displayed and the
 timer will remain armed.
+.It Fl t
+This flag tickles an external mode timer.
 .El
 .Sh FILES
 .Pa /dev/watchdog
diff -r 62e801bfb0a9 -r 0378484a60d5 sbin/wdogctl/wdogctl.c
--- a/sbin/wdogctl/wdogctl.c    Sun Jan 09 22:24:04 2005 +0000
+++ b/sbin/wdogctl/wdogctl.c    Sun Jan 09 22:51:32 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdogctl.c,v 1.10 2004/01/05 23:23:34 jmmv Exp $        */
+/*     $NetBSD: wdogctl.c,v 1.11 2005/01/09 22:51:32 smb Exp $ */
 
 /*-
  * Copyright (c) 2000 Zembu Labs, Inc.
@@ -35,7 +35,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: wdogctl.c,v 1.10 2004/01/05 23:23:34 jmmv Exp $");
+__RCSID("$NetBSD: wdogctl.c,v 1.11 2005/01/09 22:51:32 smb Exp $");
 #endif
 
 
@@ -59,47 +59,74 @@
 int    main(int, char *[]);
 void   enable_kernel(const char *, u_int);
 void   enable_user(const char *, u_int);
+void   enable_ext(const char *, u_int);
+void   tickle_ext(void);
 void   disable(void);
+void   prep_wmode(struct wdog_mode *, int,  const char *, u_int);
 void   list_timers(void);
 void   usage(void);
 
 int    Aflag;
 
+/* Caution -- ordered list; entries >= CMD_EXT_TICKLE set timers */
+enum   cmd {
+       CMD_NONE,       /* No verb given */
+       CMD_DISABLE,
+       CMD_DOTICKLE,
+       CMD_EXT_TICKLE,
+       CMD_KERN_TICKLE,
+       CMD_USER_TICKLE
+};
+
 int
 main(int argc, char *argv[])
 {
-       int cmds = 0, kflag = 0, uflag = 0, dflag = 0, ch;
+       enum cmd command = CMD_NONE;
+       int period_flag = 0;
+       int ch;
        u_int period = WDOG_PERIOD_DEFAULT;
 
-       while ((ch = getopt(argc, argv, "Adkp:u")) != -1) {
+       while ((ch = getopt(argc, argv, "Adekp:ut")) != -1) {
                switch (ch) {
                case 'A':
-                       if (cmds == 0 || dflag)
-                               usage();
                        Aflag = 1;
                        break;
 
                case 'd':
-                       dflag = 1;
-                       cmds++;
+                       if (command != CMD_NONE)
+                               usage();
+                       command = CMD_DISABLE;
+                       break;
+
+               case 'e':
+                       if (command != CMD_NONE)
+                               usage();
+                       command = CMD_EXT_TICKLE;
                        break;
 
                case 'k':
-                       kflag = 1;
-                       cmds++;
+                       if (command != CMD_NONE)
+                               usage();
+                       command = CMD_KERN_TICKLE;
+                       break;
+
+               case 't':
+                       if (command != CMD_NONE)
+                               usage();
+                       command = CMD_DOTICKLE;
                        break;
 
                case 'p':
-                       if (cmds == 0 || dflag)
-                               usage();
+                       period_flag = 1;
                        period = atoi(optarg);
                        if (period == -1)
                                usage();
                        break;
 
                case 'u':
-                       uflag = 1;
-                       cmds++;
+                       if (command != CMD_NONE)
+                               usage();
+                       command = CMD_USER_TICKLE;
                        break;
 
                default:
@@ -110,41 +137,60 @@
        argc -= optind;
        argv += optind;
 
-       if (cmds > 1)
-               usage();
-
-       if (kflag) {
-               if (argc != 1)
+       if (command < CMD_EXT_TICKLE) {
+               if (Aflag || period_flag)
                        usage();
-               enable_kernel(argv[0], period);
-       } else if (uflag) {
+               if (argc != 0)
+                       usage();
+       }
+       else {
                if (argc != 1)
                        usage();
-               enable_user(argv[0], period);
-       } else if (dflag) {
-               if (argc != 0)
-                       usage();
-               disable();
-       } else
-               list_timers();
+       }
 
+       switch (command) {
+               case CMD_NONE:
+                       list_timers();
+                       break;
+               case CMD_DISABLE:
+                       disable();
+                       break;
+               case CMD_DOTICKLE:
+                       tickle_ext();
+                       break;
+               case CMD_EXT_TICKLE:
+                       enable_ext(argv[0], period);
+                       break;
+               case CMD_KERN_TICKLE:
+                       enable_kernel(argv[0], period);
+                       break;
+               case CMD_USER_TICKLE:
+                       enable_user(argv[0], period);
+                       break;
+       }
        exit(0);
 }
 
 void
+prep_wmode(struct wdog_mode *wp, int mode,  const char *name, u_int period)
+{
+       if (strlen(name) >= WDOG_NAMESIZE)
+               errx(1, "invalid watchdog timer name: %s", name);
+
+       strlcpy(wp->wm_name, name, sizeof(wp->wm_name));
+       wp->wm_mode = mode;
+       wp->wm_period = period;
+       if (Aflag)
+               wp->wm_mode |= WDOG_FEATURE_ALARM;
+}
+
+void
 enable_kernel(const char *name, u_int period)
 {
        struct wdog_mode wm;
        int fd;
 
-       if (strlen(name) >= WDOG_NAMESIZE)
-               errx(1, "invalid watchdog timer name: %s", name);
-       strlcpy(wm.wm_name, name, sizeof(wm.wm_name));
-       wm.wm_mode = WDOG_MODE_KTICKLE;
-       wm.wm_period = period;
-
-       if (Aflag)
-               wm.wm_mode |= WDOG_FEATURE_ALARM;
+       prep_wmode(&wm, WDOG_MODE_KTICKLE, name, period);
 
        fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
        if (fd == -1)
@@ -155,6 +201,26 @@
 }
 
 void
+enable_ext(const char *name, u_int period)
+{
+       struct wdog_mode wm;  
+       int fd;
+
+       prep_wmode(&wm, WDOG_MODE_ETICKLE, name, period);
+
+       fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
+       if (fd == -1)
+               err(1, "open %s", _PATH_WATCHDOG);
+       if (ioctl(fd, WDOGIOC_SMODE, &wm) == -1) {
+               err(1, "WDOGIOC_SMODE");



Home | Main Index | Thread Index | Old Index