daniel-p-carvalho opened a new pull request, #20782:
URL: https://github.com/apache/nuttx/pull/20782
## Summary
Add a task watchdog supervisor (`CONFIG_TASKWDT`): one hardware watchdog
shared
among any number of tasks, each with its own time-out. It is the kind of
service Zephyr calls `task_wdt`, but its interface is the Linux watchdog API
instead of a new set of functions.
Each task opens `/dev/taskwdt` (`CONFIG_TASKWDT_DEVPATH`) and gets a channel:
- `write()` or `WDIOC_KEEPALIVE` feeds it, `WDIOC_SETTIMEOUT` sets its
time-out in milliseconds, `WDIOC_GETSTATUS` reports it.
- a `'V'` in a `write()` (or `WDIOC_STOP`) disarms it, `WDIOC_START` arms it
again.
- `close()` frees the channel only if it is disarmed. A channel closed while
armed is never fed again, so a task that exits or is killed without
disarming it ends in a reset, as it would on Linux.
The supervisor sits on top of any watchdog registered with
`watchdog_register()` and feeds it from the low priority work queue only
while
every armed channel is within its time-out. When one is late it logs the pid
and the name of the task that opened it and stops feeding, so the hardware
resets the system (or panics at once with `CONFIG_TASKWDT_PANIC`, to get a
crash dump). With `CONFIG_TASKWDT_AUTOSTART` the hardware watchdog is armed
at
initialization and fed even with no channel open, which also covers a hang of
the whole system (scheduler, work queue, interrupts) before any task has
registered. It replaces `WATCHDOG_AUTOMONITOR`, which feeds unconditionally,
so
the two exclude each other.
Why a separate driver and not an extension of `drivers/timers/watchdog.c`:
the
upper half exposes one lower half to one user, the supervisor needs per-open
state (one channel per `open()`) and a policy on top of the existing
hardware, and it must not depend on which lower half is used.
Commits:
1. `drivers/timers: add a task watchdog supervisor.` The driver, its header,
Kconfig, Make.defs/CMake, and the documentation page.
2. `boards/sim: add a simulated watchdog timer.` `CONFIG_SIM_WATCHDOG`: a
software watchdog at `CONFIG_WATCHDOG_DEVPATH`. The simulator cannot
reset,
so when it expires the simulator exits with
`CONFIG_SIM_WATCHDOG_EXITCODE` (77).
3. `boards/sim: add a taskwdt configuration.` `sim:taskwdt`, which builds the
supervisor in CI and enables the `taskwdt_test` application
(apache/nuttx-apps#3874, to be merged first).
## Impact
New option, off by default; nothing changes for existing configurations.
`TASKWDT` depends on `WATCHDOG` and `SCHED_LPWORK` and excludes
`WATCHDOG_AUTOMONITOR`. Each channel costs one small allocation plus the
name of the task. New documentation page
`os/drivers/character/timers/taskwdt`, and a `taskwdt` section on the sim
board page. No change to the existing watchdog upper half or to any other
board.
## Testing
Host: Linux x86_64 (Ubuntu), gcc for the sim, Microchip XC32 v6.00 for the
board. The application used is `taskwdt_test` from the companion nuttx-apps
PR;
run it without arguments for the list of cases. A `PASS`/`FAIL` line is
printed
by the cases that must not reset the system. The others stop feeding on
purpose
and expect a reset.
**Simulator** (`./tools/configure.sh sim:taskwdt && make`, then
`taskwdt_test <case>` in NSH; a "reset" is the exit status 77):
| Case | Result |
|------|--------|
| `idle` (no channel, 30 s), `feed`, `write`, `disarm`, `stop`, `status`,
`errors`, `multi`, `leak` (1000 open/close, heap unchanged) | PASS |
| `starve`, `exit` (closed while armed), `kill` (task deleted), `two` (one
of two threads starves), `late` (feeding resumes after the time-out), `hog`
(scheduler locked) | exit status 77 in 5 to 8 s |
| `CONFIG_TASKWDT_PANIC=y`, `starve` | time-out report, then the panic dump |
| `CONFIG_TASKWDT_AUTOSTART=n`: `starve` resets (first `open()` arms the
hardware); `hog` with no channel does not | as expected |
**Board**: EV49N51A (WFI32E01PE, PIC32MZ-W1) with the watchdog of #20776 as
`/dev/watchdog0` (time-out 8.2 s nominal, LPRC based, so 6.7 to 9.3 s), and
the
supervisor started from the board bring-up (a board configuration for it is
not
part of this PR). Same cases, times are seconds after the command, "boot" is
the `Last reset was caused by the watchdog` line of the next boot:
| Case | Result | Report | Boot |
|------|--------|--------|------|
| `idle 30`, `feed 20`, `write 20`, `disarm 12`, `stop 12`, `status`,
`errors`, `multi 15`, `leak 1000` | PASS (heap 10648 before and after) | | |
| `starve 2000` | reset | 2.06 | 9.59 |
| `exit 2000` | reset | 2.56 | 10.09 |
| `kill 2000` | reset, names `victim` | 3.06 | 10.59 |
| `two 2000` | reset, names `starver` | 2.56 | 10.09 |
| `late 1000` | reset | 1.51 | 9.09 |
| `hog` (scheduler locked) | reset | | 8.04 |
| `hang` (interrupts disabled) | reset | | 8.08 |
| `TASKWDT_PANIC=y`, `starve 2000` | report, panic dump, reset | 2.11 | 9.64
|
| `TASKWDT_AUTOSTART=n`: `idle 30` PASS, `starve 2000` | reset | 2.11 | 9.64
|
| `TASKWDT_AUTOSTART=n`: `hog` with no channel | no reset in 25 s (hardware
not armed) | | |
The reset comes about 7.5 s after the report: the last feed was at most one
`CONFIG_TASKWDT_INTERVAL` (500 ms) before it, plus the hardware time-out.
```
nsh> taskwdt_test starve 2000
channel of 2000 ms never fed
expect: system reset
taskwdt_worker: Task watchdog timeout: pid 14 (taskwdt_test), 2000 ms
Last reset was caused by the watchdog
NuttShell (NSH) NuttX-13.1.0
```
```
nsh> taskwdt_test kill 2000
deleting pid 5 that feeds a channel of 2000 ms
expect: system reset
taskwdt_worker: Task watchdog timeout: pid 5 (victim), 2000 ms
Last reset was caused by the watchdog
```
Documentation: `make html` builds the new page and the changed ones without
warnings; the 32 existing warnings of the tree are not related.
`tools/checkpatch.sh -c -u -m -g` is clean for all the commits.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]