HEARTBEAT(9)

πŸ“¦ version 11.0, in nixpkgs unstable

πŸ’“ HEARTBEAT(9) β€” the kernel developer's manual page, bestie edition πŸ’“

okay so this is the heartbeat(9) page from the Kernel Developer's Manual, and honestly it's giving "the system's literal pulse" energy. buckle up 🫢


✨ SYNOPSIS ✨

first, the kernel config bits:

options HEARTBEAT
options HEARTBEAT_MAX_PERIOD_DEFAULT=15

then the header you gotta pull in:

#include <sys/heartbeat.h>

and here's every single function signature, verbatim, no edits:

void
heartbeat_start(void);

void
heartbeat(void);

void
heartbeat_suspend(void);

void
heartbeat_resume(void);

#ifdef DDB

void
heartbeat_dump(void);

#endif

not the #ifdef DDB gate on heartbeat_dump() β€” that one's only there when DDB is compiled in. iykyk πŸ’…


🩺 DESCRIPTION 🩺

so the heartbeat subsystem is basically the kernel's wellness check. it verifies that soft interrupts (softint(9)) and the system timecounter(9) are actually making progress over time β€” and if they look stuck, it panics. not me being dramatic, that's literally the behaviour 😭

how long it waits before panicking is controlled by the sysctl knob kern.heartbeat.max_period, which defaults to 15 seconds. set it to zero and heartbeat checks are disabled entirely β€” vibe check: skipped πŸ™ˆ

the periodic hardware timer interrupt handler calls heartbeat() every tick on each CPU. once per second (i.e., every hz(9) ticks), heartbeat() schedules a soft interrupt at priority SOFTINT_CLOCK to advance the current CPU's view of time_uptime(9).

here's where it gets real. heartbeat() checks whether time_uptime(9) has changed, to see if either the timecounter(9) or soft interrupts on the current CPU are stuck. and it panics if:

  • it hasn't advanced within kern.heartbeat.max_period seconds worth of ticks, or
  • it has updated and the current CPU's view of it hasn't been updated by more than kern.heartbeat.max_period seconds.

yep, both paths lead to panic. no cap πŸ’€

heartbeat() also checks whether the next online CPU has advanced its view of time_uptime(9) β€” that's how it catches soft interrupts (including callout(9)) being stuck on that other CPU. if it hasn't updated within kern.heartbeat.max_period seconds, heartbeat() sends an ipi(9) to panic on that CPU. and if that CPU has not acknowledged the ipi(9) within one second, heartbeat() panics on the current CPU instead. the way it just escalates πŸ”₯


πŸŽ€ FUNCTIONS πŸŽ€

  • heartbeat() β€” checks for timecounter and soft interrupt progress on this CPU and on another CPU, and schedules a soft interrupt to advance this CPU's view of timecounter progress. called by hardclock(9) periodically. main character energy fr fr πŸ‘‘
  • heartbeat_dump() β€” prints each CPU's heartbeat counter, uptime cache, and uptime cache timestamp (in units of heartbeats) to the console. you can invoke it from ddb(9) with call heartbeat_dump. iconic debugging moment ⭐
  • heartbeat_resume() β€” resumes heartbeat monitoring of the current CPU. called after a CPU has started running but before it has been marked online. welcome back bestie πŸ¦‹
  • heartbeat_start() β€” starts monitoring heartbeats systemwide. called by main() in sys/kern/init_main.c as soon as soft interrupts can be established. the glow-up moment ✨
  • heartbeat_suspend() β€” suspends heartbeat monitoring of the current CPU. called after the current CPU has been marked offline but before it has stopped running. nap time, deserved 😴

πŸ“‚ CODE REFERENCES πŸ“‚

the heartbeat subsystem is implemented in sys/kern/kern_heartbeat.c. go read the source, it's right there πŸ’–


πŸ‘€ SEE ALSO πŸ‘€


🌸 HISTORY 🌸

the heartbeat subsystem first appeared in NetBSD 11.0. a whole era πŸ‘‘


lowkey the whole point: if the clock or the softints stop moving, the kernel does not just sit there pretending everything's fine. it panics. loudly. periodt πŸ’…

and that's the page, bestie πŸŽ€ this one's from Debian, dated July 6, 2023 β€” go forth and keep those CPUs beating πŸ’“πŸ«Ά

πŸ“¦ where this page comes from