nx_ioadmit_gate.nx
buildroot/runtime/nx_ioadmit_gate.nx
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
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
structs
| none |
consts
| 25 | const 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" |
| 26 | const IG_FIX_NOCPU: *u8 = "cpu 10 20 30 40\nintr 55\nprocs_running 2\n" |
| 27 | const IG_NCPU: i64 = 8 // synthetic box for the pure budget teeth (the measured host, but any value works) |
| 28 | const IG_COMMBUF: i64 = 64 // /proc/self/comm is at most TASK_COMM_LEN bytes + newline |
| 29 | const 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" |
| 30 | const 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" |
| 35 | const IG_CONG_WARN_KB: i64 = 100000 |
| 36 | const IG_CONG_STORM_KB: i64 = 400000 |
| 38 | const IG_CONG_ABSURD_KB: i64 = 99999999 |
| 40 | const IG_CONG_BELOW_WARN_KB: i64 = 1000 |
| 41 | const IG_DW_SLOTS: i64 = 32 |
| 45 | const IG_FIX_MEM: *u8 = "Dirty: 644820 kB\nWritebackTmp: 12345 kB\nWriteback: 19340 kB\n" |
| 46 | const IG_FIX_MEM_DIRTY: i64 = 644820 |
| 47 | const IG_FIX_MEM_WB: i64 = 19340 |
| 52 | const 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" |
| 53 | const IG_DS_MD4_SREAD: i64 = 500 |
| 54 | const IG_DS_MD4_SWRIT: i64 = 700 |
| 55 | const IG_DS_MD4_INFLIGHT: i64 = 3 |
| 56 | const IG_DS_MD4_MSIO: i64 = 40 |
| 57 | const IG_DS_MD40_SREAD: i64 = 2 |
| 58 | const IG_DS_MD40_SWRIT: i64 = 6 |
| 59 | const IG_DS_OUT_SLOTS: i64 = 64 |
| 62 | const IG_DS_RATE_SECTORS: i64 = 2048 |
| 63 | const IG_DS_RATE_MS: i64 = 1000 |
| 64 | const IG_DS_RATE_EXPECT_KBS: i64 = 1024 |
| 69 | const IG_MED_S0: i64 = 14 |
| 70 | const IG_MED_S1: i64 = 10 |
| 71 | const IG_MED_S2: i64 = 5 |
| 72 | const IG_MED_S3: i64 = 10 |
| 73 | const IG_MED_S4: i64 = 9 |
| 74 | const IG_MED_REAL_EXPECT: i64 = 10 |
| 76 | const IG_MED_QUIET: i64 = 2 |
| 77 | const IG_MED_SPIKE: i64 = 14 |
| 78 | const IG_MED_SPIKE_EXPECT: i64 = 2 |
| 80 | const IG_MED_STORM_LO: i64 = 9 |
| 81 | const IG_MED_STORM_HI: i64 = 10 |
| 82 | const IG_MED_STORM_EXPECT: i64 = 10 |
| 83 | const IG_MED_K5: i64 = 5 |
| 84 | const IG_MED_SLOTS: i64 = 64 |
| 85 | const IG_MED_LIVE_K: i64 = 3 |
| 86 | const IG_MED_LIVE_GAP_MS: i64 = 50 |
| 90 | const IG_OWN_PREFIX: *u8 = "nx_" |
| 92 | const IG_OWN_NOBODY: *u8 = "zzq_nosuchprefix_" |
| 93 | const IG_OWN_SLOTS: i64 = 64 |
| 96 | const IG_SHARE_PART: i64 = 250 |
| 97 | const IG_SHARE_WHOLE: i64 = 1000 |
| 98 | const IG_SHARE_EXPECT: i64 = 250 |
functions
| 100 | func ig_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } called by 1: main |
| 102 | func main(argc: i64, argv: *i64) -> i64 |