Watchdog Timeout Pretimeout Ioctls
Querying watchdog capabilities and identity, then reading and setting timeout, pretimeout, and time-left values from user space
Once your supervisor can open, ping, and cleanly stop a watchdog, the next question in any real deployment is: what can this particular watchdog actually do, and how much time is really left before it fires? Not every driver supports every feature — some hardware watchdogs have a fixed timeout burned into silicon, others let you tune it on the fly, and only some support a pretimeout warning before the reset. This lecture in our free linux device drivers course covers the ioctl set that answers those questions: capability discovery, timeout get/set, pretimeout get/set, and time-left queries. Getting this right is what separates a watchdog client that merely compiles from one that behaves correctly across different hardware in a free embedded systems course style product line.
What You Will Learn
Prerequisites
Discovering Capabilities With WDIOC_GETSUPPORT
Every watchdog driver is required to fill in a struct watchdog_info, and user space can read a copy of it with the WDIOC_GETSUPPORT ioctl. This struct is the single source of truth for what a given watchdog node can do — its human-readable identity string, an optional firmware version number, and an options bitmask of WDIOF_* flags describing supported features. A disciplined client always checks this before touching timeout or pretimeout ioctls, rather than assuming every driver behaves the same way.
struct watchdog_info info;
if (ioctl(wdfd, WDIOC_GETSUPPORT, &info) == -1) {
fprintf(stderr, "ep_wdt_info: GETSUPPORT failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("identity : %s\n", info.identity);
printf("firmware_version: %u\n", info.firmware_version);
printf("options bitmask : 0x%08x\n", info.options);
The bitmask is then tested field by field against the flags you actually depend on:
if (info.options & WDIOF_KEEPALIVEPING)
printf("supports keep-alive pings\n");
if (info.options & WDIOF_SETTIMEOUT)
printf("supports runtime timeout changes\n");
if (info.options & WDIOF_PRETIMEOUT)
printf("supports pretimeout warning\n");
| Flag | Meaning |
|---|---|
| WDIOF_KEEPALIVEPING | Driver accepts keep-alive pings via write or WDIOC_KEEPALIVE |
| WDIOF_SETTIMEOUT | Timeout can be changed at runtime via WDIOC_SETTIMEOUT |
| WDIOF_PRETIMEOUT | Driver supports a pretimeout warning before the actual reset |
| WDIOF_MAGICCLOSE | Driver honours the magic ‘V’ close sequence from the previous lecture |
Getting and Setting the Timeout
If WDIOF_SETTIMEOUT is set, the driver exposes a .set_timeout callback, and you can adjust the countdown length at runtime with WDIOC_SETTIMEOUT. The value you pass is in whole seconds, but hardware limitations mean the value the driver actually applies can differ from what you asked for — always re-read the same variable after the call rather than assuming your request was honoured exactly.
int timeout = 45;
if (ioctl(wdfd, WDIOC_SETTIMEOUT, &timeout) == -1)
fprintf(stderr, "ep_wdt_info: SETTIMEOUT failed: %s\n", strerror(errno));
else
printf("timeout applied by hardware: %d seconds\n", timeout);
To simply read the current value without changing anything, use WDIOC_GETTIMEOUT:
int current_timeout;
ioctl(wdfd, WDIOC_GETTIMEOUT, ¤t_timeout);
printf("current timeout: %d seconds\n", current_timeout);
Getting and Setting the Pretimeout
A pretimeout is an earlier warning point before the actual reset — useful for logging state, flushing storage, or alerting an operator in the last few seconds before the hard reset happens. It requires the driver to advertise WDIOF_PRETIMEOUT and provide a .set_pretimeout callback. The value is set with WDIOC_SETPRETIMEOUT, and must be strictly between zero and the current timeout — a value of zero or one that is not smaller than the timeout returns -EINVAL.
int pretimeout = 10;
if (ioctl(wdfd, WDIOC_SETPRETIMEOUT, &pretimeout) == -1) {
if (errno == EINVAL)
fprintf(stderr, "ep_wdt_info: pretimeout must be 0 < p < timeout\n");
else
fprintf(stderr, "ep_wdt_info: SETPRETIMEOUT failed: %s\n", strerror(errno));
}
| | |
watchdog armed pretimeout event hard reset fires
(warning window opens) (if never serviced)
Checking the Time Left
Beyond the static timeout value, WDIOC_GETTIMELEFT answers a more dynamic question: right now, how many seconds remain before this watchdog resets the board if nobody pings it again? This is invaluable for diagnostics and for supervisors that want to log a warning if the remaining time ever drops below a safety margin. Support for this ioctl depends on the driver providing a .get_timeleft() callback — if it does not, the call fails with EOPNOTSUPP rather than returning a wrong number.
int timeleft;
if (ioctl(wdfd, WDIOC_GETTIMELEFT, &timeleft) == -1) {
if (errno == EOPNOTSUPP)
printf("this driver does not report time left\n");
else
fprintf(stderr, "ep_wdt_info: GETTIMELEFT failed: %s\n", strerror(errno));
} else {
printf("time left before reset: %d seconds\n", timeleft);
}
Building ep_wdt_status: A Watchdog Inspection Tool
The following original tool combines everything above into a single diagnostic pass: identity, capabilities, current timeout, and time left — printing “n/a” for anything the driver does not support instead of guessing.
// ep_wdt_status.c — watchdog capability and status inspector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>
int main(int argc, char *argv[])
{
const char *node = (argc > 1) ? argv[1] : "/dev/watchdog0";
int fd = open(node, O_RDWR);
if (fd == -1) {
fprintf(stderr, "ep_wdt_status: open(%s): %s\n", node, strerror(errno));
return EXIT_FAILURE;
}
struct watchdog_info info;
if (ioctl(fd, WDIOC_GETSUPPORT, &info) == 0) {
printf("identity : %s\n", info.identity);
printf("firmware : %u\n", info.firmware_version);
printf("keepalive: %s\n", (info.options & WDIOF_KEEPALIVEPING) ? "yes" : "no");
printf("settimeout: %s\n", (info.options & WDIOF_SETTIMEOUT) ? "yes" : "no");
printf("pretimeout: %s\n", (info.options & WDIOF_PRETIMEOUT) ? "yes" : "no");
}
int timeout;
if (ioctl(fd, WDIOC_GETTIMEOUT, &timeout) == 0)
printf("timeout : %d s\n", timeout);
else
printf("timeout : n/a\n");
int timeleft;
if (ioctl(fd, WDIOC_GETTIMELEFT, &timeleft) == 0)
printf("timeleft : %d s\n", timeleft);
else
printf("timeleft : n/a (EOPNOTSUPP)\n");
close(fd);
return EXIT_SUCCESS;
}
$ sudo ./ep_wdt_status /dev/watchdog0
identity : ep_swwdt
firmware : 0
keepalive: yes
settimeout: yes
pretimeout: no
timeout : 30 s
timeleft : n/a (EOPNOTSUPP)
Common Mistakes and Troubleshooting
Calling SETTIMEOUT without checking WDIOF_SETTIMEOUT
Some drivers have a fixed hardware timeout; blindly calling the ioctl on those wastes an error path you should have avoided by checking the flag first.
Assuming the requested timeout was applied exactly
Hardware granularity can round your requested value; always re-read the variable after WDIOC_SETTIMEOUT returns.
Setting a pretimeout equal to or above the timeout
This always returns -EINVAL — the pretimeout must be strictly smaller than the current timeout.
Treating EOPNOTSUPP on GETTIMELEFT as a fatal error
It simply means the driver has no .get_timeleft() callback — handle it gracefully rather than aborting the supervisor.
Best Practices
Performance Considerations
All of these ioctls are cheap, synchronous kernel calls with no meaningful overhead — there is no performance reason to avoid querying capabilities or time left frequently. The only real cost is polling too aggressively for no benefit; querying time left once every few seconds in a supervisor loop is more than sufficient.
Summary and Key Takeaways
The watchdog_info struct returned by WDIOC_GETSUPPORT is the authoritative description of what a given watchdog node can do, and every optional ioctl — timeout changes, pretimeout, time-left queries — should be gated on its corresponding WDIOF_* flag rather than assumed. Timeout and pretimeout can both be read and adjusted at runtime within the constraints the hardware allows, and WDIOC_GETTIMELEFT gives a live countdown for diagnostics. Together with the open/stop/ping lifecycle from the previous lecture, this completes the full user-space contract for building a correct watchdog supervisor.
Frequently Asked Questions
What does WDIOC_GETSUPPORT actually return?
It fills a struct watchdog_info with the driver’s identity string, firmware version, and a bitmask of supported WDIOF_* capability flags.
Why did my WDIOC_SETTIMEOUT value come back different from what I requested?
Hardware timing granularity means the driver may round your requested value to the nearest value it can actually apply; always re-read it after the call.
Why does WDIOC_SETPRETIMEOUT return -EINVAL?
The pretimeout value must be greater than zero and strictly smaller than the current timeout, or the kernel rejects it.
What does EOPNOTSUPP mean on WDIOC_GETTIMELEFT?
It means the driver did not implement a .get_timeleft() callback, so time-left reporting simply is not available on that device.
Should I check capability flags before calling every ioctl?
Yes — not all watchdog drivers support timeout changes or pretimeout, and checking WDIOF_* flags first avoids relying on undefined behaviour.
Can I use these ioctls on any Linux watchdog driver?
The ioctl interface itself is generic and part of the watchdog framework, but which specific ioctls succeed depends entirely on the capabilities that particular driver advertises.
Continue the Free Linux Kernel Development Course
Next: the last reboot reason and diagnosing whether the watchdog caused a reset.
Next Lecture Back to Course Index