code wiki / _hdl_build / nx_clock_sched.nx

nx_clock_sched.nx

buildroot/runtime/_hdl_build/nx_clock_sched.nx

77255 B1207 linesdepth 5pulls 11 transitivereach 11 importersview sourcekind librarytopic clock
docsdependenciesstructsconstsfunctions

about

nx_clock_sched.nx -- RENAMED FROM nx_clock.nx 2026-07-31 (lib-reconcile). PERMANENT FIX for a two-libraries-one-name collision: runtime/nx_clock.nx is the TIMING library (nx_clock_monotonic_ns, 62 importers); THIS file is an unrelated tickless JOB SCHEDULER (clk_* registry + dispatcher) that only shared the filename. nx_cc binds an import to the IMPORTER'S OWN DIRECTORY FIRST, so every _hdl_build organ importing nx_clock.nx silently got the SCHEDULER -- _clk_probe.nx, whose whole purpose is to prove nx_clock_monotonic_ns works, could not resolve it. The RENAME is the fix. so we avoid issues ... dont have a million pulses and daemons"). Researched (knowledge/fetched/sched_*.raw: clock-distribution = ONE oscillator -> a tree of DIVIDERS; PLL derives every frequency from ONE reference; cron = ONE daemon reads ONE table of timed jobs; tickless = don't burn a constant tick when idle). The S-class pattern is identical: ONE tick source + ONE durable JOB REGISTRY + ONE dispatcher. Every periodic capability REGISTERS a job (name, interval-in-ticks) = a divider off the single clock -- it does NOT spin up its own daemon/pulse loop. So N capabilities cost ONE loop, not N. This library is the registry + dispatcher; the single tick source drives it (one external spark, like a crystal). license_tier: ORIGINAL

dependencies 4 imports · 11 importers

nx_syscalls.nx nx_store_seed_lib.nx nx_clock_caps.nx nx_ioadmit_lib.nx nx_clock_sched.nx _clksched_probe.nx nx_clock_dispatch_gate.nx nx_clock_edf_gate.nx nx_clock_gate.nx nx_clock_reregister_gate.nx nx_clock_run.nx nx_clock_status.nx nx_clock_status_gate.nx nx_clock_tickless.nx nx_clock_tickless_gate.nx

diagram shows first 10 each side; +0 more imports, +1 more importers in the complete lists below.

imports: nx_syscalls.nxnx_store_seed_lib.nxnx_clock_caps.nxnx_ioadmit_lib.nx

imported by: _clksched_probe.nxnx_clock_dispatch_gate.nxnx_clock_edf_gate.nxnx_clock_gate.nxnx_clock_reregister_gate.nxnx_clock_run.nxnx_clock_status.nxnx_clock_status_gate.nxnx_clock_tickless.nxnx_clock_tickless_gate.nxnx_gateadjudicate.nx

structs

none

consts

18const CLK_MAGIC_1000000: i64 = 1000000
20const CLK_MAXJOBS: i64 = 512 // WAS 128 (2026-08-19): the desired plane hit 128/128 and every
32const CLK_HOGDUTY: i64 = 9
45const CLK_SIGKILL: i64 = 9
46const CLK_DISPATCH_POLL_MS: i64 = 250
61const CLK_DISPATCH_DEADLINE_MS: i64 = 900000
62const CLK_NAMEW: i64 = CLK_CMD_CAP // bytes per name/organ slot -- DERIVED from the ONE shared
74const CLK_ROWW: i64 = 2*CLK_NAMEW + 64 // per-row serialization budget, DERIVED, not chosen:
79const CLK_REG: *u8 = "knowledge/sched/jobs.tsv" // RETIRED LEGACY PATH (2026-08-03, debt 1785792856):
100const CLK_HEAVY_CONF: *u8 = "knowledge/status/clock_heavy.conf"
101const CLK_DEFER_DIV: i64 = 4 // re-arm at interval/4: a 1800 s beat re-checks every 450 s, so a storm costs it at most 3 probes before its own next period
102const CLK_DEFER_MIN_S: i64 = 60 // floor: the shortest re-check that is not a busy loop against /proc/stat
103const CLK_DEFER_MAX_S: i64 = 900 // cap: half a window, the same bound CLK_DISPATCH_DEADLINE_MS already places on one job
347const CLK_ACTLOGW: i64 = CLK_NAMEW + CLK_NAMEW + 128
348const CLK_TOKEN_MIN_BYTE: i64 = 33 // the first printable ASCII byte that is not a space; every byte below it is a space or a control byte
349const CLK_TOKEN_DEL_BYTE: i64 = 127 // ASCII DEL, the one control byte above the printable range
786const CLK_EPOCH_FLOOR: i64 = 1000000000

functions

