code wiki / _hdl_build / nx_osbench_kern.nx

nx_osbench_kern.nx source

↩ module page · 205 lines · 10246 B

1// nx_osbench_kern.nx -- rung F853b (lane osbench): the KERNEL-AXIS harness. 2// 3// WHY THIS EXISTS: the operator mission is RAW KERNEL PERFORMANCE, and 750 of 1000 permille of that 4// mission (syscall_trap, ipc, thread_spawn, context_switch) was UNMEASURED -- we did not even know 5// what LINUX costs on this hardware, so we had no target to aim at. This organ measures the LINUX 6// side of the kernel axes so the number NishiOS must beat is on record. 7// 8// ★ HONEST SCOPE, STATED UP FRONT: these are REFERENCE rows, not comparisons. NishiOS does not run 9// as an OS on this substrate -- it is hosted, so it has no syscall-trap or scheduler of its own 10// here. There is therefore NO NishiOS counterpart to pair against, and the judge scores NOTHING 11// from this file. Emitting a one-sided number as if it were a head-to-head would be exactly the 12// no-wave violation this lane exists to prevent. The NishiOS halves stay UNMEASURED, with the 13// rung that unblocks them named (F856 bare-metal node). 14// 15// ★ A STRUCTURAL NOTE THAT MUST NOT BE SCORED AS A WIN: NishiOS's native contract has no syscall 16// trap on the store path at all (capability call, not a ring transition). That is a FLOOR/design 17// difference, and the gap ledger's rule applies -- "we own it" is never printed as "we beat it". 18// It is recorded as prose here, never as a ratio. 19// 20// AXES (Linux, this host): 21// syscall_trap -- minimal round trip into the kernel and back (close on an invalid fd: 22// a real trap, EBADF immediately, near-zero kernel work = trap floor) 23// pipe_write_read -- a byte through a real pipe buffer, same process. NAMED HONESTLY: this is 24// the pipe-buffer cost, NOT an inter-process IPC round trip and NOT a context 25// switch. Calling it ipc_roundtrip would be a lie by label. 26// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 27import "nx_syscalls.nx" 28import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 29 30const OK_N: i64 = 2000 31const OK_ROUNDS: i64 = 15 32const OK_WARM: i64 = 200 33const OK_MODE: i64 = 420 34const OK_NSEC: i64 = 1000000000 35const OK_BADFD: i64 = 0 - 1 36const OK_UNSTABLE: i64 = 100 37 38func ok_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 39func ok_w(fd: i64, s: *u8) -> i64 { let n: i64 = ok_len(s); sys_write(fd, s, n); return 0 } 40func ok_p(s: *u8) -> i64 { return ok_w(1, s) } 41// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 42// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 43// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 44// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 45func ok_wn(fd: i64, v: i64) -> i64 { nxi_fd(fd, v); return 0 } 46func ok_pn(v: i64) -> i64 { return ok_wn(1, v) } 47 48func ok_ns(ts: *i64) -> i64 { 49 sys_clock_gettime_mono(ts) 50 let s: i64 = ts[0] 51 let n: i64 = ts[1] 52 return s * OK_NSEC + n 53} 54 55// sort a copy, return rank r. FLAG LOOP -- a pseudo-break assigning the loop var destroys the 56// insertion index and silently shuffles instead of sorting (that defect produced a NEGATIVE IQR 57// in the sibling harness and passed a naive gate as a false GREEN). 58func ok_rank(arr: *i64, n: i64, r: i64) -> i64 { 59 let c: *i64 = sys_mmap(n * 8 + 8) as *i64 60 var i: i64 = 0 61 while i < n { c[i] = arr[i]; i = i + 1 } 62 var a: i64 = 1 63 while a < n { 64 let key: i64 = c[a] 65 var b: i64 = a - 1 66 var placed: i64 = 0 67 while placed == 0 { 68 if b < 0 { placed = 1 } else { 69 let cb: i64 = c[b] 70 if cb > key { c[b+1] = cb; b = b - 1 } else { placed = 1 } 71 } 72 } 73 c[b+1] = key 74 a = a + 1 75 } 76 return c[r] 77} 78func ok_med(arr: *i64, n: i64) -> i64 { return ok_rank(arr, n, n/2) } 79func ok_iqr(arr: *i64, n: i64) -> i64 { 80 let m: i64 = ok_med(arr, n) 81 if m <= 0 { return 0 } 82 let q1: i64 = ok_rank(arr, n, n/4) 83 let q3: i64 = ok_rank(arr, n, (n*3)/4) 84 return ((q3 - q1) * 1000) / m 85} 86func ok_rng(arr: *i64, n: i64) -> i64 { 87 var lo: i64 = arr[0] 88 var hi: i64 = arr[0] 89 var i: i64 = 0 90 while i < n { 91 let v: i64 = arr[i] 92 if v < lo { lo = v } 93 if v > hi { hi = v } 94 i = i + 1 95 } 96 let m: i64 = ok_med(arr, n) 97 if m <= 0 { return 0 } 98 return ((hi - lo) * 1000) / m 99} 100 101// axis 0 = syscall trap floor, axis 1 = pipe write+read. Returns ns/op for one round. 102func ok_round(axis: i64, rfd: i64, wfd: i64) -> i64 { 103 let ts: *i64 = sys_mmap(32) as *i64 104 let b: *u8 = sys_mmap(16) 105 b[0] = 65 as u8 106 var w: i64 = 0 107 while w < OK_WARM { 108 if axis == 0 { sys_close(OK_BADFD) } 109 if axis == 1 { sys_write(wfd, b, 1); sys_read(rfd, b, 1) } 110 w = w + 1 111 } 112 let t0: i64 = ok_ns(ts) 113 var i: i64 = 0 114 while i < OK_N { 115 if axis == 0 { sys_close(OK_BADFD) } 116 if axis == 1 { sys_write(wfd, b, 1); sys_read(rfd, b, 1) } 117 i = i + 1 118 } 119 let t1: i64 = ok_ns(ts) 120 let d: i64 = t1 - t0 121 if d < 0 { return 0 } 122 return d / OK_N 123} 124 125func ok_axname(axis: i64) -> *u8 { 126 if axis == 0 { return "syscall_trap" as *u8 } 127 return "pipe_write_read" as *u8 128} 129 130func main() -> i64 { 131 ok_p("nx_osbench_kern -- LINUX kernel-axis REFERENCE numbers (the target NishiOS must beat)\n" as *u8) 132 ok_p(" These are ONE-SIDED reference rows. NishiOS is HOSTED on this substrate: it has no syscall\n" as *u8) 133 ok_p(" trap and no scheduler of its own here, so there is NO counterpart to pair against and the\n" as *u8) 134 ok_p(" judge scores NOTHING from this file. A one-sided number presented as a head-to-head would\n" as *u8) 135 ok_p(" be the exact no-wave violation this lane exists to prevent.\n\n" as *u8) 136 137 // a real pipe for axis 1. 138 // ⚠WIDTH TRAP (cost a hang): sys_pipe2 is declared `(fds: *i64, flags)` but the KERNEL writes 139 // `int pipefd[2]` = TWO 32-BIT ints into that buffer. Reading it as *i64 packs BOTH fds into 140 // slot 0 and leaves slot 1 as GARBAGE -- sys_read on that garbage fd blocks forever (the run 141 // hung after emitting the syscall_trap row). The pointer TYPE on the wrapper invites this bug. 142 // Read the buffer as *i32: [0]=read end, [1]=write end. 143 let pmem: *u8 = sys_mmap(32) 144 let prc: i64 = sys_pipe2(pmem as *i64, 0) 145 let pf32: *i32 = pmem as *i32 146 var rfd: i64 = 0 - 1 147 var wfd: i64 = 0 - 1 148 if prc == 0 { rfd = pf32[0] as i64; wfd = pf32[1] as i64 } 149 if prc != 0 { ok_p(" WARN pipe2 failed -- pipe_write_read will be SKIPPED, not faked\n" as *u8) } 150 ok_p(" pipe fds: r="); ok_pn(rfd); ok_p(" w="); ok_pn(wfd); ok_p("\n" as *u8) 151 152 let fd: i64 = sys_openat_append("knowledge/status/osbench_measured.dat" as *u8, OK_MODE) 153 if fd < 0 { ok_p("KERN-FAIL cannot open dat\n" as *u8); sys_exit(1); return 1 } 154 ok_w(fd, "# osbench_kern run (LINUX reference only; no NishiOS counterpart on this substrate)\n" as *u8) 155 156 ok_p(" AXIS ns/op(med) IQR range stability\n" as *u8) 157 let samp: *i64 = sys_mmap(OK_ROUNDS * 8 + 8) as *i64 158 var axis: i64 = 0 159 while axis < 2 { 160 var skip: i64 = 0 161 if axis == 1 { if prc != 0 { skip = 1 } } 162 if axis == 1 { if rfd < 0 { skip = 1 } } 163 if axis == 1 { if wfd < 0 { skip = 1 } } 164 if skip == 0 { 165 var r: i64 = 0 166 while r < OK_ROUNDS { samp[r] = ok_round(axis, rfd, wfd); r = r + 1 } 167 let med: i64 = ok_med(samp, OK_ROUNDS) 168 let iqr: i64 = ok_iqr(samp, OK_ROUNDS) 169 let rng: i64 = ok_rng(samp, OK_ROUNDS) 170 ok_p(" "); ok_p(ok_axname(axis)) 171 ok_p(" "); ok_pn(med) 172 ok_p(" "); ok_pn(iqr) 173 ok_p(" "); ok_pn(rng) 174 if iqr > OK_UNSTABLE { ok_p(" UNSTABLE\n" as *u8) } else { ok_p(" stable\n" as *u8) } 175 ok_w(fd, "REFERENCE\t" as *u8); ok_w(fd, ok_axname(axis)) 176 ok_w(fd, "\tlinux-host\tnative\t" as *u8); ok_wn(fd, med) 177 ok_w(fd, "\t" as *u8); ok_wn(fd, iqr) 178 ok_w(fd, "\tone-sided linux reference; no NishiOS counterpart on a hosted substrate\n" as *u8) 179 } 180 axis = axis + 1 181 } 182 183 // The NishiOS halves stay explicitly UNMEASURED with the unblocking rung named. 184 ok_w(fd, "UNMEASURED\tsyscall_trap\tnishios\t-1\t-1\tNishiOS is hosted here; native contract has NO trap on the store path (FLOOR/design, never scored) - real number needs F856\n" as *u8) 185 ok_w(fd, "UNMEASURED\tipc_roundtrip\tnishios\t-1\t-1\tneeds NishiOS running AS an OS - F856\n" as *u8) 186 ok_w(fd, "UNMEASURED\tthread_spawn\tnishios\t-1\t-1\tneeds NishiOS running AS an OS - F856\n" as *u8) 187 ok_w(fd, "UNMEASURED\tcontext_switch\tnishios\t-1\t-1\tneeds NishiOS running AS an OS - F856\n" as *u8) 188 sys_close(fd) 189 190 ok_p("\n DECLARED ENVELOPE: N="); ok_pn(OK_N) 191 ok_p(" ops/round, rounds="); ok_pn(OK_ROUNDS) 192 ok_p(", single-threaded, single-node, warm.\n" as *u8) 193 ok_p(" syscall_trap = close(-1): a REAL trap returning EBADF with near-zero kernel work = the trap FLOOR.\n" as *u8) 194 ok_p(" pipe_write_read = one byte through a real pipe buffer, SAME process. Named honestly: this is\n" as *u8) 195 ok_p(" the pipe-buffer cost, NOT an inter-process IPC round trip and NOT a context switch. Labelling\n" as *u8) 196 ok_p(" it ipc_roundtrip would be a lie by label -- those axes remain UNMEASURED, gated on F856.\n" as *u8) 197 ok_p("\n STRUCTURAL (recorded as prose, NEVER as a ratio): the NishiOS native contract performs store\n" as *u8) 198 ok_p(" access via a capability call with NO ring transition, so the trap cost above has no NishiOS\n" as *u8) 199 ok_p(" analogue at all. Per the gap-ledger rule, 'we own it' is never printed as 'we beat it'.\n" as *u8) 200 201 let lg: i64 = sys_openat_append("knowledge/status/osbench_kern.log" as *u8, OK_MODE) 202 if lg >= 0 { ok_w(lg, "NX-OSBENCH-KERN verdict=GREEN linux reference axes emitted; nishios halves UNMEASURED (F856)\n" as *u8); sys_close(lg) } 203 ok_p("\nNX-OSBENCH-KERN verdict=GREEN (linux reference emitted; nothing scored, nothing claimed)\n" as *u8) 204 return 0 205}