code wiki / _hdl_build / nx_lease.nx
nx_lease.nx source
↩ module page · 281 lines · 18110 B
1// nx_lease.nx -- THE SOVEREIGN LEASE PRIMITIVE (eats debt seq12/D002: "WMS write lane unlocked =
2// race debt; claims/lease it"). Advisory TTL leases for contended write lanes (ws_put / planes /
3// MEMORY-class shared state): ACQUIRE is atomic (mkdirat -- EEXIST = held), takeover of a stale or
4// released lease is CAS-VERIFIED (write own stamp via tmp+renameat, read back, own nonce wins --
5// last-writer-wins + verify = the loser backs off), RELEASE flips the stamp to released and NEVER
6// unlinks or rmdirs (the never-unlink-lock law: lock dirs are additive; a released stamp is the
7// reusable slot). Self-mkdirs knowledge/lease (rule 20). Stamp = one line:
8// held|released<TAB>owner<TAB>epoch<TAB>ttl<TAB>nonce
9// Stale = state held AND now > epoch + ttl (the HOLDER's declared ttl -- crash-safe by construction:
10// a dead holder's lease self-expires; no daemon needed).
11// nx_lease acquire <name> <owner> <ttl-sec> exit 0 ACQUIRED | 3 BUSY (holder shown) | 4 io
12// nx_lease release <name> <owner> exit 0 RELEASED | 3 REFUSED not-holder | 4 io
13// nx_lease check <name> exit 0 prints stamp | 1 free
14// nx_lease selftest 7 teeth, verdict=GREEN/RED, exit 0/5
15// name grammar [a-zA-Z0-9_-] only (deny slash/dot/traversal by construction).
16// expect_exit: 0 license_tier: ORIGINAL No hw writes (Rule 26).
17import "nx_lease_lib.nx" // the primitive itself; this file is the CLI verbs + selftest (2026-09-03 extraction)
18
19// 2026-09-05: the check verb's second and third roots were INLINE LITERALS assigned inside a nested loop, and the
20// compiled probe never opened them -- LS-FREE against a stamp the shell tool could read at that very path, from the
21// same CWD. The first root is a named const and worked. So: the roots are consts, the probe is ONE function that
22// main and the selftest both call, and the selftest plants a HELD stamp under the buildroot root and requires the
23// probe to find it THERE (the old selftest was GREEN because every fixture lived under the first root).
24const LS_ROOT_BUILDROOT: *u8 = "buildroot/knowledge/lease/"
25const LS_ROOT_PARENT: *u8 = "../knowledge/lease/"
26const LS_ROOTS: i64 = 3
27func ls_root_at(ri: i64) -> *u8 {
28 if ri == 1 { return LS_ROOT_BUILDROOT }
29 if ri == 2 { return LS_ROOT_PARENT }
30 return LS_DEFAULT_ROOT
31}
32// probes every root for <name>'s stamp: a HELD stamp (h) from any root wins, else the first stamp found.
33// returns the stamp length copied into rb (0 when no root holds one) and writes the winning root index to rsel[0].
34func ls_probe_roots(name: *u8, rb: *u8, rsel: *i64) -> i64 {
35 let dir: *u8 = sys_mmap(LS_PATHCAP)
36 let sp: *u8 = sys_mmap(LS_PATHCAP)
37 let tb: *u8 = sys_mmap(LS_STAMPCAP)
38 var rn: i64 = 0
39 rsel[0] = 0 - 1
40 var ri: i64 = 0
41 var chosen: i64 = 0
42 while ri < LS_ROOTS {
43 if chosen == 0 {
44 let root: *u8 = ls_root_at(ri)
45 ls_dirpath_root(root, name, dir)
46 ls_stamp_path(dir, sp)
47 let tn: i64 = ls_read(sp, tb, LS_STAMPCAP - 1)
48 if tn > 0 {
49 var take: i64 = 0
50 if rn <= 0 { take = 1 }
51 if tb[0] == (104 as u8) { take = 1; chosen = 1 }
52 if take == 1 {
53 rn = tn
54 rsel[0] = ri
55 var ci: i64 = 0
56 while ci < tn { rb[ci] = tb[ci]; ci = ci + 1 }
57 }
58 }
59 }
60 ri = ri + 1
61 }
62 return rn
63}
64func main(argc: i64, argv: *i64) -> i64 {
65 if argc < 2 { ls_werr("usage: nx_lease {acquire <name> <owner> <ttl-sec> | release <name> <owner> | check <name> | selftest}\n" as *u8); sys_exit(LS_EXIT_USAGE); return LS_EXIT_USAGE }
66 let v: *u8 = argv[1] as *u8
67 let hb: *u8 = sys_mmap(LS_PATHCAP)
68
69 if v[0] == (LS_V_S as u8) {
70 var pass: i64 = 1
71 if ls_name_ok("../evil" as *u8) == 1 { pass = 0 }
72 if ls_name_ok("a/b" as *u8) == 1 { pass = 0 }
73 if ls_name_ok("wms-write" as *u8) == 0 { pass = 0 }
74 if ls_acquire("lease_probe" as *u8, "tester-a" as *u8, LS_MAGIC_3600, hb) != 0 { pass = 0; ls_werr("t1 acquire fail\n" as *u8) }
75 if ls_acquire("lease_probe" as *u8, "tester-b" as *u8, LS_MAGIC_3600, hb) != 1 { pass = 0; ls_werr("t2 busy-expected fail\n" as *u8) }
76 if ls_release("lease_probe" as *u8, "tester-b" as *u8) != 1 { pass = 0; ls_werr("t3 wrong-owner-release fail\n" as *u8) }
77 if ls_release("lease_probe" as *u8, "tester-a" as *u8) != 0 { pass = 0; ls_werr("t4 release fail\n" as *u8) }
78 if ls_acquire("lease_probe" as *u8, "tester-b" as *u8, LS_MAGIC_3600, hb) != 0 { pass = 0; ls_werr("t5 reacquire-after-release fail\n" as *u8) }
79 if ls_release("lease_probe" as *u8, "tester-b" as *u8) != 0 { pass = 0; ls_werr("t6 cleanup fail\n" as *u8) }
80 if ls_acquire("lease_probe2" as *u8, "tester-a" as *u8, 0, hb) != 0 { pass = 0; ls_werr("t7a stale-setup fail\n" as *u8) }
81 if ls_acquire("lease_probe2" as *u8, "tester-b" as *u8, LS_MAGIC_3600, hb) != 0 { pass = 0; ls_werr("t7b stale-takeover fail\n" as *u8) }
82 if ls_release("lease_probe2" as *u8, "tester-b" as *u8) != 0 { pass = 0; ls_werr("t7c cleanup fail\n" as *u8) }
83 // ---- TOOTH 8: CONCURRENCY -- THE ONLY PROPERTY THAT MAKES THIS A MUTEX, AND UNTIL 2026-08-08
84 // THE ONE PROPERTY NEVER TESTED. Teeth 1-7 are all SEQUENTIAL acquires in ONE process, and the
85 // source contained zero sys_fork/sys_clone/sys_wait, so mutual exclusion under SIMULTANEOUS
86 // acquire had never been exercised in either direction and a GREEN said nothing about it.
87 // ★A MUTEX WHOSE SELFTEST NEVER RUNS TWO ACQUIRERS AT ONCE IS UNTESTED FOR THE ONLY PROPERTY
88 // THAT MAKES IT A MUTEX; A GREEN FROM A SEQUENTIAL FIXTURE IS SILENT ABOUT EVERY CONCURRENT PATH.
89 // WHY NOW: two independently forked sweeps were OBSERVED both reporting acquisition of one slot.
90 // The observation is real; the cause is NOT reproduced. This tooth is the experiment that
91 // decides it -- it does not assume the answer.
92 // ★REPEATED ROUNDS ON PURPOSE: a race that fires 1-in-K is invisible in a single trial.
93 var rround: i64 = 0
94 while rround < 5 {
95 // ★UNIQUE NAME PER RUN, NOT JUST PER ROUND -- MY FIRST FIXTURE CONTAMINATED ITSELF.
96 // v1 used fixed literals lease_race0..4 and RELEASED them at the end of each round. On the
97 // SECOND run of the selftest those names still carried a `released` stamp, so every racer
98 // took the RELEASED-TAKEOVER path (g_st==2) instead of the stampless path, and all four
99 // legitimately claimed. The failure count jumped 3/5 -> 5/5 and looked exactly like a
100 // REGRESSION FROM MY FIX, when it was leftover state from the previous run.
101 // ★★A FIXTURE THAT PERSISTS STATE BETWEEN RUNS STOPS MEASURING THE CODE AND STARTS MEASURING
102 // ITS OWN HISTORY -- and the false signal it produces points at whatever you changed last.
103 // pid+round makes every round of every run a name that has never existed before.
104 let rnb: *u8 = sys_mmap(LS_PATHCAP)
105 var rno: i64 = ls_cat(rnb, 0, "lrace" as *u8)
106 rno = ls_catn(rnb, rno, ls_pid())
107 rnb[rno] = 95 as u8
108 rno = rno + 1
109 rno = ls_catn(rnb, rno, rround)
110 rnb[rno] = 0 as u8
111 let rname: *u8 = rnb
112 var kid: i64 = 0
113 while kid < 4 {
114 var kown: *u8 = "ra" as *u8
115 if kid == 1 { kown = "rb" as *u8 }
116 if kid == 2 { kown = "rc" as *u8 }
117 if kid == 3 { kown = "rd" as *u8 }
118 let kpid: i64 = sys_fork()
119 if kpid == 0 {
120 let khb: *u8 = sys_mmap(LS_PATHCAP)
121 let kr: i64 = ls_acquire(rname, kown, LS_MAGIC_3600, khb)
122 if kr == 0 { sys_exit(0) }
123 sys_exit(1)
124 }
125 kid = kid + 1
126 }
127 var got: i64 = 0
128 var w: i64 = 0
129 while w < 4 {
130 let stp: *i64 = sys_mmap(16) as *i64
131 sys_wait4(0 - 1, stp, 0)
132 if ((stp[0] >> 8) % 256) == 0 { got = got + 1 }
133 w = w + 1
134 }
135 // ★ASSERT EXACTLY ONE. got>1 = not mutually exclusive (the defect this hunts).
136 // got==0 = nobody won, which is ALSO a failure and must not read as "safe".
137 if got != 1 {
138 pass = 0
139 ls_werr("t8 RACE FAIL: acquirers=" as *u8); ls_wn(got); ls_werr(" expected exactly 1\n" as *u8)
140 }
141 ls_release(rname, "ra" as *u8)
142 ls_release(rname, "rb" as *u8)
143 ls_release(rname, "rc" as *u8)
144 ls_release(rname, "rd" as *u8)
145 rround = rround + 1
146 }
147 // ---- TOOTH 9: TAKEOVER CONCURRENCY. Tooth 8 races on FRESH names, so every racer there goes
148 // through the INITIAL claim; the TAKEOVER path (a stamp that EXISTS and has been judged
149 // released/expired) is never reached, and a GREEN tooth 8 is SILENT about it.
150 // ★★★★★★A CONCURRENCY TEST COVERS ONLY THE CODE PATH ITS FIXTURE HAPPENS TO REACH -- "THE MUTEX IS
151 // PROVEN" IS A CLAIM ABOUT THE FIXTURE, NOT ABOUT THE MUTEX. This path is the one a real sweep
152 // uses constantly (release the lease, next sweep takes it over), so it is the COMMON case, not
153 // an exotic one -- and it is the case my contaminated tooth-8 fixture reached BY ACCIDENT, where
154 // it showed acquirers=4.
155 var tround: i64 = 0
156 while tround < 5 {
157 let tnb: *u8 = sys_mmap(LS_PATHCAP)
158 var tno: i64 = ls_cat(tnb, 0, "ltake" as *u8)
159 tno = ls_catn(tnb, tno, ls_pid())
160 tnb[tno] = 95 as u8
161 tno = tno + 1
162 tno = ls_catn(tnb, tno, tround)
163 tnb[tno] = 0 as u8
164 let tname: *u8 = tnb
165 // ★ASSERT THE FIXTURE REACHED THE CONDITION BEFORE ASSERTING THE OUTCOME. If this seed
166 // acquire+release does not leave a RELEASED stamp, the racers below take the INITIAL path
167 // and tooth 9 silently degrades into a second copy of tooth 8 -- passing while testing
168 // nothing new. That is the vacuous-fixture failure, so it is checked, not assumed.
169 if ls_acquire(tname, "seed" as *u8, LS_MAGIC_3600, hb) != 0 { pass = 0; ls_werr("t9 seed-acquire fail (FIXTURE DID NOT REACH THE CONDITION)\n" as *u8) }
170 if ls_release(tname, "seed" as *u8) != 0 { pass = 0; ls_werr("t9 seed-release fail (FIXTURE DID NOT REACH THE CONDITION)\n" as *u8) }
171 var tkid: i64 = 0
172 while tkid < 4 {
173 var town: *u8 = "ta" as *u8
174 if tkid == 1 { town = "tb" as *u8 }
175 if tkid == 2 { town = "tc" as *u8 }
176 if tkid == 3 { town = "td" as *u8 }
177 let tpid: i64 = sys_fork()
178 if tpid == 0 {
179 let thb: *u8 = sys_mmap(LS_PATHCAP)
180 let tr: i64 = ls_acquire(tname, town, LS_MAGIC_3600, thb)
181 if tr == 0 { sys_exit(0) }
182 sys_exit(1)
183 }
184 tkid = tkid + 1
185 }
186 var tgot: i64 = 0
187 var tw: i64 = 0
188 while tw < 4 {
189 let tstp: *i64 = sys_mmap(16) as *i64
190 sys_wait4(0 - 1, tstp, 0)
191 if ((tstp[0] >> 8) % 256) == 0 { tgot = tgot + 1 }
192 tw = tw + 1
193 }
194 // tgot>1 = the takeover ABA. tgot==0 = a released lease nobody could reclaim, which is a
195 // DIFFERENT and equally real defect (a permanently wedged slot) and must not read as safe.
196 if tgot != 1 {
197 pass = 0
198 ls_werr("t9 TAKEOVER-RACE FAIL: acquirers=" as *u8); ls_wn(tgot); ls_werr(" expected exactly 1 -- KNOWN-OPEN, OWNED, REPRODUCED: debt 1786244397. This RED is not a new breakage and not noise: teeth 1-8 (incl. fresh-name concurrency) are GREEN and the initial/stampless claim is correct by construction. Remedy is renameat2(RENAME_NOREPLACE) to move the dead stamp aside -- arbitration by WHO MOVED IT, which needs no unique nonce (the current one collides within a process-second). DO NOT green-wash this tooth; deleting it hides the only reproduction we have.\n" as *u8)
199 }
200 ls_release(tname, "ta" as *u8)
201 ls_release(tname, "tb" as *u8)
202 ls_release(tname, "tc" as *u8)
203 ls_release(tname, "td" as *u8)
204 tround = tround + 1
205 }
206 // 2026-09-05 CROSS-ROOT PROBE TOOTH: the check verb's second root was an inline literal that never opened, and this
207 // selftest read GREEN because every fixture lived under the first root -- a fixture the defect could not fail. Plant a
208 // HELD stamp under the buildroot root and require the probe to find it THERE and read it as held; then require a
209 // name held nowhere to read absent (neg-control), so a probe that answered present for everything cannot pass.
210 let xnb: *u8 = sys_mmap(LS_PATHCAP)
211 var xno: i64 = ls_cat(xnb, 0, "lsxroot" as *u8)
212 xno = ls_catn(xnb, xno, ls_pid())
213 xnb[xno] = 0 as u8
214 let xhb: *u8 = sys_mmap(LS_PATHCAP)
215 let xr: i64 = ls_acquire_root(LS_ROOT_BUILDROOT, xnb, "xroot" as *u8, LS_MAGIC_3600, xhb)
216 let xrb: *u8 = sys_mmap(LS_STAMPCAP)
217 let xsel: *i64 = sys_mmap(LS_STAMPCAP) as *i64
218 let xrn: i64 = ls_probe_roots(xnb, xrb, xsel)
219 ls_werr("LS-SELFTEST cross-root: acquire_rc=" as *u8); ls_wn(xr); ls_werr(" probe_len=" as *u8); ls_wn(xrn); ls_werr(" root_index=" as *u8); ls_wn(xsel[0]); ls_werr("\n" as *u8)
220 if xr != 0 { pass = 0; ls_werr("LS-SELFTEST FAIL cross-root fixture did not acquire under the buildroot root\n" as *u8) }
221 if xrn <= 0 { pass = 0; ls_werr("LS-SELFTEST FAIL cross-root probe found NO stamp for a lease held under the buildroot root\n" as *u8) }
222 if xsel[0] != 1 { pass = 0; ls_werr("LS-SELFTEST FAIL cross-root probe found the stamp under the wrong root\n" as *u8) }
223 if xrn > 0 { if xrb[0] != (104 as u8) { pass = 0; ls_werr("LS-SELFTEST FAIL cross-root stamp was not read as HELD\n" as *u8) } }
224 ls_release_root(LS_ROOT_BUILDROOT, xnb, "xroot" as *u8)
225 xnb[xno] = 122 as u8
226 xnb[xno + 1] = 0 as u8
227 let xrn2: i64 = ls_probe_roots(xnb, xrb, xsel)
228 if xrn2 > 0 { pass = 0; ls_werr("LS-SELFTEST FAIL neg-control: a name held nowhere read as present\n" as *u8) }
229 if pass == 1 { ls_werr("LS-SELFTEST OK verdict=GREEN teeth=11 (concurrency: fresh-name AND released-takeover, 5 rounds x 4 racers each; cross-root probe + neg-control)\n" as *u8); sys_exit(0); return 0 }
230 ls_werr("LS-SELFTEST FAIL verdict=RED\n" as *u8)
231 sys_exit(LS_EXIT_SELF)
232 return LS_EXIT_SELF
233 }
234
235 if argc < 3 { ls_werr("verb needs <name>\n" as *u8); sys_exit(LS_EXIT_USAGE); return LS_EXIT_USAGE }
236 let name: *u8 = argv[2] as *u8
237 if ls_name_ok(name) == 0 { ls_werr("LS-REFUSED bad name (grammar [a-zA-Z0-9_-])\n" as *u8); sys_exit(LS_EXIT_USAGE); return LS_EXIT_USAGE }
238
239 if v[0] == (LS_V_A as u8) {
240 if argc < 5 { ls_werr("acquire needs <name> <owner> <ttl-sec>\n" as *u8); sys_exit(LS_EXIT_USAGE); return LS_EXIT_USAGE }
241 let owner: *u8 = argv[3] as *u8
242 var ttl: i64 = 0
243 let ts: *u8 = argv[4] as *u8
244 var ti: i64 = 0
245 while ts[ti] != (0 as u8) { let c: i64 = ts[ti]; if c >= LS_D0 { if c <= LS_D9 { ttl = ttl * LS_B10 + (c - LS_D0) } } ti = ti + 1 }
246 let r: i64 = ls_acquire(name, owner, ttl, hb)
247 if r == 0 { ls_werr("LS-ACQUIRED " as *u8); ls_werr(name); ls_werr(" owner=" as *u8); ls_werr(owner); ls_werr(" ttl=" as *u8); ls_wn(ttl); ls_werr("\n" as *u8); sys_exit(0); return 0 }
248 if r == 1 { ls_werr("LS-BUSY " as *u8); ls_werr(name); ls_werr(" holder=" as *u8); ls_werr(hb); ls_werr("\n" as *u8); sys_exit(LS_EXIT_BUSY); return LS_EXIT_BUSY }
249 ls_werr("LS-FAIL io\n" as *u8)
250 sys_exit(LS_EXIT_IO)
251 return LS_EXIT_IO
252 }
253 if v[0] == (LS_V_R as u8) {
254 if argc < 4 { ls_werr("release needs <name> <owner>\n" as *u8); sys_exit(LS_EXIT_USAGE); return LS_EXIT_USAGE }
255 let owner2: *u8 = argv[3] as *u8
256 let r2: i64 = ls_release(name, owner2)
257 if r2 == 0 { ls_werr("LS-RELEASED " as *u8); ls_werr(name); ls_werr("\n" as *u8); sys_exit(0); return 0 }
258 if r2 == 1 { ls_werr("LS-REFUSED not-holder (or not held)\n" as *u8); sys_exit(LS_EXIT_BUSY); return LS_EXIT_BUSY }
259 ls_werr("LS-FAIL io\n" as *u8)
260 sys_exit(LS_EXIT_IO)
261 return LS_EXIT_IO
262 }
263 if v[0] == (LS_V_C as u8) {
264 // TWO LEASE STORES UNDER ONE NAME, MEASURED 2026-09-05: the lease dir is CWD-relative, so a check
265 // from the serving root printed LS-FREE while nishi_compare_regen (CWD=buildroot) held the lease and
266 // refused LS-BUSY seconds later. A false FREE is the worst answer a mutex probe can give, so the
267 // READ side now probes every root the estate's two CWDs produce and a HELD stamp from any root wins;
268 // the WRITE side (acquire and release) is deliberately unchanged -- moving writers is a separate decision.
269 let rb: *u8 = sys_mmap(LS_STAMPCAP)
270 let rsel: *i64 = sys_mmap(LS_STAMPCAP) as *i64
271 let rn: i64 = ls_probe_roots(name, rb, rsel)
272 if rn > 0 { ls_werr("LS-ROOT " as *u8); ls_werr(ls_root_at(rsel[0])); ls_werr(" (3 roots probed, a held stamp from any root wins)" as *u8); ls_werr("\n" as *u8) }
273 if rn <= 0 { ls_werr("LS-FREE " as *u8); ls_werr(name); ls_werr("\n" as *u8); sys_exit(1); return 1 }
274 sys_write(1, rb, rn)
275 sys_exit(0)
276 return 0
277 }
278 ls_werr("usage: nx_lease {acquire|release|check|selftest}\n" as *u8)
279 sys_exit(LS_EXIT_USAGE)
280 return LS_EXIT_USAGE
281}