code wiki / _hdl_build / nx_clock_tickless.nx
nx_clock_tickless.nx
buildroot/runtime/_hdl_build/nx_clock_tickless.nx
about
nx_clock_tickless.nx -- the TICKLESS driver (the sched_tickless.raw lesson: don't burn a constant tick when
idle). From ONE spark it runs a BOUNDED number of beats, but between beats it SLEEPS exactly until the next due
job (the minimum next_due) instead of waking every tick -- so a registry with sparse jobs costs only as many
wakeups as there are due events, not one-per-tick. Bounded (TLN_MAXBEATS) so a single spark can never run away.
Reduces the external trigger from per-beat to per-WINDOW. Reuses the gated nx_clock library (load/dispatch/save).
nx_clock_tickless [registry] [tickfile] (run the elf directly to pass args; defaults = the live registry)
license_tier: ORIGINAL expect_exit: 0
dependencies 2 imports · 0 importers
imports: nx_clock_sched.nxnx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 10 | const TLN_MAGIC_1000000: i64 = 1000000 |
| 12 | const TLN_MAXBEATS: i64 = 30 // beats per window; the NAS supervisor respawns after each window (respawns stay well under the crash-loop guard) |
| 13 | const TLN_WINDOW_SECS: i64 = 1800 // 2026-08-04: a window is now bounded by REAL seconds, not by a beat |
| 16 | const TLN_MAXDISPATCH: i64 = 240 // hard per-window dispatch ceiling: a saturated registry can never turn |
| 19 | const TLN_TICK_MS: i64 = 1000 // 1s per logical tick (server cadence; a sitecheck at interval 30 = a probe every ~30s) |
| 20 | const TLN_MAXWINDOWS: i64 = 120 // windows per LIFE (2026-07-05 leak arc): the GC-free substrate leaks address |
functions
| 28 | func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } |
| 29 | func 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 } |
| 30 | func cat(dst: *u8, o: i64, s: *u8) -> i64 { var x: i64=o; var i: i64=0; while s[i]!=(0 as u8){dst[x]=s[i];x=x+1;i=i+1} return x } called by 1: hbp |
| 31 | func catn(dst: *u8, o: i64, v: i64) -> i64 { var x: i64=o; var m: i64=v; if m<0{dst[x]=45 as u8;x=x+1;m=0-m} if m==0{dst[x]=48 as u8;return x+1} let t:*u8=sys_mmap(24); var k:i64=0; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{dst[x]=t[k-1-j];x=x+1;j=j+1} return x } |
| 43 | func hbp(tag: *u8, a: i64, b: i64, c: i64, p: *u8) -> i64 { let now: i64=sys_now_realtime_sec(); let st:*u8=sys_mmap(256); var o:i64=0; o=cat(st,o,"CLOCKBEAT " as *u8); o=cat(st,o,tag); o=cat(st,o," a=" as *u8); o=catn(st,o,a); o=cat(st,o," b=" as *u8); o=catn(st,o,b); o=cat(st,o," c=" as *u8); o=catn(st,o,c); o=cat(st,o," t=" as *u8); o=catn(st,o,now); st[o]=10 as u8; o=o+1; st[o]=0 as u8; let fd:i64=sys_openat_wr(p,0x1a4); if fd>=0 { sys_write(fd,st,o); sys_close(fd) } return 0 } |
| 44 | func hb(tag: *u8, a: i64, b: i64, c: i64) -> i64 { return hbp(tag, a, b, c, "sites/nishifamily/clock_heartbeat.txt" as *u8) } |
| 45 | func 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 } |
| 46 | func savenum(p: *u8, v: i64) -> i64 { let buf: *u8 = sys_mmap(24); var o: i64=0; var m: i64=v; if m==0 { buf[0]=48 as u8; o=1 } else { let t: *u8=sys_mmap(24); var k: i64=0; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} while o<k { buf[o]=t[k-1-o]; o=o+1 } } let fd: i64 = sys_openat_wr(p, 0x1a4); if fd>=0 { sys_write(fd, buf, o); sys_close(fd) } return 0 } |
| 50 | func sleep_ms(ms: i64) -> i64 |
| 64 | func main(argc: i64, argv: *i64) -> i64 |