code wiki / _hdl_build / nx_clock_dispatch_gate.nx
nx_clock_dispatch_gate.nx source
↩ module page · 50 lines · 3791 B
1// nx_clock_dispatch_gate.nx -- proves the clock is FUNCTIONAL: its ONE dispatcher actually RUNS a registered job's
2// organ (fork+exec) at the job's interval. Job A (interval 1, the marker organ) must run on every tick; job B
3// (interval 3) must run only when due. Over ticks 1..4: A runs 4x, B runs 1x -- proven by the marker file length
4// and the dispatch counts. This is the divider property realized as REAL execution, from ONE loop, no per-job
5// daemon. Pre-req: _build/nx_clock_marker.sov.elf must be built (run `nx_sov_build_run nx_clock_marker
6// --build-only` first; cwd = buildroot). ⚠THE FIXTURE MUST NOT LIVE IN /tmp: this NAS mounts /tmp
7// noexec (measured 2026-08-03: tmpfs rw,nosuid,nodev,noexec), so the old /tmp path made every
8// dispatch exec fail 127 and the gate was RED ON THIS HOST FROM BIRTH -- an environmentally-dead
9// gate that never once measured what it claims. license_tier: ORIGINAL expect_exit: 0
10import "nx_clock_sched.nx"
11import "nx_syscalls.nx"
12
13func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
14func wn(v: i64) -> i64 { var m: i64=v; if m<0{w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
15func dun(p: *u8) -> i64 { __syscall(87, p as i64, 0, 0, 0, 0, 0); return 0 }
16func readnum(p: *u8) -> i64 { let lp: *i64 = sys_mmap(8) as *i64; let d: *u8 = sys_read_file(p, lp); if (d as i64)==0 { return 0 } var c: i64=0; var i: i64=0; while i<lp[0] { if d[i]>=(48 as u8) { if d[i]<=(57 as u8) { c=c*10+(d[i]-(48 as u8)) as i64 } } i=i+1 } return c }
17func setslot(buf: *u8, i: i64, s: *u8) -> i64 { let d: *u8 = clk_slot(buf, i); var c: i64=0; while s[c]!=(0 as u8){ if c<CLK_NAMEW-1 { d[c]=s[c] } c=c+1 } d[c]=0 as u8; return 0 }
18
19func main(argc: i64, argv: *i64) -> i64 {
20 w("=== nx_clock_dispatch_gate -- ONE dispatcher actually RUNS due jobs (fork+exec) ===\n" as *u8)
21 let organs: *u8 = sys_mmap(CLK_MAXJOBS*CLK_NAMEW)
22 let iv: *i64 = sys_mmap(CLK_MAXJOBS*8) as *i64
23 let nd: *i64 = sys_mmap(CLK_MAXJOBS*8) as *i64
24 let fired: *i64 = sys_mmap(CLK_MAXJOBS*8) as *i64
25
26 // Job A: the marker organ, interval 1 (runs every tick). Job B: same organ, interval 3 (runs only when due).
27 setslot(organs, 0, "_build/nx_clock_marker.sov.elf" as *u8); iv[0]=1; nd[0]=1
28 setslot(organs, 1, "_build/nx_clock_marker.sov.elf" as *u8); iv[1]=3; nd[1]=3
29 let n: i64 = 2
30 dun("/tmp/clk_mark.txt" as *u8)
31
32 var total: i64 = 0
33 var now: i64 = 1
34 while now <= 4 {
35 let c: i64 = clk_dispatch_run(organs, iv, nd, n, now, fired)
36 total = total + c
37 now = now + 1
38 }
39 let runs: i64 = readnum("/tmp/clk_mark.txt" as *u8)
40 w(" dispatched (A int1 + B int3) over ticks 1..4: total dispatch="); wn(total); w(", organ actually ran="); wn(runs); w(" times\n" as *u8)
41
42 var pass: i64=0; var tot: i64=0
43 // A (int1) ran 4x + B (int3) ran 1x (tick 3) = 5 real organ executions from ONE dispatcher loop
44 tot=tot+1; if runs==5 { pass=pass+1; w(" PASS the clock RAN the registered organ exactly 5x (A:4 + B:1) = divider as REAL execution\n" as *u8) } else { w(" FAIL organ ran "); wn(runs); w(" times (expected 5)\n" as *u8) }
45 tot=tot+1; if total==5 { pass=pass+1; w(" PASS dispatch count matches (5), one loop drove both jobs\n" as *u8) } else { w(" FAIL dispatch count "); wn(total); w("\n" as *u8) }
46
47 w("nx_clock_dispatch_gate pass="); wn(pass); w("/"); wn(tot)
48 if pass==tot { w(" verdict=GREEN (the ONE clock executes real organs at their intervals -- no per-job daemon)\n" as *u8); sys_exit(0); return 0 }
49 w(" verdict=RED\n" as *u8); sys_exit(1); return 1
50}