decisions(scheduler): the scheduler IS an actor — tick-driven receive, one kernel cycle at the floor; MA3c re-sliced #55

Manually merged
mdoorn merged 4 commits from feat/055-decisions-scheduler-the-scheduler-is-an-actor into master 2026-03-10 08:30:00 +01:00
Owner

decisions(scheduler): the scheduler IS an actor — tick-driven receive, one kernel cycle at the floor; MA3c re-sliced

Along the way:

  • MA3c-1: receive-slot LOWERING — hoisted handlers, tag → handler dispatch table, the message word crosses (row 14c checkpoint 4)
  • MA3c-2a: actor STATE bootstrap — fields at the arena base, with mut lands, the watermark is real (row 14c checkpoint 5)
  • corpus/primes: the sieve of Eratosthenes at 1,000,000 — first computational-scale stone + the performance roadmap

Touches 75 files: current-state.md, decisions-scheduler-model.md, docs/actors.md, docs/errors/E0737.md, docs/impl/memory-model/arenas.md, docs/runtime.md and 69 more.

decisions(scheduler): the scheduler IS an actor — tick-driven receive, one kernel cycle at the floor; MA3c re-sliced Along the way: - MA3c-1: receive-slot LOWERING — hoisted handlers, tag → handler dispatch table, the message word crosses (row 14c checkpoint 4) - MA3c-2a: actor STATE bootstrap — fields at the arena base, with mut lands, the watermark is real (row 14c checkpoint 5) - corpus/primes: the sieve of Eratosthenes at 1,000,000 — first computational-scale stone + the performance roadmap Touches 75 files: `current-state.md`, `decisions-scheduler-model.md`, `docs/actors.md`, `docs/errors/E0737.md`, `docs/impl/memory-model/arenas.md`, `docs/runtime.md` and 69 more.
mdoorn approved these changes 2026-03-09 17:37:12 +01:00
mdoorn left a comment

Yes. The commit messages carried me through all 75 files, which is not always true.

Yes. The commit messages carried me through all 75 files, which is not always true.
@ -396,0 +530,4 @@
/// behavior's (deduped by [`FnId`] against what the behavior already
/// pulled), then the handlers themselves join the set. Split from
/// [`lower_reachable_fns`] under the R4 function-LoC cap.
fn fold_in_handlers<'a>(
Owner

fold_in_handlers reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?

`fold_in_handlers` reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?
Author
Owner

Split. The decision in fold_in_handlers is a pure function now, with its own tests in src/rust/crates/ck_driver/src/compile/supervisor.rs.