106func clk_heavy_listed(conf: *u8, n: i64, name: *u8) -> i64 {
called by 2: mainclk_run_edf
133func clk_defer_secs(interval: i64) -> i64 {
called by 2: mainclk_run_edf
141func clk_storm_defer(heavy: i64, budget: i64) -> i64 {
called by 2: mainclk_run_edf
148func clk_storm_budget(ioa: *i64) -> i64 {
153func clk_slot(names: *u8, i: i64) -> *u8 { return ((names as i64) + i*CLK_NAMEW) as *u8 }
154func clk_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
156func clk_find(names: *u8, n: i64, name: *u8) -> i64 { var i: i64=0; while i<n { if clk_streq(clk_slot(names,i), name)==1 { return i } i=i+1 } return 0-1 }
160func clk_register(names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64, name: *u8, organ: *u8, interval: i64) -> i64 {
230func clk_tick(intervals: *i64, next_due: *i64, n: i64, now: i64, fired: *i64) -> i64 {
called by 1: main
247func clk_dispatch_run(organs: *u8, intervals: *i64, next_due: *i64, n: i64, now: i64, fired: *i64) -> i64 {
283func clk_run_tickless(organs: *u8, intervals: *i64, next_due: *i64, n: i64, start_tick: i64, maxbeats: i64, tick_ms: i64, out: *i64) -> i64 {
called by 1: main calls 2: sys_mmapclk_dispatch_run
306func clk_due_in(next_due_i: i64, now: i64) -> i64 { return next_due_i - now }
called by 2: mainmain
307func clk_twin_ok(organ: *u8) -> i64 { let fd: i64 = sys_openat_rd(organ); if fd < 0 { return 0 } sys_close(fd); return 1 }
called by 2: mainmain calls 2: sys_openat_rdsys_close
309func clk_itoa(buf: *u8, o: i64, v: i64) -> i64 { var w: i64=o; var m: i64=v; if m==0{buf[w]=48 as u8;return w+1} if m<0{buf[w]=45 as u8;w=w+1;m=0-m} 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{buf[w]=t[k-1-j];w=w+1;j=j+1} return w }
312func clk_msgcat(d: *u8, o: i64, s: *u8) -> i64 { var x: i64=o; var i: i64=0; while s[i]!=(0 as u8){d[x]=s[i];x=x+1;i=i+1} return x }
313func clk_msgnum(d: *u8, o: i64, v: i64) -> i64 {
called by 1: clk_actlog_row calls 2: sys_mmapsys_munmap
358func clk_job_token_len(job: *u8) -> i64 {
called by 1: clk_actlog_row
383func clk_actlog_row(ln: *u8, now: i64, organ: *u8, code: i64, job: *u8) -> i64 {
405func clk_actlog(organ: *u8, code: i64, job: *u8) -> i64 {
416func clk_save(path: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, n: i64) -> i64 {
516func clk_load_plane(prefix: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64) -> i64 {
559func clk_save_plane(prefix: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, n: i64) -> i64 {
607func clk_load_state(prefix: *u8, legacy: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64) -> i64 {
called by 2: mainmain calls 2: clk_load_planeclk_load
619func clk_merge_store(prefix: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64, base_tick: i64) -> i64 {
801func clk_demand_per_window(intervals: *i64, n: i64, window_secs: i64) -> i64 {
called by 2: mainmain
821func clk_edf_pick_free(deadlines: *i64, n: i64, now: i64, busy: *i64) -> i64 {
called by 1: main
837func clk_edf_pick(deadlines: *i64, n: i64, now: i64) -> i64 {
called by 2: mainclk_run_edf
852func clk_edf_next(deadlines: *i64, n: i64) -> i64 {
called by 1: clk_run_edf
862func clk_edf_missed(deadlines: *i64, intervals: *i64, i: i64, now: i64) -> i64 {
called by 2: mainclk_run_edf
871func clk_edf_rearm(deadlines: *i64, intervals: *i64, i: i64, now: i64) -> i64 {
called by 2: mainclk_run_edf
883func clk_edf_migrate(deadlines: *i64, intervals: *i64, n: i64, now: i64) -> i64 {
called by 2: mainmain
914func clk_ifw(s: *u8, dst: *u8, o: i64) -> 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: clk_inflight
915func clk_ifn(dst: *u8, o: i64, v: i64) -> i64 { var x: i64=o; var mm: i64=v; if mm<0{dst[x]=45 as u8;x=x+1;mm=0-mm} if mm==0{dst[x]=48 as u8;return x+1} let t:*u8=sys_mmap(24); var k:i64=0; while mm>0{t[k]=(48+(mm%10)) as u8;mm=mm/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 }
called by 1: clk_inflight calls 1: sys_mmap
916func clk_inflight(tag: *u8, organ: *u8, a: i64, b: i64) -> i64 {
929func clk_run_edf(organs: *u8, names: *u8, intervals: *i64, deadlines: *i64, n: i64, maxdispatch: i64, budget_secs: i64, tick_ms: i64, out: *i64) -> i64 {
1063func clk_split_argv(raw0: *u8, buf: *u8, argv: *i64, label: *u8) -> i64 {
1104func clk_dispatch_one(organs: *u8, names: *u8, i: i64) -> i64 {
1174func clk_load(path: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64) -> i64 {