nx_headroom.nx source
↩ module page · 211 lines · 9794 B
1// nx_headroom.nx -- S4 of the SRE program (seq1295, incident 2026-07-29): the SPAWN-TIME HEADROOM
2// GATE every background producer must consult before forking work. The outage proof: an 8-wide TLS
3// fork pool spooling to tmpfs on a memory-tight box (which had ALREADY refused a build on the
4// MemAvailable floor) co-produced a host-wide starvation + hard crash. /api/build has this gate
5// baked in; this organ EXTRACTS it as the shared, config-driven primitive so no producer derives
6// width from taste again (bounds-derived law).
7// nx_headroom width <cap> <child_cost_mb> [meminfo] [loadavg] [cpuinfo]
8// -> NX-HEADROOM ok width=<n> avail_mb= usable_mb= cores= load1_centi= (exit 0)
9// -> NX-HEADROOM REFUSED reason=mem_floor|load_ceiling ... (exit 5)
10// width = min(cap, cores/2, (MemAvailable-floor)/child_cost), floor 1 -- else REFUSED.
11// nx_headroom gate <need_mb> [meminfo] [loadavg] [cpuinfo]
12// -> ok (exit 0) iff need_mb fits above the floor AND load is under ceiling; else REFUSED exit 5.
13// Conf headroom.conf in CWD: floor_mb= loadceil_centi_per_core= (else derived defaults below).
14// Path override args exist so the GATE can prove exact math on fixture files -- real callers omit them.
15// Read-only; no hw writes (Rule 26).
16// license_tier: ORIGINAL expect_exit: 0
17import "nx_syscalls.nx"
18const H_MAGIC_1024: i64 = 1024
19const H_MAGIC_4096: i64 = 4096
20const H_MAGIC_4095: i64 = 4095
21
22const H_EXIT_USAGE: i64 = 2
23const H_EXIT_REFUSED: i64 = 5
24const H_READCAP: i64 = 131072
25const H_DEF_FLOOR_MB: i64 = 4096 // derived: control plane + page-cache reserve ~11% of the 36GB hub
26const H_DEF_LOADCEIL: i64 = 200 // 2.00 load per core: beyond that the box is already saturated
27
28func h_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
29func h_putn(v: i64) -> i64 {
30 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
31 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
32 let d: *u8 = sys_mmap(24); var k: i64 = 0
33 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
34 let o: *u8 = sys_mmap(24); var w: i64 = 0
35 while w < k { o[w] = d[k-1-w]; w = w + 1 }
36 sys_write(1, o, k)
37 sys_munmap(d, 24); sys_munmap(o, 24)
38 return 0
39}
40func h_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
41func h_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
42func h_atoi(s: *u8) -> i64 { var v: i64 = 0; var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } return v }
43func h_read(path: *u8, buf: *u8, cap: i64) -> i64 {
44 let fd: i64 = sys_openat_rd(path)
45 if fd < 0 { return 0 - 1 }
46 var tot: i64 = 0
47 var n: i64 = sys_read(fd, buf, cap)
48 while n > 0 { tot = tot + n; if tot >= cap { n = 0 } else { n = sys_read(fd, (buf as i64 + tot) as *u8, cap - tot) } }
49 sys_close(fd)
50 return tot
51}
52// first integer after <key>, skipping spaces/tabs between key and digits (meminfo shape). -1 if absent.
53func h_num_after(buf: *u8, n: i64, key: *u8) -> i64 {
54 let kn: i64 = h_slen(key)
55 var i: i64 = 0
56 while i + kn <= n {
57 var j: i64 = 0
58 var ok: i64 = 1
59 while j < kn { if buf[i+j] != key[j] { ok = 0; j = kn } else { j = j + 1 } }
60 if ok == 1 {
61 var p: i64 = i + kn
62 var sk: i64 = 1
63 while sk == 1 { sk = 0; if p < n { if buf[p] == (32 as u8) { p = p + 1; sk = 1 } else { if buf[p] == (9 as u8) { p = p + 1; sk = 1 } } } }
64 var v: i64 = 0
65 var any: i64 = 0
66 var go: i64 = 1
67 while go == 1 {
68 go = 0
69 if p < n {
70 let c: i64 = buf[p] as i64
71 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1; p = p + 1; go = 1 } }
72 }
73 }
74 if any == 1 { return v }
75 return 0 - 1
76 }
77 i = i + 1
78 }
79 return 0 - 1
80}
81// parse leading "D.DD" of loadavg as centi-load (12.44 -> 1244). -1 on empty.
82func h_load_centi(buf: *u8, n: i64) -> i64 {
83 var v: i64 = 0
84 var any: i64 = 0
85 var i: i64 = 0
86 var go: i64 = 1
87 while go == 1 {
88 go = 0
89 if i < n { let c: i64 = buf[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1; i = i + 1; go = 1 } } }
90 }
91 if any == 0 { return 0 - 1 }
92 v = v * 100
93 if i < n { if buf[i] == (46 as u8) {
94 i = i + 1
95 var f: i64 = 0
96 var fd: i64 = 0
97 var go2: i64 = 1
98 while go2 == 1 {
99 go2 = 0
100 if i < n { if fd < 2 { let c2: i64 = buf[i] as i64; if c2 >= 48 { if c2 <= 57 { f = f * 10 + (c2 - 48); fd = fd + 1; i = i + 1; go2 = 1 } } } }
101 }
102 if fd == 1 { f = f * 10 }
103 v = v + f
104 } }
105 return v
106}
107// count lines beginning with "processor" (cpuinfo core count); floor 1
108func h_cores(buf: *u8, n: i64) -> i64 {
109 var k: i64 = 0
110 var i: i64 = 0
111 var bol: i64 = 1
112 while i < n {
113 if bol == 1 {
114 if i + 9 <= n {
115 var j: i64 = 0
116 var ok: i64 = 1
117 let key: *u8 = "processor" as *u8
118 while j < 9 { if buf[i+j] != key[j] { ok = 0; j = 9 } else { j = j + 1 } }
119 if ok == 1 { k = k + 1 }
120 }
121 }
122 if buf[i] == (10 as u8) { bol = 1 } else { bol = 0 }
123 i = i + 1
124 }
125 if k < 1 { return 1 }
126 return k
127}
128func h_refuse(reason: *u8, avail: i64, usable: i64, cores: i64, load: i64) -> i64 {
129 h_puts("NX-HEADROOM REFUSED reason=" as *u8); h_puts(reason)
130 h_puts(" avail_mb=" as *u8); h_putn(avail)
131 h_puts(" usable_mb=" as *u8); h_putn(usable)
132 h_puts(" cores=" as *u8); h_putn(cores)
133 h_puts(" load1_centi=" as *u8); h_putn(load)
134 h_puts(" (spawn NOTHING; shed or wait -- the floor exists because 2026-07-29 did)\n" as *u8)
135 return 0
136}
137func main(argc: i64, argv: *i64) -> i64 {
138 if argc < 3 { h_puts("usage: nx_headroom width <cap> <child_cost_mb> [meminfo] [loadavg] [cpuinfo] | gate <need_mb> [meminfo] [loadavg] [cpuinfo]\n" as *u8); return H_EXIT_USAGE }
139 let verb: *u8 = argv[1] as *u8
140 var mode: i64 = 0 - 1
141 var pbase: i64 = 0
142 if h_streq(verb, "width" as *u8) == 1 { mode = 0; pbase = 4 }
143 if h_streq(verb, "gate" as *u8) == 1 { mode = 1; pbase = 3 }
144 if mode < 0 { h_puts("usage: nx_headroom width <cap> <child_cost_mb> [...] | gate <need_mb> [...]\n" as *u8); return H_EXIT_USAGE }
145 if mode == 0 { if argc < 4 { h_puts("width needs <cap> <child_cost_mb>\n" as *u8); return H_EXIT_USAGE } }
146 var pm: *u8 = "/proc/meminfo" as *u8
147 var pl: *u8 = "/proc/loadavg" as *u8
148 var pc: *u8 = "/proc/cpuinfo" as *u8
149 if argc > pbase { pm = argv[pbase] as *u8 }
150 if argc > pbase + 1 { pl = argv[pbase+1] as *u8 }
151 if argc > pbase + 2 { pc = argv[pbase+2] as *u8 }
152 // conf-or-derived-default bounds
153 var floor_mb: i64 = H_DEF_FLOOR_MB
154 var loadceil: i64 = H_DEF_LOADCEIL
155 let cbuf: *u8 = sys_mmap(256)
156 let cn: i64 = h_read("headroom.conf" as *u8, cbuf, 255)
157 if cn > 0 {
158 let v1: i64 = h_num_after(cbuf, cn, "floor_mb=" as *u8)
159 if v1 > 0 { floor_mb = v1 }
160 let v2: i64 = h_num_after(cbuf, cn, "loadceil_centi_per_core=" as *u8)
161 if v2 > 0 { loadceil = v2 }
162 }
163 sys_munmap(cbuf, 256)
164 // measure
165 let mb: *u8 = sys_mmap(H_READCAP)
166 let mn: i64 = h_read(pm, mb, H_READCAP - 1)
167 if mn <= 0 { h_puts("NX-HEADROOM ERROR: cannot read meminfo\n" as *u8); return 1 }
168 let kb: i64 = h_num_after(mb, mn, "MemAvailable:" as *u8)
169 if kb < 0 { h_puts("NX-HEADROOM ERROR: no MemAvailable in meminfo\n" as *u8); return 1 }
170 let avail_mb: i64 = kb / H_MAGIC_1024
171 let lb: *u8 = sys_mmap(H_MAGIC_4096)
172 let ln: i64 = h_read(pl, lb, H_MAGIC_4095)
173 var load1: i64 = 0
174 if ln > 0 { let lv: i64 = h_load_centi(lb, ln); if lv >= 0 { load1 = lv } }
175 let cb: *u8 = sys_mmap(H_READCAP)
176 let cnn: i64 = h_read(pc, cb, H_READCAP - 1)
177 var cores: i64 = 1
178 if cnn > 0 { cores = h_cores(cb, cnn) }
179 let usable: i64 = avail_mb - floor_mb
180 // load ceiling first: a saturated box refuses regardless of free memory
181 if load1 > loadceil * cores { h_refuse("load_ceiling" as *u8, avail_mb, usable, cores, load1); return H_EXIT_REFUSED }
182 if mode == 1 {
183 let need: i64 = h_atoi(argv[2] as *u8)
184 if usable < need { h_refuse("mem_floor" as *u8, avail_mb, usable, cores, load1); return H_EXIT_REFUSED }
185 h_puts("NX-HEADROOM ok need_mb=" as *u8); h_putn(need)
186 h_puts(" avail_mb=" as *u8); h_putn(avail_mb)
187 h_puts(" usable_mb=" as *u8); h_putn(usable)
188 h_puts(" cores=" as *u8); h_putn(cores)
189 h_puts(" load1_centi=" as *u8); h_putn(load1)
190 h_puts("\n" as *u8)
191 return 0
192 }
193 let cap: i64 = h_atoi(argv[2] as *u8)
194 let cost: i64 = h_atoi(argv[3] as *u8)
195 if cap < 1 { h_puts("width needs cap >= 1\n" as *u8); return H_EXIT_USAGE }
196 if cost < 1 { h_puts("width needs child_cost_mb >= 1\n" as *u8); return H_EXIT_USAGE }
197 if usable < cost { h_refuse("mem_floor" as *u8, avail_mb, usable, cores, load1); return H_EXIT_REFUSED }
198 var w: i64 = usable / cost
199 var wb: i64 = cores / 2
200 if wb < 1 { wb = 1 }
201 if w > wb { w = wb }
202 if w > cap { w = cap }
203 if w < 1 { w = 1 }
204 h_puts("NX-HEADROOM ok width=" as *u8); h_putn(w)
205 h_puts(" avail_mb=" as *u8); h_putn(avail_mb)
206 h_puts(" usable_mb=" as *u8); h_putn(usable)
207 h_puts(" cores=" as *u8); h_putn(cores)
208 h_puts(" load1_centi=" as *u8); h_putn(load1)
209 h_puts("\n" as *u8)
210 return 0
211}