code wiki / _hdl_build / nx_clock_edf_gate.nx
nx_clock_edf_gate.nx source
↩ module page · 181 lines · 11017 B
1// nx_clock_edf_gate.nx -- GATE for the wall-clock/EDF scheduler (debt 1785872141, operator 2026-08-04
2// "get the clock to sota"). Proves the SOTA properties on the PURE decision functions, so a 6-HOUR
3// period is verified in MILLISECONDS with fabricated clock values instead of by waiting 6 hours.
4//
5// T1 EDF ORDER: the most-overdue job is picked FIRST (earliest deadline), not registry order.
6// T2 NOT-DUE: nothing overdue -> pick returns -1 (a scheduler must not invent work).
7// T3 CATCH-UP WITHOUT RUNAWAY: re-arming a job 5 periods late lands STRICTLY past now, exactly once.
8// T4 MISSED PERIODS ARE COUNTED, NOT HIDDEN: a job 3 periods late reports 3.
9// T5 THE REGRESSION ITSELF (the whole reason this exists): simulate a window where dispatching costs
10// real time. Under the OLD model (logical tick advanced by SLEEP ONLY) a 21600s job is still not
11// due after a full real day. Under the NEW model (wall-clock deadlines) it fires on time.
12// This is a NEGATIVE CONTROL: the old algorithm MUST fail the same assertion the new one passes,
13// or the tooth proves nothing.
14// T6 MIGRATION IS EXACT: legacy logical-tick deadlines convert; genuine epochs are left ALONE.
15// T7 STARVATION IS BOUNDED: with EDF + re-arm, every job in a saturated set fires within its own
16// period once the backlog drains -- no job is passed over forever.
17// expect_exit: 0 license_tier: ORIGINAL Read-only. No hw writes (Rule 26).
18import "nx_clock_sched.nx"
19import "nx_syscalls.nx"
20import "nx_gate_verdict.nx" // 2026-08-06: this gate emitted NO verdict= anchor, so nx_gate_green read a
21// PASSING run as NOT-GREEN and /api/build REFUSED it outright (detector nx_gatedry, seq585). The gate that
22// proves the EDF scheduler -- including T7, the starvation tooth -- was therefore STRUCTURALLY UNJUDGEABLE
23// and could never appear in the rollup. ★A GATE THAT CANNOT BE JUDGED IS NOT A WEAK GATE, IT IS NO GATE.
24
25const G_N: i64 = 8
26
27func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
28func gn(v: i64) -> i64 {
29 var m: i64=v; if m<0{gw("-" as *u8);m=0-m}
30 let t:*u8=sys_mmap(24); var k:i64=0
31 if m==0{t[0]=48 as u8;k=1}
32 while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}
33 let o:*u8=sys_mmap(24); var i:i64=0
34 while i<k{o[i]=t[k-1-i];i=i+1}
35 sys_write(1,o,k); return 0
36}
37func row(name: *u8, ok: i64, pass: *i64, total: *i64) -> i64 {
38 total[0] = total[0] + 1
39 if ok==1 { pass[0]=pass[0]+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
40 gw(name); gw("\n" as *u8)
41 return ok
42}
43
44func main() -> i64 {
45 gw("=== nx_clock_edf_gate: wall-clock EDF scheduling (kills the logical-tick drift) ===\n" as *u8)
46 let pass: *i64 = sys_mmap(16) as *i64; let total: *i64 = sys_mmap(16) as *i64
47 pass[0]=0; total[0]=0
48 let dl: *i64 = sys_mmap(G_N*8) as *i64
49 let iv: *i64 = sys_mmap(G_N*8) as *i64
50 let NOW: i64 = 1785900000
51
52 // ---- T1 EDF order: three overdue, the EARLIEST deadline must win (index 2, not 0) ----
53 iv[0]=60; dl[0]=NOW-10
54 iv[1]=120; dl[1]=NOW-5
55 iv[2]=21600; dl[2]=NOW-9000 // most overdue in absolute terms = earliest deadline
56 iv[3]=60; dl[3]=NOW+300 // not due
57 let k1: i64 = clk_edf_pick(dl, 4, NOW)
58 gw(" picked index="); gn(k1); gw(" (expect 2 = the 6h job, most overdue)\n" as *u8)
59 var t1: i64 = 0; if k1 == 2 { t1 = 1 }
60 row("T1 EDF: the most-overdue job is dispatched FIRST, not registry order" as *u8, t1, pass, total)
61
62 // ---- T2 nothing due -> -1 ----
63 dl[0]=NOW+1; dl[1]=NOW+2; dl[2]=NOW+3; dl[3]=NOW+4
64 let k2: i64 = clk_edf_pick(dl, 4, NOW)
65 var t2: i64 = 0; if k2 == (0-1) { t2 = 1 }
66 row("T2 nothing overdue -> pick=-1 (never invents work)" as *u8, t2, pass, total)
67
68 // ---- T3 catch-up: 5 periods late, one re-arm lands strictly past now ----
69 iv[0]=60; dl[0]=NOW-300
70 let skipped: i64 = clk_edf_rearm(dl, iv, 0, NOW)
71 gw(" after rearm deadline-now="); gn(dl[0]-NOW); gw(" skipped="); gn(skipped); gw("\n" as *u8)
72 var t3: i64 = 0
73 if dl[0] > NOW { if dl[0] <= NOW+60 { t3 = 1 } }
74 row("T3 catch-up re-arm lands strictly past now, within one interval (no runaway, no drift)" as *u8, t3, pass, total)
75
76 // ---- T4 missed periods reported honestly ----
77 iv[0]=100; dl[0]=NOW-300
78 let miss: i64 = clk_edf_missed(dl, iv, 0, NOW)
79 gw(" missed="); gn(miss); gw(" (expect 3)\n" as *u8)
80 var t4: i64 = 0; if miss == 3 { t4 = 1 }
81 row("T4 missed periods are COUNTED (3 late = 3), never silently swallowed" as *u8, t4, pass, total)
82
83 // ---- T5 THE REGRESSION + NEGATIVE CONTROL ----
84 // A day of real time. Each beat sleeps until the fastest job (60s) then dispatches; every beat
85 // burns EXEC_COST seconds of real time inside children. OLD model: logical T += sleep only.
86 // NEW model: deadline compared against the real clock.
87 let DAY: i64 = 86400
88 let SLEEP: i64 = 60
89 let EXEC: i64 = 30 // measured-plausible: 132 dispatches/window of real organs
90 var real_t: i64 = 0
91 var logical_T: i64 = 0
92 while real_t < DAY {
93 logical_T = logical_T + SLEEP // OLD: advances by what it SLEPT
94 real_t = real_t + SLEEP + EXEC // REAL: sleep PLUS what the children took
95 }
96 gw(" after 1 real day: logical_tick="); gn(logical_T)
97 gw(" real_secs="); gn(real_t); gw("\n" as *u8)
98 // the 6h job under the OLD model: due when logical_T >= 21600
99 var old_fired: i64 = 0; if logical_T >= 21600 { old_fired = 1 }
100 // ...but the question is whether it fired ON TIME (4x in a day). Count old fires:
101 let old_fires: i64 = logical_T / 21600
102 let new_fires: i64 = real_t / 21600
103 gw(" 6h-job fires in that day -- OLD(logical)="); gn(old_fires)
104 gw(" NEW(wall-clock)="); gn(new_fires); gw(" (expect 4 for a correct 6h period)\n" as *u8)
105 var t5: i64 = 0
106 if new_fires == 4 { if old_fires < 4 { t5 = 1 } } // NEW correct AND OLD provably wrong
107 row("T5 REGRESSION+NEGCTL: wall-clock fires a 6h job 4x/day; the OLD logical tick provably does NOT" as *u8, t5, pass, total)
108 if old_fires < 4 { gw(" (negative control BIT: the old model lost " as *u8); gn(4-old_fires); gw(" of 4 fires = the measured 21h defect)\n" as *u8) }
109
110 // ---- T6 migration exact: ticks convert, epochs untouched ----
111 iv[0]=21600; dl[0]=2970420 // a legacy LOGICAL TICK (the live value seen 2026-08-04)
112 iv[1]=60; dl[1]=NOW+30 // a genuine epoch, must NOT be touched
113 let conv: i64 = clk_edf_migrate(dl, iv, 2, NOW)
114 gw(" converted="); gn(conv); gw(" row0="); gn(dl[0]-NOW); gw(" row1_untouched="); gn(dl[1]-NOW); gw("\n" as *u8)
115 var t6: i64 = 0
116 if conv == 1 { if dl[0] == NOW+21600 { if dl[1] == NOW+30 { t6 = 1 } } }
117 row("T6 migration converts legacy ticks EXACTLY and leaves real epochs alone" as *u8, t6, pass, total)
118
119 // ---- T7 no permanent starvation: saturated set, every job eventually picked ----
120 var i: i64 = 0
121 while i < G_N { iv[i]=60; dl[i]=NOW-1000+i*7; i=i+1 } // all overdue, distinct deadlines
122 let seen: *i64 = sys_mmap(G_N*8) as *i64
123 i=0; while i<G_N { seen[i]=0; i=i+1 }
124 var step: i64 = 0
125 var cur: i64 = NOW
126 while step < G_N*2 {
127 let k: i64 = clk_edf_pick(dl, G_N, cur)
128 if k >= 0 { seen[k]=1; clk_edf_rearm(dl, iv, k, cur) }
129 step = step + 1
130 }
131 var allseen: i64 = 1
132 i=0; while i<G_N { if seen[i]==0 { allseen=0 } i=i+1 }
133 row("T7 no permanent starvation: every job in a saturated set gets dispatched" as *u8, allseen, pass, total)
134
135 // ---- T8 DEMAND vs CAPACITY: the number that explains a starving beat whose row and elf are both fine ----
136 // T7 proves EDF starves nobody PERMANENTLY *once the backlog drains*. On the live plane the backlog NEVER
137 // drained -- 45 jobs demanded ~273 dispatches per 1800s window while the window completed 51 -- so T7 held
138 // while every beat ran late, and netobs read as dead for days.
139 // ★A GATE THAT PROVES A PROPERTY "ONCE THE BACKLOG DRAINS" PROVES NOTHING ABOUT A SYSTEM WHOSE BACKLOG
140 // NEVER DRAINS -- so assert the drain PRECONDITION itself, not only the ordering.
141 iv[0]=30; iv[1]=30; iv[2]=60; iv[3]=60 // 60+60+30+30 = 180 dispatches required per 1800s window
142 let dem: i64 = clk_demand_per_window(iv, 4, 1800)
143 gw(" demand=" as *u8); gn(dem); gw(" (expect 180)\n" as *u8)
144 var t8: i64 = 0; if dem == 180 { t8 = 1 }
145 row("T8 demand/window is derived from the real periods (30,30,60,60 @1800s = 180)" as *u8, t8, pass, total)
146
147 // ---- T9 the demand figure is a CONSERVATIVE FLOOR, so 'demand > capacity' is proof, not suspicion ----
148 iv[0]=86400; iv[1]=21600; iv[2]=1800; iv[3]=0 // two sub-window periods, one exact, one ZERO interval
149 let dem2: i64 = clk_demand_per_window(iv, 4, 1800)
150 gw(" demand(long+zero)=" as *u8); gn(dem2); gw(" (expect 1)\n" as *u8)
151 var t9: i64 = 0; if dem2 == 1 { t9 = 1 }
152 row("T9 demand FLOORS (periods longer than the window -> 0) and a ZERO interval never divides" as *u8, t9, pass, total)
153
154 // ---- T10/T11 THE PARALLEL-DISPATCH CORRECTNESS CONDITION ----------------------------------
155 // Proven on the PURE picker BEFORE it is wired to a live dispatcher. Under bounded parallelism a
156 // running job is still overdue (it is re-armed only after reaping), so a picker without a busy mask
157 // dispatches a SECOND copy of the organ already saturating the box. These two teeth are the whole
158 // reason clk_edf_pick_free exists as a separate function instead of a flag on the incumbent.
159 let busy: *i64 = sys_mmap(G_N*8) as *i64
160 iv[0]=60; dl[0]=NOW-10
161 iv[1]=120; dl[1]=NOW-5
162 iv[2]=21600; dl[2]=NOW-9000 // MOST overdue -- and about to be marked in-flight
163 iv[3]=60; dl[3]=NOW+300 // not due at all
164 busy[0]=0; busy[1]=0; busy[2]=1; busy[3]=0
165 let k10: i64 = clk_edf_pick_free(dl, 4, NOW, busy)
166 gw(" busy=[_,_,X,_] picked index="); gn(k10); gw(" (expect 0 -- index 2 is the most overdue but IN FLIGHT)\\n" as *u8)
167 var t10: i64 = 0; if k10 == 0 { t10 = 1 }
168 row("T10 an IN-FLIGHT job is never re-picked, even when it is the most overdue (no double dispatch)" as *u8, t10, pass, total)
169
170 busy[0]=1; busy[1]=1; busy[2]=1; busy[3]=0
171 let k11: i64 = clk_edf_pick_free(dl, 4, NOW, busy)
172 gw(" all-overdue-busy picked index="); gn(k11); gw(" (expect -1 -- the only free job is NOT due)\\n" as *u8)
173 var t11: i64 = 0; if k11 == (0-1) { t11 = 1 }
174 row("T11 every overdue job in flight -> -1: the loop WAITS rather than inventing a duplicate" as *u8, t11, pass, total)
175
176 // VERDICT THROUGH THE CANONICAL LIB (D001): the anchor comes with it, so a passing run is judgeable.
177 let ctr: *i64 = sys_mmap(16) as *i64
178 ctr[0] = pass[0]; ctr[1] = total[0]
179 let rc: i64 = gv_verdict("CLOCK-EDF" as *u8, ctr, "wall-clock EDF: drift-free periods, EDF order, honest starvation, demand-vs-capacity" as *u8)
180 sys_exit(rc); return rc
181}