code wiki / (root) / nx_ioconfirm.nx

nx_ioconfirm.nx source

↩ module page · 290 lines · 13606 B

1// nx_ioconfirm.nx -- THE CONFIRMED I/O-STORM LEVEL: maintained continuously, read in constant time. 2// Rung DG7, /compare/degradation. 3// 4// WHY THIS EXISTS, MEASURED. The D-state witness that gates every build on this estate reads /proc/stat 5// ONCE. nx_blkprofile sampled 2,400 times at 100 ms on 2026-09-04 and found procs_blocked with median 4 6// against a bar of 8, p90 8, max 15, and 118 permil of SINGLE samples at or above the bar. So roughly one 7// build in eight is refused by a transient spike on a box whose sustained level is HALF the bar. Two 8// nx_dstate rosters 90 s apart shared only four pids: the D population is mostly churn over a small 9// persistent core. 10// 11// AND THE OBVIOUS FIX IS THE WRONG ONE, WHICH IS THE POINT OF THIS ORGAN. Making the gate take a median 12// AT DECISION TIME is already built and wired (ioa_measure_median, armed by two keys in build_admit.conf) 13// and the same run shows why it must not be armed: the refusal curve is STILL FALLING at a 12,000 ms span 14// (118 -> 36 permil) and has not flattened, so any span wide enough to help costs SECONDS on EVERY 15// admission check -- the clock dispatcher's pre-dispatch call included. That does not remove the stall, it 16// relocates it onto every caller. build_admit.conf refuses arming for exactly this reason and asks for the 17// cost to be measured first. It now has been, and the answer is no. 18// 19// THIS IS THE AEROSPACE ANSWER INSTEAD. Flight control does not confirm a fault inside the control law; a 20// monitor confirms CONTINUOUSLY and the law reads an already-confirmed state. So: a beat pays the whole 21// confirmation window once per cadence, off the critical path, and every consumer reads one small file in 22// constant time. The window costs the beat its span and costs the consumer nothing. 23// 24// FRESHNESS IS PART OF THE ANSWER, NOT A FOOTNOTE. A stale level is WORSE than none: it decides with 25// authority about a box it last saw minutes ago. `read` returns FRESH, STALE and ABSENT as three distinct 26// exits so a consumer that cannot get FRESH falls back to its own single sample -- degrade to the 27// incumbent, never acquit on a reading nobody took. 28// 29// KEY NAMES ARE DELIBERATELY NOT build_admit.conf's. That conf is parsed by PLAIN SUBSTRING with no 30// comment handling, and its own header records a measured incident where prose describing a key ARMED it. 31// This file uses confirm_samples and confirm_gap_ms so its bytes can never be mistaken for that envelope. 32// 33// COMPOSES, DOES NOT RE-IMPLEMENT: ioa_measure_median is the same sampler nx_build_admit would use if it 34// were armed, so the level published here is the level that gate would have computed -- one ruler, not two. 35 36import "nx_syscalls.nx" 37import "nx_ioadmit_lib.nx" 38 39const IC_STDOUT: i64 = 1 40const IC_STDERR: i64 = 2 41const IC_OUTCAP: i64 = 8192 42const IC_MEAS_BYTES: i64 = 64 43const IC_BOX_BYTES: i64 = 64 44const IC_MODE_644: i64 = 420 45const IC_UNREADABLE: i64 = 0 - 1 46const IC_EXIT_STALE: i64 = 1 47const IC_EXIT_USAGE: i64 = 2 48const IC_EXIT_ABSENT: i64 = 3 49const IC_EXIT_UNMEASURED: i64 = 4 50// DEFAULTS ARE THE WIDEST SPAN ACTUALLY MEASURED, AND THAT IS A FLOOR RATHER THAN AN OPTIMUM: the DG1 run 51// stopped at 12,000 ms with the curve still falling, so a wider window is likely better and is NOT yet 52// evidenced. A beat pays this span once per cadence, so widening it is cheap -- but it must be MEASURED 53// before it is claimed, and this constant is the last value that was. 54const IC_DEF_SAMPLES: i64 = 5 55const IC_DEF_GAP_MS: i64 = 3000 56// The freshness bound must exceed the producing cadence or the axis is blind by construction. Stated here 57// rather than assumed: at the estate's 300 s status cadence this leaves two whole missed beats of margin. 58const IC_DEF_MAX_AGE_S: i64 = 900 59const IC_STATUS: *u8 = "knowledge/status/ioconfirm.status" 60const IC_STATUS_UP: *u8 = "../knowledge/status/ioconfirm.status" 61const IC_CH_MINUS: i64 = 45 62const IC_CH_0: i64 = 48 63const IC_CH_9: i64 = 57 64const IC_CH_BEAT: i64 = 98 65const IC_CH_READ: i64 = 114 66const IC_KEY_TS: *u8 = "ts=" 67const IC_KEY_CONF: *u8 = "blocked_confirmed=" 68 69func ic_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 70func ic_werr(s: *u8) -> i64 { sys_write(IC_STDERR, s, ic_slen(s)); return 0 } 71 72func ic_puts(b: *u8, off: i64, s: *u8) -> i64 { 73 var o: i64 = off 74 var j: i64 = 0 75 while s[j] != (0 as u8) { b[o] = s[j]; o = o + 1; j = j + 1 } 76 return o 77} 78 79func ic_puti(b: *u8, off: i64, v: i64) -> i64 { 80 var o: i64 = off 81 var x: i64 = v 82 if x < 0 { b[o] = IC_CH_MINUS as u8; o = o + 1; x = 0 - x } 83 var d: i64 = 1 84 var t: i64 = x 85 while t >= 10 { d = d * 10; t = t / 10 } 86 while d > 0 { 87 let q: i64 = x / d 88 b[o] = (IC_CH_0 + q) as u8 89 o = o + 1 90 x = x - q * d 91 d = d / 10 92 } 93 return o 94} 95 96func ic_atoi(s: *u8) -> i64 { 97 let n: i64 = ic_slen(s) 98 if n <= 0 { return IC_UNREADABLE } 99 var v: i64 = 0 100 var i: i64 = 0 101 var bad: i64 = 0 102 while i < n { 103 let c: i64 = s[i] as i64 104 if c < IC_CH_0 { bad = 1 } 105 if c > IC_CH_9 { bad = 1 } 106 if bad == 0 { v = v * 10 + (c - IC_CH_0) } 107 i = i + 1 108 } 109 if bad == 1 { return IC_UNREADABLE } 110 return v 111} 112 113func ic_now() -> i64 { 114 let tb: *i64 = sys_mmap(IC_BOX_BYTES) as *i64 115 tb[0] = 0 116 sys_clock_gettime_real(tb) 117 let t: i64 = tb[0] 118 sys_munmap(tb, IC_BOX_BYTES) 119 return t 120} 121 122// LINE-ANCHORED integer read: the value after `key` on the line that STARTS with key. Anchoring at the 123// line start is what stops a key matching inside another key's value or inside prose -- the estate has 124// lost a whole verdict to an unanchored match reading its own explanatory sentence as data. 125func ic_field(buf: *u8, n: i64, key: *u8) -> i64 { 126 let kl: i64 = ic_slen(key) 127 var p: i64 = 0 128 var res: i64 = IC_UNREADABLE 129 var atline: i64 = 1 130 while p < n { 131 if atline == 1 { 132 if p + kl <= n { 133 var m: i64 = 0 134 var hit: i64 = 1 135 while m < kl { 136 if buf[p + m] != key[m] { hit = 0 } 137 m = m + 1 138 } 139 if hit == 1 { 140 if res < 0 { 141 var q: i64 = p + kl 142 var v: i64 = 0 143 var got: i64 = 0 144 var stop: i64 = 0 145 while q < n { 146 let c: i64 = buf[q] as i64 147 if c < IC_CH_0 { stop = 1 } 148 if c > IC_CH_9 { stop = 1 } 149 if stop == 0 { v = v * 10 + (c - IC_CH_0); got = 1; q = q + 1 } else { q = n } 150 } 151 if got == 1 { res = v } 152 } 153 } 154 } 155 } 156 atline = 0 157 if buf[p] == (10 as u8) { atline = 1 } 158 p = p + 1 159 } 160 return res 161} 162 163func main(argc: i64, argv: *i64) -> i64 { 164 if argc < 2 { 165 ic_werr("usage: nx_ioconfirm beat [samples] [gap_ms] [outpath] | nx_ioconfirm read [path] [max_age_s]\n" as *u8) 166 sys_exit(IC_EXIT_USAGE) 167 return IC_EXIT_USAGE 168 } 169 let verb: *u8 = argv[1] as *u8 170 let ob: *u8 = sys_mmap(IC_OUTCAP) 171 var off: i64 = 0 172 173 if verb[0] == (IC_CH_BEAT as u8) { 174 var k: i64 = IC_DEF_SAMPLES 175 var gap: i64 = IC_DEF_GAP_MS 176 var path: *u8 = IC_STATUS 177 if argc > 2 { let a: *u8 = argv[2] as *u8; let v: i64 = ic_atoi(a); if v > 0 { k = v } } 178 if argc > 3 { let b: *u8 = argv[3] as *u8; let v2: i64 = ic_atoi(b); if v2 > 0 { gap = v2 } } 179 if argc > 4 { path = argv[4] as *u8 } 180 if k > IOA_MEDIAN_MAX_K { 181 ic_werr("nx_ioconfirm beat: samples exceeds IOA_MEDIAN_MAX_K, the bound the shared sampler enforces -- REFUSING\n" as *u8) 182 sys_exit(IC_EXIT_USAGE) 183 return IC_EXIT_USAGE 184 } 185 let mm: *i64 = sys_mmap(IC_MEAS_BYTES) as *i64 186 if ioa_measure_median(mm, k, gap) != 0 { 187 ic_werr("nx_ioconfirm beat: /proc/stat UNREADABLE across the whole window -- writing NOTHING, because a status file nobody could measure would be read as a level\n" as *u8) 188 sys_exit(IC_EXIT_UNMEASURED) 189 return IC_EXIT_UNMEASURED 190 } 191 let ncpu: i64 = mm[0] 192 let conf: i64 = mm[1] 193 let got: i64 = mm[2] 194 var bar: i64 = IC_UNREADABLE 195 if ncpu > 0 { bar = ncpu * IOA_BLOCKED_PER_CPU } 196 off = ic_puts(ob, off, "ts=" as *u8); off = ic_puti(ob, off, ic_now()) 197 off = ic_puts(ob, off, "\nncpu=" as *u8); off = ic_puti(ob, off, ncpu) 198 off = ic_puts(ob, off, "\nblocked_confirmed=" as *u8); off = ic_puti(ob, off, conf) 199 off = ic_puts(ob, off, "\nbar=" as *u8); off = ic_puti(ob, off, bar) 200 off = ic_puts(ob, off, "\nconfirm_samples=" as *u8); off = ic_puti(ob, off, got) 201 off = ic_puts(ob, off, "\nconfirm_requested=" as *u8); off = ic_puti(ob, off, k) 202 off = ic_puts(ob, off, "\nconfirm_gap_ms=" as *u8); off = ic_puti(ob, off, gap) 203 off = ic_puts(ob, off, "\nspan_ms=" as *u8); off = ic_puti(ob, off, (got - 1) * gap) 204 off = ic_puts(ob, off, "\nproducer=nx_ioconfirm\n" as *u8) 205 let fd: i64 = sys_openat_wr(path, IC_MODE_644) 206 if fd < 0 { 207 ic_werr("nx_ioconfirm beat: cannot open the status path for write -- REFUSING silently is not an option, so this is announced\n" as *u8) 208 sys_exit(IC_EXIT_UNMEASURED) 209 return IC_EXIT_UNMEASURED 210 } 211 let w: i64 = sys_write(fd, ob, off) 212 sys_close(fd) 213 // THE RECEIPT ANNOUNCES ITS OWN WRITE. A publisher that does not say how many bytes it wrote turns 214 // "did my write land?" into a hunt instead of a number. 215 var o2: i64 = 0 216 let rb: *u8 = sys_mmap(IC_OUTCAP) 217 o2 = ic_puts(rb, o2, "IOCONFIRM-BEAT wrote=" as *u8); o2 = ic_puti(rb, o2, w) 218 o2 = ic_puts(rb, o2, " of=" as *u8); o2 = ic_puti(rb, o2, off) 219 o2 = ic_puts(rb, o2, " blocked_confirmed=" as *u8); o2 = ic_puti(rb, o2, conf) 220 o2 = ic_puts(rb, o2, " bar=" as *u8); o2 = ic_puti(rb, o2, bar) 221 o2 = ic_puts(rb, o2, " samples=" as *u8); o2 = ic_puti(rb, o2, got) 222 o2 = ic_puts(rb, o2, " span_ms=" as *u8); o2 = ic_puti(rb, o2, (got - 1) * gap) 223 o2 = ic_puts(rb, o2, " path=" as *u8); o2 = ic_puts(rb, o2, path) 224 o2 = ic_puts(rb, o2, "\nverdict=MEASURED\n" as *u8) 225 sys_write(IC_STDOUT, rb, o2) 226 if w != off { return IC_EXIT_UNMEASURED } 227 return 0 228 } 229 230 if verb[0] != (IC_CH_READ as u8) { 231 ic_werr("usage: nx_ioconfirm beat [samples] [gap_ms] [outpath] | nx_ioconfirm read [path] [max_age_s]\n" as *u8) 232 sys_exit(IC_EXIT_USAGE) 233 return IC_EXIT_USAGE 234 } 235 236 var maxage: i64 = IC_DEF_MAX_AGE_S 237 var rpath: *u8 = IC_STATUS 238 var explicit: i64 = 0 239 if argc > 2 { rpath = argv[2] as *u8; explicit = 1 } 240 if argc > 3 { let c: *u8 = argv[3] as *u8; let v3: i64 = ic_atoi(c); if v3 > 0 { maxage = v3 } } 241 let box: *i64 = sys_mmap(IC_BOX_BYTES) as *i64 242 box[0] = 0 243 var src: *u8 = rpath 244 var buf: *u8 = sys_read_file(rpath, box) 245 // TWO ROOTS when the caller did not name one: a bare path is CWD-relative and this estate runs organs 246 // from both the serving root and buildroot/. An explicit path is honoured exactly as given. 247 if box[0] <= 0 { if explicit == 0 { box[0] = 0; src = IC_STATUS_UP; buf = sys_read_file(IC_STATUS_UP, box) } } 248 let n: i64 = box[0] 249 if n <= 0 { 250 off = ic_puts(ob, off, "IOCONFIRM-READ verdict=ABSENT path=" as *u8) 251 off = ic_puts(ob, off, rpath) 252 off = ic_puts(ob, off, " -- no confirmed level exists. A CONSUMER MUST FALL BACK TO ITS OWN SINGLE SAMPLE:\n absence is not a quiet box, it is an unmeasured one, and it must never read as headroom.\n" as *u8) 253 sys_write(IC_STDOUT, ob, off) 254 sys_exit(IC_EXIT_ABSENT) 255 return IC_EXIT_ABSENT 256 } 257 let ts: i64 = ic_field(buf, n, IC_KEY_TS) 258 let conf: i64 = ic_field(buf, n, IC_KEY_CONF) 259 let now: i64 = ic_now() 260 var age: i64 = IC_UNREADABLE 261 if ts > 0 { age = now - ts } 262 off = ic_puts(ob, off, "IOCONFIRM-READ path=" as *u8); off = ic_puts(ob, off, src) 263 off = ic_puts(ob, off, " blocked_confirmed=" as *u8); off = ic_puti(ob, off, conf) 264 off = ic_puts(ob, off, " ts=" as *u8); off = ic_puti(ob, off, ts) 265 off = ic_puts(ob, off, " age_s=" as *u8); off = ic_puti(ob, off, age) 266 off = ic_puts(ob, off, " max_age_s=" as *u8); off = ic_puti(ob, off, maxage) 267 if conf < 0 { 268 off = ic_puts(ob, off, " verdict=ABSENT -- the file exists and carries no readable level\n" as *u8) 269 sys_write(IC_STDOUT, ob, off) 270 sys_exit(IC_EXIT_ABSENT) 271 return IC_EXIT_ABSENT 272 } 273 // A NEGATIVE AGE IS NOT FRESH. A future stamp means clock skew or a forged write, and both are 274 // unobservable rather than healthy -- the flattering reading is the one that must be refused. 275 if age < 0 { 276 off = ic_puts(ob, off, " verdict=STALE reason=future-timestamp-clock-skew-or-forged\n" as *u8) 277 sys_write(IC_STDOUT, ob, off) 278 sys_exit(IC_EXIT_STALE) 279 return IC_EXIT_STALE 280 } 281 if age > maxage { 282 off = ic_puts(ob, off, " verdict=STALE -- older than the freshness bound. FALL BACK to a single sample.\n" as *u8) 283 sys_write(IC_STDOUT, ob, off) 284 sys_exit(IC_EXIT_STALE) 285 return IC_EXIT_STALE 286 } 287 off = ic_puts(ob, off, " verdict=FRESH\n" as *u8) 288 sys_write(IC_STDOUT, ob, off) 289 return 0 290}