From d905c9da4d8984f19cd74a17cebd2743d399b035 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 30 Nov 2015 14:49:56 +0100 Subject: Reorganize source directory --- src/unitd/watchdog.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/unitd/watchdog.c (limited to 'src/unitd/watchdog.c') diff --git a/src/unitd/watchdog.c b/src/unitd/watchdog.c new file mode 100644 index 0000000..f462d00 --- /dev/null +++ b/src/unitd/watchdog.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 Matthias Schiffer + * + * Based on "procd" by: + * Copyright (C) 2013 Felix Fietkau + * Copyright (C) 2013 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "unitd.h" +#include "watchdog.h" + +#include + +#include +#include +#include +#include + +#include + +#include + + +#define WDT_PATH "/dev/watchdog" + +static struct uloop_timeout wdt_timeout; +static int wdt_fd = -1; +static int wdt_frequency = 5; + +void watchdog_ping(void) +{ + DEBUG(4, "Ping\n"); + if (wdt_fd >= 0 && write(wdt_fd, "X", 1) < 0) + ERROR("WDT failed to write: %s\n", strerror(errno)); +} + +static void watchdog_timeout_cb(struct uloop_timeout *t) +{ + watchdog_ping(); + uloop_timeout_set(t, wdt_frequency * 1000); +} + +void watchdog_set_stopped(bool val) +{ + if (val) + uloop_timeout_cancel(&wdt_timeout); + else + watchdog_timeout_cb(&wdt_timeout); +} + +bool watchdog_get_stopped(void) +{ + return !wdt_timeout.pending; +} + +int watchdog_timeout(int timeout) +{ + if (wdt_fd < 0) + return 0; + + if (timeout) { + DEBUG(4, "Set watchdog timeout: %ds\n", timeout); + ioctl(wdt_fd, WDIOC_SETTIMEOUT, &timeout); + } + ioctl(wdt_fd, WDIOC_GETTIMEOUT, &timeout); + + return timeout; +} + +int watchdog_frequency(int frequency) +{ + if (wdt_fd < 0) + return 0; + + if (frequency) { + DEBUG(4, "Set watchdog frequency: %ds\n", frequency); + wdt_frequency = frequency; + } + + return wdt_frequency; +} + +char* watchdog_fd(void) +{ + static char fd_buf[3]; + + if (wdt_fd < 0) + return NULL; + snprintf(fd_buf, sizeof(fd_buf), "%d", wdt_fd); + + return fd_buf; +} + +void watchdog_init(int preinit) +{ + char *env = getenv("WDTFD"); + + if (wdt_fd >= 0) + return; + + wdt_timeout.cb = watchdog_timeout_cb; + if (env) { + DEBUG(2, "Watchdog handover: fd=%s\n", env); + wdt_fd = atoi(env); + unsetenv("WDTFD"); + } else { + wdt_fd = open("/dev/watchdog", O_WRONLY); + } + + if (wdt_fd < 0) + return; + + if (!preinit) + fcntl(wdt_fd, F_SETFD, fcntl(wdt_fd, F_GETFD) | FD_CLOEXEC); + + LOG("- watchdog -\n"); + watchdog_timeout(30); + watchdog_timeout_cb(&wdt_timeout); + + DEBUG(4, "Opened watchdog with timeout %ds\n", watchdog_timeout(0)); +} + + +void watchdog_no_cloexec(void) +{ + if (wdt_fd < 0) + return; + + fcntl(wdt_fd, F_SETFD, fcntl(wdt_fd, F_GETFD) & ~FD_CLOEXEC); +} -- cgit v1.2.3