code wiki / _hdl_build / nx_clock_sched.nx
nx_clock_sched.nx
buildroot/runtime/_hdl_build/nx_clock_sched.nx
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
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
| 18 | const CLK_MAGIC_1000000: i64 = 1000000 |
| 20 | const CLK_MAXJOBS: i64 = 512 // WAS 128 (2026-08-19): the desired plane hit 128/128 and every |
| 32 | const CLK_HOGDUTY: i64 = 9 |
| 45 | const CLK_SIGKILL: i64 = 9 |
| 46 | const CLK_DISPATCH_POLL_MS: i64 = 250 |
| 61 | const CLK_DISPATCH_DEADLINE_MS: i64 = 900000 |
| 62 | const CLK_NAMEW: i64 = CLK_CMD_CAP // bytes per name/organ slot -- DERIVED from the ONE shared |
| 74 | const CLK_ROWW: i64 = 2*CLK_NAMEW + 64 // per-row serialization budget, DERIVED, not chosen: |
| 79 | const CLK_REG: *u8 = "knowledge/sched/jobs.tsv" // RETIRED LEGACY PATH (2026-08-03, debt 1785792856): |
| 100 | const CLK_HEAVY_CONF: *u8 = "knowledge/status/clock_heavy.conf" |
| 101 | const 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 |
| 102 | const CLK_DEFER_MIN_S: i64 = 60 // floor: the shortest re-check that is not a busy loop against /proc/stat |
| 103 | const CLK_DEFER_MAX_S: i64 = 900 // cap: half a window, the same bound CLK_DISPATCH_DEADLINE_MS already places on one job |
| 347 | const CLK_ACTLOGW: i64 = CLK_NAMEW + CLK_NAMEW + 128 |
| 348 | const 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 |
| 349 | const CLK_TOKEN_DEL_BYTE: i64 = 127 // ASCII DEL, the one control byte above the printable range |
| 786 | const CLK_EPOCH_FLOOR: i64 = 1000000000 |
functions
| 106 | func clk_heavy_listed(conf: *u8, n: i64, name: *u8) -> i64 { |
| 133 | func clk_defer_secs(interval: i64) -> i64 { |
| 141 | func clk_storm_defer(heavy: i64, budget: i64) -> i64 { |
| 148 | func clk_storm_budget(ioa: *i64) -> i64 { |
| 153 | func clk_slot(names: *u8, i: i64) -> *u8 { return ((names as i64) + i*CLK_NAMEW) as *u8 } |
| 154 | func 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 } |
| 156 | func 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 } |
| 160 | func clk_register(names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64, name: *u8, organ: *u8, interval: i64) -> i64 { |
| 230 | func clk_tick(intervals: *i64, next_due: *i64, n: i64, now: i64, fired: *i64) -> i64 {
called by 1: main |
| 247 | func clk_dispatch_run(organs: *u8, intervals: *i64, next_due: *i64, n: i64, now: i64, fired: *i64) -> i64 {
called by 3: mainmainclk_run_tickless calls 7: clk_slotsys_forksys_mmapsys_execvesys_exitsys_wait4+1 |
| 283 | func clk_run_tickless(organs: *u8, intervals: *i64, next_due: *i64, n: i64, start_tick: i64, maxbeats: i64, tick_ms: i64, out: *i64) -> i64 { |
| 306 | func clk_due_in(next_due_i: i64, now: i64) -> i64 { return next_due_i - now } |
| 307 | func clk_twin_ok(organ: *u8) -> i64 { let fd: i64 = sys_openat_rd(organ); if fd < 0 { return 0 } sys_close(fd); return 1 } |
| 309 | func 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 } |
| 312 | func 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 } |
| 313 | func clk_msgnum(d: *u8, o: i64, v: i64) -> i64 { |
| 358 | func clk_job_token_len(job: *u8) -> i64 {
called by 1: clk_actlog_row |
| 383 | func clk_actlog_row(ln: *u8, now: i64, organ: *u8, code: i64, job: *u8) -> i64 { |
| 405 | func clk_actlog(organ: *u8, code: i64, job: *u8) -> i64 { |
| 416 | func clk_save(path: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, n: i64) -> i64 { |
| 516 | func clk_load_plane(prefix: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64) -> i64 {
called by 6: mainmainmainclk_save_planeclk_load_statega_clockpass calls 4: sys_mmapsts_loadclk_slotsys_munmap |
| 559 | func clk_save_plane(prefix: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, n: i64) -> i64 { |
| 607 | func clk_load_state(prefix: *u8, legacy: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64) -> i64 { |
| 619 | func clk_merge_store(prefix: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64, base_tick: i64) -> i64 { |
| 801 | func clk_demand_per_window(intervals: *i64, n: i64, window_secs: i64) -> i64 { |
| 821 | func clk_edf_pick_free(deadlines: *i64, n: i64, now: i64, busy: *i64) -> i64 {
called by 1: main |
| 837 | func clk_edf_pick(deadlines: *i64, n: i64, now: i64) -> i64 { |
| 852 | func clk_edf_next(deadlines: *i64, n: i64) -> i64 {
called by 1: clk_run_edf |
| 862 | func clk_edf_missed(deadlines: *i64, intervals: *i64, i: i64, now: i64) -> i64 { |
| 871 | func clk_edf_rearm(deadlines: *i64, intervals: *i64, i: i64, now: i64) -> i64 { |
| 883 | func clk_edf_migrate(deadlines: *i64, intervals: *i64, n: i64, now: i64) -> i64 { |
| 914 | func 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 |
| 915 | func 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 } |
| 916 | func clk_inflight(tag: *u8, organ: *u8, a: i64, b: i64) -> i64 {
called by 1: clk_run_edf calls 7: sys_mmapclk_ifwclk_ifnsys_now_realtime_secsys_openat_wrsys_write+1 |
| 929 | func clk_run_edf(organs: *u8, names: *u8, intervals: *i64, deadlines: *i64, n: i64, maxdispatch: i64, budget_secs: i64, tick_ms: i64, out: *i64) -> i64 {
called by 1: main calls 14: sys_mmapsys_now_realtime_secsys_read_fileclk_edf_pickclk_heavy_listedclk_slot+8 |
| 1063 | func clk_split_argv(raw0: *u8, buf: *u8, argv: *i64, label: *u8) -> i64 { |
| 1104 | func clk_dispatch_one(organs: *u8, names: *u8, i: i64) -> i64 {
called by 2: mainclk_run_edf calls 14: sys_mmapclk_split_argvclk_slotsys_forkclk_msgcatsys_openat_append+8 |
| 1174 | func clk_load(path: *u8, names: *u8, organs: *u8, intervals: *i64, next_due: *i64, np: *i64) -> i64 { |