code wiki / _hdl_build / nx_procchurn.nx

nx_procchurn.nx

buildroot/runtime/_hdl_build/nx_procchurn.nx

20244 B343 linesdepth 6pulls 7 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_procchurn.nx -- the PROCESS-CHURN axis the health plane never had (debt seq1317 / seq1318). WHY THIS EXISTS: 2026-07-30, nx_health said {overall:OK, degraded:0, down:0} with all 14 services UP while the NAS was forking 78.3 processes/sec sustained, burning 231 permil of an 8-core box in the KERNEL against 98 permil in userspace (a 2.36x kernel:user inversion) and taking 91718 context switches/sec. nx_resmon owns MEMORY, nx_netobs owns NETWORK -- the process-churn axis had NO organ, so the largest CPU consumer on the platform was invisible to every instrument we owned and was found by hand. This is that instrument. LAW: liveness is not performance. A board that only asks "is it up" cannot see the machine burning. WHAT IT MEASURES (two /proc/stat samples bracketing a real window -- deltas, never since-boot totals, because a since-boot average hides a storm that started an hour ago): forks/sec -- `processes` delta. THE headline: fork+exec is the most expensive thing a kernel does. ctxsw/sec -- `ctxt` delta. Rises with churn AND with thrash; corroborates, never diagnoses alone. intr/sec -- `intr` delta, first field. Device pressure, reported for context (not thresholded). kernel:user -- system:user+nice jiffies as permil. 1000 = parity. THE inversion detector. busy/idle -- share of measured capacity, self-normalising (no HZ and no core count needed -- every share is a fraction of the SAME jiffy total, so the arithmetic cannot drift when the box changes size. That is what makes this instrument hardware-portable). Policy lives in nx_procchurn_lib.nx so the gate exercises the SAME code (rule 9 + rule 15); thresholds are data-driven from knowledge/status/procchurn.conf (rule 11). Read-only. No hw writes (Rule 26). Exit code IS the verdict so a caller can gate on it: 0=GREEN 1=AMBER 2=RED 3=UNMEASURED. license_tier: ORIGINAL expect_exit: 0

dependencies 1 imports · 0 importers

nx_procchurn_lib.nx nx_procchurn.nx

imports: nx_procchurn_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main rm_conf rm_field rm_slen pc_scalar pc_line_ints rm_slen ↻ pc_line_ints ↻ pc_pids pc_name_is_pid pc_isdig pc_name_to_i64 pc_fork_by_parent pc_pid_seen pc_ppid_of ioa_read_pid_stat nxi_buf sys_openat_rd sys_read sys_close ioa_stat_parse pc_tally_parent pc_rate pc_ratio_permil pc_attrib_permil pc_verdict pc_frame pc_cat pc_catn pc_jappend pc_sev_last pc_find_in pc_int_at pc_isdig ↻ pc_sev_consumer pc_act_name pc_cat ↻ pc_catn ↻

structs

none

consts

27const PC_STATBUF: i64 = 8192
28const PC_CONFBUF: i64 = 4096
29const PC_FIELD_BYTES: i64 = 256
30const PC_NCPU_FIELDS: i64 = 10
31const PC_DEF_WINDOW_MS: i64 = 3000
32const PC_MIN_WINDOW_MS: i64 = 1000
33const PC_MAX_WINDOW_MS: i64 = 10000
34const PC_US_PER_MS: i64 = 1000
35const PC_DEF_F_AMBER: i64 = 20
36const PC_DEF_F_RED: i64 = 50
37const PC_DEF_R_AMBER: i64 = 1000
38const PC_DEF_R_RED: i64 = 1500
39const PC_DEF_C_AMBER: i64 = 20000
40const PC_DEF_C_RED: i64 = 50000
41const PC_EXIT_UNMEASURED: i64 = 3
42const PC_JBUF: i64 = 512
43const PC_MODE_644: i64 = 420
46const PC_SEEK_SET: i64 = 0
47const PC_SEEK_END: i64 = 2
48const PC_MS_PER_S: i64 = 1000
52const PC_ACT_AGE_WINDOWS: i64 = 2
56const PC_ACTTAIL: i64 = 4096
62const PC_PIDCAP: i64 = 4096
63const PC_PIDS_BYTES: i64 = 32768
64const PC_TALLY_MAX: i64 = 64
65const PC_TALLY_BYTES: i64 = 512

functions

71func pc_jappend(path: *u8, buf: *u8, n: i64) -> i64
called by 1: main
80func pc_scalar(buf: *u8, n: i64, key: *u8, out: *i64) -> i64
called by 1: main calls 1: pc_line_ints
86func main() -> i64