code wiki / _hdl_build / nx_ctxtop.nx
nx_ctxtop.nx
buildroot/runtime/_hdl_build/nx_ctxtop.nx
about
nx_ctxtop.nx -- WHO is producing the context switches. The producer-finder for seq1340.
nx_procchurn measured the box at 81k-93k ctxsw/sec in every sample (the one CONSTANT in the perf lane)
and DISPROVED forks as the driver -- forks swing 15->179->10 while ctxsw stays flat. A box-level rate
names no culprit, so this walks /proc/<pid>/status twice and attributes the switches per process.
LAW (rising-debt-means-find-the-producer): a rate with no owner is a symptom, not a diagnosis.
★Reports voluntary and nonvoluntary SEPARATELY because they demand OPPOSITE fixes: voluntary = the
process blocked itself (poll/read/sleep) -> batch, lengthen polls, go event-driven; nonvoluntary = the
scheduler preempted it -> reduce concurrency. A tool printing only the sum sends the fix the wrong way.
Exit code = 0 when the sample completed, 3 UNMEASURED (fail-closed, never a confident empty answer).
★2026-08-12 -- PRODUCER-CLASS ATTRIBUTION: the ranked rows name WHO; a final NX-CTXTOP-CLASS line names
WHAT KIND (SYSTEM=DSM/Synology, ESTATE=nx_* organs, KERNEL=kthreads, OTHER) so a RED churn axis carries
its own verdict instead of a human minting a cap and eyeballing comm strings. Field-measured 2026-08-12:
every top-8 producer was DSM (ssrtmpserverd/synorelayd/syno-cloud-clie/redis/kworkers), zero estate.
license_tier: ORIGINAL Read-only. No hw writes (Rule 26). expect_exit: 0
dependencies 2 imports · 0 importers
imports: nx_ctxtop_lib.nxnx_proc_ctl.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 21 | const CT_MAXP: i64 = 2048 |
| 22 | const CT_TABLE_BYTES: i64 = 16384 |
| 23 | const CT_DIRBUF: i64 = 65536 |
| 24 | const CT_STATBUF: i64 = 4096 |
| 25 | const CT_TOPK: i64 = 8 |
| 26 | const CT_TOPK_BYTES: i64 = 128 |
| 27 | const CT_WINDOW_MS: i64 = 3000 |
| 28 | const CT_US_PER_MS: i64 = 1000 |
| 29 | const CT_NAMEOFF: i64 = 6 |
| 30 | const CT_EXIT_UNMEASURED: i64 = 3 |
| 31 | const CT_SLASH: i64 = 47 |
| 32 | const CT_EXIT_REFUSED: i64 = 4 |
| 36 | const CT_CONFBUF: i64 = 4096 |
| 37 | const CT_LOADBUF: i64 = 128 |
| 40 | const CTC_SYSTEM: i64 = 0 |
| 41 | const CTC_ESTATE: i64 = 1 |
| 42 | const CTC_KERNEL: i64 = 2 |
| 43 | const CTC_OTHER: i64 = 3 |
functions
| 47 | func ct_scan(pids: *i64, vols: *i64, nvs: *i64, dbuf: *u8, path: *u8, sbuf: *u8) -> i64 |
| 141 | func ct_putname(pid: i64, path: *u8, sbuf: *u8) -> i64 called by 1: main |
| 168 | func ct_has(hay: *u8, n: i64, needle: *u8) -> i64 called by 1: ct_class_of |
| 191 | func ct_class_of(tid: i64, path: *u8, cbuf: *u8) -> i64 |
| 220 | func main(argc: i64, argv: *i64) -> i64 |