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}