Skip to main content

Module taskwd

Module taskwd 

Source
Expand description

taskwd — the IOC’s task watchdog, C libCom/src/taskwd/taskwd.c (R7.0.10).

One low-priority thread wakes every TASKWD_DELAY and asks each registered task whether it is still running. When one stops running the watchdog says so on the console, calls that task’s own callback, and tells every registered monitor — which is how a C IOC turns a wedged scan thread into an operator-visible event instead of records that quietly stop updating.

This is not a thread registry. Nothing here enumerates threads, names them or reports their stacks; a task is here because it asked to be watched, and the list is the watchdog’s, not the process’s.

§What “suspended” means here

C’s watchdog polls epicsThreadIsSuspended(tid) (taskwd.c:99). On vxWorks that is a real OS state; on POSIX it is a flag epicsThreadSuspendSelf sets, so a C IOC on Linux only ever reports a thread that suspended itself — out of memory, cantProceed. Rust has neither: a thread cannot be suspended by another and never suspends itself.

So the port asks the question the other way round, which is the only way it can be asked here: a task checks in (TaskwdEntry::check_in) as it goes round its loop, and a task that stops checking in inside the interval it declared is this port’s suspended. That covers strictly more than C’s POSIX build does — a thread wedged on a lock or an unbounded read is invisible to epicsThreadIsSuspended and visible here — and the operator’s side of it is unchanged: the same console line, the same callback, the same taskwdShow state column.

A task that cannot promise to come back — one parked in accept(), or in a blocking read with no deadline — registers CheckIn::Unbounded and is listed but never reported, which is exactly what C’s POSIX build does with every one of its tasks.

§Identity is the registration, not a thread id

C keys everything on epicsThreadId, because the state it polls belongs to a thread. Half the port’s equivalents of C’s call sites are futures, which have no thread of their own and may run on a different one after every await, so a thread id would name the wrong thing for them and the right thing for the others — one field, two meanings. Registration returns a TaskwdEntry instead, and TaskwdId is what the monitor API carries.

The handle is also what removes the task: C pairs every taskwdInsert with a taskwdRemove on each exit path and errlogs when it is passed a thread that was never inserted (taskwd.c:241-243). Dropping the handle removes it, on every path including a panic, and there is no way to ask for the removal of something that was never registered.

§Not ported

  • taskwdAnyInsert / taskwdAnyRemove (taskwd.c:306-354) — the deprecated pre-3.15 monitor API, which C implements as a monitor whose notify fires only on suspension. Nothing in base or in the modules this workspace ports calls it; the TaskwdMonitor trait is what it wraps.
  • The free-node pool (taskwd.c:395-430) and the %d free nodes it puts in the report. It is an allocator for three C structs that share a union; Rust drops the entry instead, so there is no pool to count.
  • twdctlDisable (taskwd.c:74) — the enum has the state, nothing in R7.0.10 ever assigns it.

Structs§

TaskInfo
What a monitor is told about, and what taskwd_show lists.
TaskwdEntry
A watched task’s registration. Dropping it stops the watch — C taskwdRemove (taskwd.c:207-244) on every exit path, including the ones C’s callers have to remember.
TaskwdId
The watchdog’s name for one registration — C’s epicsThreadId in the monitor API, without the claim that a task is a thread.
TaskwdMonitorEntry
A registered monitor’s handle. Dropping it unregisters the monitor.

Enums§

CheckIn
What a task promises about coming back to check in.

Constants§

TASKWD_DELAY
How often the watchdog looks at its list — C TASKWD_DELAY (taskwd.c:80).

Traits§

TaskwdMonitor
Something watching every task, rather than one — C’s taskwdMonitor (taskwd.h:41-45). Every method is optional there (a NULL slot is skipped), so every method here has a do-nothing default.

Functions§

taskwd_init
Start the watchdog thread if it is not running — C taskwdInit (taskwd.c:168-172), which iocInit calls early (iocInit.c:151) and every registration calls for itself.
taskwd_insert
Watch this task — C taskwdInsert (taskwd.c:177-205).
taskwd_monitor_add
Watch every task — C taskwdMonitorAdd (taskwd.c:249-264).
taskwd_show
Report the watchdog’s list — C taskwdShow (taskwd.c:359-390).

Type Aliases§

TaskwdCallback
A task’s own answer to being found stuck — C’s TASKWDFUNC and its usr pointer collapsed into one closure (taskwd.h:33).