code wiki / (root) / nx_ioadmit_gate.nx

nx_ioadmit_gate.nx

buildroot/runtime/nx_ioadmit_gate.nx

25917 B422 linesdepth 5pulls 7 transitivereach 0 importersview sourcekind gate/proof
docsdependenciesstructsconstsfunctions

about

nx_ioadmit_gate.nx -- referee for nx_ioadmit_lib, the I/O-storm admission ruler every I/O spawner (first consumer: nx_torrent_daemon) asks before adding uninterruptible I/O to the shared array. It gates the SAME functions the daemon runs (nx_ioadmit_lib.nx), not a reimplementation. The budget arithmetic is tested as a pure function on synthetic inputs (deterministic, no box state needed); the /proc readers are tested against the live kernel (any Linux answers) plus a fixture parse so the parser is proven on bytes whose answer is KNOWN, not merely "something came back". THE TEETH THAT MATTER: T3/T4 pin the two numbers that make this a ruler and not a wish: the storm line clamps the budget to ZERO (never negative, never "a little over"), and the reserve slot is LOAD-BEARING -- drop it and the spawner becomes the process that crosses the line. T5 is the THIRD STATE: unobservable inputs return IOA_UNREADABLE, never a budget. A caller that reads -1 as "minus one worker" would be the fabrication this estate forbids; the daemon names its own fallback (D_UNOBS_SPAWNS) and this tooth proves the lib never invents one. T7 neg-control: a comm nobody runs counts 0 -- a counter that returns >0 for a nonsense name is counting something other than the name. T8 positive control: the gate's OWN comm (read from /proc/self/comm, not assumed) counts >= 1, so the /proc walk is proven to SEE a running process, not just to return without error. T9 bite: the ruler FIRES at the storm line and stays SILENT with headroom -- proven in one cell. license_tier: ORIGINAL expect_exit: 0

dependencies 2 imports · 0 importers

nx_gate_verdict.nx nx_ioadmit_lib.nx nx_ioadmit_gate.nx

imports: nx_gate_verdict.nxnx_ioadmit_lib.nx

imported by: nobody (leaf or entry point)

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

main gv_ctr sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_head gv_puts sys_write ↻ ioa_measure sys_mmap ↻ rm_read sys_openat_rd sys_read sys_close ioa_ncpu rm_field rm_slen sys_munmap gv_check gv_puts ↻ gv_puts ↻ gv_num sys_mmap ↻ sys_write ↻ sys_munmap ↻ ioa_spawn_budget ig_slen ioa_ncpu ↻

structs

none

consts

25const IG_FIX_A: *u8 = "cpu 10 20 30 40\ncpu0 1 2 3\ncpu1 1 2 3\ncpu2 1 2 3\nintr 55 1 2 3\nctxt 99\nprocs_running 2\nprocs_blocked 3\n"
26const IG_FIX_NOCPU: *u8 = "cpu 10 20 30 40\nintr 55\nprocs_running 2\n"
27const IG_NCPU: i64 = 8 // synthetic box for the pure budget teeth (the measured host, but any value works)
28const IG_COMMBUF: i64 = 64 // /proc/self/comm is at most TASK_COMM_LEN bytes + newline
29const IG_FIX_STAT_A: *u8 = "4242 (nx_torrent_get.) S 1 4242 4242 0 -1 4194560 91 0 0 0 3 1 0 0 20 0 1 0 176053211 1048576 0 18446744073709551615\n"
30const IG_FIX_STAT_B: *u8 = "7 (a) b) R 77 7 7 0 -1 0 0 0 0 0 0 0 0 0 20 0 1 0 5 0 0 0\n"
35const IG_CONG_WARN_KB: i64 = 100000
36const IG_CONG_STORM_KB: i64 = 400000
38const IG_CONG_ABSURD_KB: i64 = 99999999
40const IG_CONG_BELOW_WARN_KB: i64 = 1000
41const IG_DW_SLOTS: i64 = 32
45const IG_FIX_MEM: *u8 = "Dirty: 644820 kB\nWritebackTmp: 12345 kB\nWriteback: 19340 kB\n"
46const IG_FIX_MEM_DIRTY: i64 = 644820
47const IG_FIX_MEM_WB: i64 = 19340
52const IG_FIX_DS: *u8 = " 9 40 md40 1 0 2 3 4 0 6 7 8 9 10\n 9 4 md4 100 0 500 10 200 0 700 20 3 40 50\n"
53const IG_DS_MD4_SREAD: i64 = 500
54const IG_DS_MD4_SWRIT: i64 = 700
55const IG_DS_MD4_INFLIGHT: i64 = 3
56const IG_DS_MD4_MSIO: i64 = 40
57const IG_DS_MD40_SREAD: i64 = 2
58const IG_DS_MD40_SWRIT: i64 = 6
59const IG_DS_OUT_SLOTS: i64 = 64
62const IG_DS_RATE_SECTORS: i64 = 2048
63const IG_DS_RATE_MS: i64 = 1000
64const IG_DS_RATE_EXPECT_KBS: i64 = 1024
69const IG_MED_S0: i64 = 14
70const IG_MED_S1: i64 = 10
71const IG_MED_S2: i64 = 5
72const IG_MED_S3: i64 = 10
73const IG_MED_S4: i64 = 9
74const IG_MED_REAL_EXPECT: i64 = 10
76const IG_MED_QUIET: i64 = 2
77const IG_MED_SPIKE: i64 = 14
78const IG_MED_SPIKE_EXPECT: i64 = 2
80const IG_MED_STORM_LO: i64 = 9
81const IG_MED_STORM_HI: i64 = 10
82const IG_MED_STORM_EXPECT: i64 = 10
83const IG_MED_K5: i64 = 5
84const IG_MED_SLOTS: i64 = 64
85const IG_MED_LIVE_K: i64 = 3
86const IG_MED_LIVE_GAP_MS: i64 = 50
90const IG_OWN_PREFIX: *u8 = "nx_"
92const IG_OWN_NOBODY: *u8 = "zzq_nosuchprefix_"
93const IG_OWN_SLOTS: i64 = 64
96const IG_SHARE_PART: i64 = 250
97const IG_SHARE_WHOLE: i64 = 1000
98const IG_SHARE_EXPECT: i64 = 250

functions

100func ig_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 1: main
102func main(argc: i64, argv: *i64) -> i64