Skip to main content

Module delayacct

Module delayacct 

Source
Expand description

Delay accounting via TASKSTATS generic netlink.

The kernel accounts, per task, how long it spent waiting rather than running: waiting for a CPU while runnable, waiting for synchronous block I/O, and waiting for a page to be swapped back in. Those three numbers are what separate “this process is working” from “this process is stuck”, and nothing in /proc exposes them.

htop reaches the same data through libnl3, which it dlopens and uses through function pointers. That is a runtime dependency on a library that may not be installed, loaded lazily so the failure is a dlopen that returns NULL. The protocol is four messages; speaking it directly removes the dependency and the failure mode, and is the reason Cargo.toml still lists nothing but libc.

§The two ways this fails, and why they are not errors

  • EPERM — TASKSTATS_CMD_GET requires CAP_NET_ADMIN. An unprivileged gander gets EPERM on every request, which is the normal case, not a fault. probe() records it once and no further requests are sent.
  • ENOENT on the family — CONFIG_TASKSTATS is not compiled in. The generic-netlink family does not exist, and neither does the column.

Both end up as None on every row, which renders -: “not measured”, which is the truth. A row must never show 0.0% for a figure nobody read.

§Units

Every *_delay_total is nanoseconds, and ac_etime is microseconds. The percentage htop prints is Δdelay / Δ(ac_etime × 1000), i.e. the share of the task’s wall-clock life spent waiting. It is a lifetime average, not an instantaneous rate, because the kernel exposes no interval counter — see docs/ROADMAP.md.

Structs§

DelayAcct
A connected generic-netlink socket bound to the TASKSTATS family.
DelayStats
Cumulative delay counters for one task, all in nanoseconds, plus the task’s elapsed wall-clock life in microseconds.

Functions§

parse_taskstats
Parse a struct taskstats blob into the four fields that are read.