From owner-svn-src-user@FreeBSD.ORG Tue Feb 12 04:22:01 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id A9C0B254; Tue, 12 Feb 2013 04:22:01 +0000 (UTC) (envelope-from alfred@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 9C45B197; Tue, 12 Feb 2013 04:22:01 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r1C4M1qu078783; Tue, 12 Feb 2013 04:22:01 GMT (envelope-from alfred@svn.freebsd.org) Received: (from alfred@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r1C4M1Ok078780; Tue, 12 Feb 2013 04:22:01 GMT (envelope-from alfred@svn.freebsd.org) Message-Id: <201302120422.r1C4M1Ok078780@svn.freebsd.org> From: Alfred Perlstein Date: Tue, 12 Feb 2013 04:22:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r246704 - in user/alfred/ewatchdog/sys: dev/watchdog sys X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Feb 2013 04:22:01 -0000 Author: alfred Date: Tue Feb 12 04:22:00 2013 New Revision: 246704 URL: http://svnweb.freebsd.org/changeset/base/246704 Log: Add a new software watchdog that has a configurable action. While here refactor the "action" code. Modified: user/alfred/ewatchdog/sys/dev/watchdog/watchdog.c user/alfred/ewatchdog/sys/sys/watchdog.h Modified: user/alfred/ewatchdog/sys/dev/watchdog/watchdog.c ============================================================================== --- user/alfred/ewatchdog/sys/dev/watchdog/watchdog.c Tue Feb 12 03:19:39 2013 (r246703) +++ user/alfred/ewatchdog/sys/dev/watchdog/watchdog.c Tue Feb 12 04:22:00 2013 (r246704) @@ -47,11 +47,17 @@ __FBSDID("$FreeBSD$"); #include /* kern_clock_gettime() */ static int wd_set_pretimeout(int newtimeout, int disableiftoolong); +static void wd_timeout_cb(void *arg); static struct callout wd_pretimeo_handle; static int wd_pretimeout; static int wd_pretimeout_act; +static struct callout wd_softtimeo_handle; +static int wd_softtimer; /* true = use softtimer instead of hardware + watchdog */ +static int wd_softtimeout_act; /* action for the software timeout */ + static struct cdev *wd_dev; static volatile u_int wd_last_u; /* last timeout value set by kern_do_pat */ @@ -90,7 +96,16 @@ kern_do_pat(u_int utim) /* Assume no watchdog available; watchdog flags success */ error = EOPNOTSUPP; } - EVENTHANDLER_INVOKE(watchdog_list, utim, &error); + if (wd_softtimer) { + if (utim == 0) { + callout_stop(&wd_softtimeo_handle); + } else { + (void) callout_reset(&wd_softtimeo_handle, + hz*utim, wd_timeout_cb, "soft"); + } + } else { + EVENTHANDLER_INVOKE(watchdog_list, utim, &error); + } wd_set_pretimeout(wd_pretimeout, true); /* * If we were able to arm/strobe the watchdog, then @@ -110,6 +125,21 @@ kern_do_pat(u_int utim) } static int +wd_valid_act(int act) +{ + + switch (act) { + case WD_SOFT_PANIC: +#ifdef DDB + case WD_SOFT_DDB: +#endif + case WD_SOFT_LOG: + return true; + } + return false; +} + +static int wd_ioctl_patpat(caddr_t data) { u_int u; @@ -145,20 +175,26 @@ wd_get_time_left(struct thread *td, time } static void -wd_pretimeout_cb(void *arg __unused) +wd_timeout_cb(void *arg) { + const char *type = arg; +#ifdef DDB + char kdb_why[80]; +#endif switch (wd_pretimeout_act) { - case WD_PRE_PANIC: - panic("watchdog pre-timeout, WD_PRE_PANIC set"); + case WD_SOFT_PANIC: + panic("watchdog %s-timeout, WD_SOFT_PANIC set", type); break; #ifdef DDB - case WD_PRE_DDB: - debugger(); + case WD_SOFT_DDB: + snprintf(kdb_why, sizeof(buf), "watchdog %s timeout", type); + kdb_backtrace(); + kdb_enter(KDB_WHY_WATCHDOG, kdb_why); break; #endif - case WD_PRE_LOG: - log(LOG_EMERG, "watchdog pre-timeout, WD_PRE_LOG"); + case WD_SOFT_LOG: + log(LOG_EMERG, "watchdog %s-timeout, WD_SOFT_LOG", type); break; default: panic("watchdog: unexpected wd_pretimeout_act %d", @@ -200,7 +236,7 @@ wd_set_pretimeout(int newtimeout, int di /* We determined the value is sane, so reset the callout */ (void) callout_reset(&wd_pretimeo_handle, hz*(utime - newtimeout), - wd_pretimeout_cb, NULL); + wd_timeout_cb, "pre-timeout"); wd_pretimeout = newtimeout; return 0; } @@ -216,20 +252,33 @@ wd_ioctl(struct cdev *dev __unused, u_lo error = 0; switch (cmd) { - case WDIOC_SETPRETIMEOUTACT: + case WDIOC_SETSOFT: u = *(int *)data; - switch (u) { - case WD_PRE_PANIC: -#ifdef DDB - case WD_PRE_DDB: -#endif - case WD_PRE_LOG: - wd_pretimeout_act = u; + /* do nothing? */ + if (u == wd_softtimer) break; - default: + /* If there is a pending timeout disallow this ioctl */ + if (wd_last_u != 0) { error = EINVAL; break; } + wd_softtimer = u; + break; + case WDIOC_SETSOFTTIMEOUTACT: + u = *(int *)data; + if (wd_valid_act(u)) { + wd_softtimeout_act = u; + } else { + error = EINVAL; + } + break; + case WDIOC_SETPRETIMEOUTACT: + u = *(int *)data; + if (wd_valid_act(u)) { + wd_pretimeout_act = u; + } else { + error = EINVAL; + } break; case WDIOC_GETPRETIMEOUT: *(int *)data = (int)wd_pretimeout; @@ -290,11 +339,15 @@ watchdog_modevent(module_t mod __unused, switch(type) { case MOD_LOAD: callout_init(&wd_pretimeo_handle, true); + callout_init(&wd_softtimeo_handle, true); wd_dev = make_dev(&wd_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, _PATH_WATCHDOG); return 0; case MOD_UNLOAD: + callout_stop(&wd_pretimeo_handle); + callout_stop(&wd_softtimeo_handle); callout_drain(&wd_pretimeo_handle); + callout_drain(&wd_softtimeo_handle); destroy_dev(wd_dev); return 0; case MOD_SHUTDOWN: Modified: user/alfred/ewatchdog/sys/sys/watchdog.h ============================================================================== --- user/alfred/ewatchdog/sys/sys/watchdog.h Tue Feb 12 03:19:39 2013 (r246703) +++ user/alfred/ewatchdog/sys/sys/watchdog.h Tue Feb 12 04:22:00 2013 (r246704) @@ -32,14 +32,19 @@ #define _PATH_WATCHDOG "fido" -#define WDIOCPATPAT _IOW('W', 42, u_int) -#define WDIOC_SETTIMEOUT _IOW('W', 43, int) -#define WDIOC_GETTIMEOUT _IOR('W', 44, int) -#define WDIOC_GETTIMELEFT _IOR('W', 45, int) -#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int) -#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int) +#define WDIOCPATPAT _IOW('W', 42, u_int) /* pat the watchdog */ +#define WDIOC_SETTIMEOUT _IOW('W', 43, int) /* set/reset the timer */ +#define WDIOC_GETTIMEOUT _IOR('W', 44, int) /* get total timeout */ +#define WDIOC_GETTIMELEFT _IOR('W', 45, int) /* get time left */ +#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int) /* get the pre-timeout */ +#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int) /* set the pre-timeout */ +/* set the action when a pre-timeout occurs see: WD_SOFT_* */ #define WDIOC_SETPRETIMEOUTACT _IOW('W', 48, int) +/* use software watchdog instead of hardware */ +#define WDIOC_SETSOFT _IOW('W', 49, int) +#define WDIOC_SETSOFTTIMEOUTACT _IOW('W', 50, int) + #define WD_ACTIVE 0x8000000 /* * Watchdog reset, timeout set to value in WD_INTERVAL field. @@ -84,9 +89,9 @@ #define WD_TO_32SEC 35 /* action on pre-timeout trigger */ -#define WD_PRE_PANIC 1 /* panic */ -#define WD_PRE_DDB 2 /* enter debugger */ -#define WD_PRE_LOG 3 /* log(9) */ +#define WD_SOFT_PANIC 1 /* panic */ +#define WD_SOFT_DDB 2 /* enter debugger */ +#define WD_SOFT_LOG 3 /* log(9) */ #ifdef _KERNEL