Split. The decision in `fold_in_handlers` is a pure function now, with its own tests in `src/rust/crates/ck_driver/src/compile/supervisor.rs`.
Owner decision 2026-07-05 (pseudo-code recorded verbatim in
decisions-scheduler-model.md): the scheduler is an ORDINARY CkLang actor —
state holds the tick handle, spawn registers Clock::tick + defers its
teardown, the drain is a receive slot; recurrence = Tick messages into its
own mailbox, no while<N> anywhere near its lifetime. ONE receive slot per
message type, multiple slots per actor. The only floor grain: the park →
deliver → dispatch → park kernel cycle, the single unbounded back-edge
CkLang deliberately cannot spell — SANCTIONED ISA 22 → 23 at the kernel
slice (ck_syscall tier). Bootstrap spellings mapped (Clock::tick closure =
register's data form until LC8; handle.destroy = defer Clock::deregister).

Supersedes the never-landed while<N>-wake-bound orchestration brief (the
MA3c-1 agent was stopped before writing; nothing to retract in code).

plan.md row 14c NEXT re-sliced: MA3c-1 receive LOWERING → MA3c-2 kernel +
Scheduler actor → MA3c-3 send lowering. docs/runtime.md floor section:
where the scheduling regress bottoms out.
A declared receive<T> slot compiles: the body hoists into a handler fn
under the two-word ABI (state_region, msg_word) — state unread until
MA3c-2, the binder bound to the message word via the resolver's documented
binding order (guarded by a hard hoist-time error, never silent drift);
the actor gets ReceiveDispatch, compiler-settled data (tag = declaration
index, dense + deterministic) the MA3c-2 kernel will read. Declared -> Int
returns recorded per row (the observation channel; kernel dispatch runs
handlers for effect). One-slot-per-type law enforced: new E0737 +
per-error doc + blessed golden. Five honest spanned LowerErrors, each
naming its closing slice (message codec/patterns = MA4, sender = MA3c-3,
state = MA3c-2, return shapes). No ISA growth — floor_isa.rs pinned at 22
untouched; send still does not lower (send_pending green).

Gate: corpus/receive_dispatch + receive_dispatch_run.rs (LC7 synthetic
precedent through the REAL front-end + hoisting path): tag 0 receive<Int>
19→21, tag 1 receive<Cmd> word 1→Snd's 21 → exit 42 exact in the container
(5 032 B, nm -u empty; swapped handlers cannot reproduce 42), + the
ordinary-run-path compile, + three fixtures pinning the sender/codec/state
errors live. RUNTIME_TESTED.

Gates: fmt clean, clippy -D warnings 0, cargo test --workspace 0 Rust
failures (the three in-container FAILED lines are the deliberate CkLang
fixtures), architecture gates hold with no cap raised.
State layout law: one word per field at bytes 16, 24, … (declaration
order) — the first carve of the actor's arena by construction; the
spawn-side wrapper reserves by writing the cursor to 16 + 8n, and the
cursor after init IS the post-state watermark 2b resets to (recorded in
docs/impl/memory-model/arenas.md). Spawn reaches the region via
Load(ArenaSlot) (the FS5 retarget's read), receive via its first ABI word
(MA3c-1's state_region, now genuinely read) — one offset law, no new
intrinsic, floor_isa.rs pinned at 22 untouched.

with mut lands end to end for the state-field target: mut is a hard
keyword, WithMutExpr parses at with's binding power, ExprKind::WithMut,
declared-type checking (E0702 reused), Store lowering; every other target
= honest LowerError::WithMutTarget. Bare = stays E0036, fixture-pinned.
Internal state reads type at declared types (ck_types::actor_state_seeds);
external reads off references stay the MA2c gap. New honest errors:
StateWidth, StateDefault (both naming MA4's codec).

Gates: actor_state_run.rs (6 tests) + corpus/actor_state — the probe
dispatches the same handler TWICE over one region: exit 42 exact (stale
read gives 38; offset swap shifts differently), watermark 32 asserted,
9 512 B; the ordinary actor path runs the spawn-write/read/raise-unless
proof → exit 0, 10 232 B, nm -u empty. fmt clean, clippy -D warnings 0,
cargo test --workspace 1210 passed 0 failed (three deliberate in-container
CkLang FAILs), architecture gates 4/4 (one justified R4 entry:
synth_uncached). trap delta: route/Parser.ck only (the mut keyword
re-cascade), reconciled strict both ways.
100% CkLang over the landed floor, zero compiler changes (floor_isa.rs
untouched at 22): byte-per-flag over a 1 MB os_acquire region,
load/store::<U8>, exact-honest while<N> bounds (999 factor walk / 499999
strike walk / 999999 count walk — bound == computed worst-case trip
count), no division anywhere, zero allocations inside loops (one 64-byte
scratch region holds the memory-held cursors). Exit chain: count 78498 =
pi(10^6), largest prime 999983 unmarked, composite 999981 marked, 2/4 spot
checks -> exit 42; mutated-count discriminator observed exiting 1.

Measured: exit 42 in the container, 9 560 B freestanding (nm -u empty, no
NEEDED), ~4.9 ms per full sieve pass (200 spawns in 0.97 s wall). Gate:
primes_run.rs, RUNTIME_TESTED.

README.md ships the ratchet-ordered performance roadmap toward a Primes
drag-race entry: measure-first harness -> bit-ops machine-op leaves ->
guard elision BY PROOF (the for-literal-range precedent) -> U64 strides ->
per-core actor segments -> optionally a thicker second Floor-core backend;
each step named with the lock it must not weaken; bits=8 category call.

Gates: fmt clean, clippy -D warnings 0, cargo test --workspace 1211 passed
0 failed (three deliberate in-container CkLang FAILs).
mdoorn manually merged commit 1b282ae692 into master 2026-03-10 08:30:00 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
northgale/cklang-bootstrap!55
No description provided.