diff --git a/scheds/rust/scx_cake/STATE.md b/scheds/rust/scx_cake/STATE.md index e4b9ac5b30..78fd1a3a5d 100644 --- a/scheds/rust/scx_cake/STATE.md +++ b/scheds/rust/scx_cake/STATE.md @@ -14,12 +14,14 @@ This file was compacted 2026-08-12 from 30,510 words; everything cut is in that Branch and squash history
-Branch: **`RitzDaCat/scx_cake-nightly`** (pushed to fork). History squashed three +Branch: **`RitzDaCat/scx_cake-nightly`** (pushed to fork). History squashed four times: at `15960cb97` (53 commits → `backup/nightly-53-commits-20260810`), at -`38397bb59` (10 commits → `backup/nightly-10-commits-20260817`), and at this commit +`38397bb59` (10 commits → `backup/nightly-10-commits-20260817`), at `c99eb00c7` (12 commits → `backup/nightly-12-commits-20260818`, after the 2026-08-18 rebase onto -upstream `ff86d6588`; pre-rebase state in `backup/nightly-pre-rebase-20260818`); all -hashes cited below resolve via those local backup branches. +upstream `ff86d6588`; pre-rebase state in `backup/nightly-pre-rebase-20260818`), and +at this commit (17 commits → `backup/nightly-17-commits-20260819`: the R.28 arc — +1.1.3 wallclock campaign, mode-flip root cause, per-task geometry, veto bisect, +live WoW confirm); all hashes cited below resolve via those local backup branches. @@ -41,6 +43,15 @@ hashes cited below resolve via those local backup branches. | 10 | **G25** steal-ring bitmask | **LANDED**, verifier accepted, attach smoke passed 2026-08-08 | wake latency on HD2 render roles + P4 bench screen. Prediction on record: ~0.04% of a core quiet, 4.7% invalidated — **expected frame effect near zero; a null confirms the pricing** | | 11 | **G23** per-line IRQ-sink detection + mask avoidance | built, smoke PASSED, **endpoint unmeasured** | HD2 ABBA during ACTIVE play (P2 needs live mouse input) on `Window & Input` / `main` / `renderer` mean wake + severe-frame screen, then P4 `--blocks 2` bench screen. Receipts + steps: `docs/REVIEW_G21_G23_2026-08-02.md` §resume | +**EXP S.1-1ms (2026-08-19): ❌ FALSIFIED.** Hypothesis was: nightly's extreme-tail loss +vs shipped 1.1.3 (mutex-handoff p999 −37% 6/6; `runs/adhoc_wallclock_113_vs_nightly_20260819`) +is SLICE_NS geometry. Probe SLICE_NS 3000→1000 µs (`092ada871`), 6-slot ABCCBA +(1.1.3 / 3 ms / 1 ms): p999 2.53→2.70 µs (both ~2× 1.1.3's stable 1.36), p99 1.20→**1.85** +(1 ms actively worse), schbench-saturated −18% worse; throughput flat ±4%. Reverted +byte-identical `3df90d103` (39d784f3). Secondary find: 1.1.3's handoff tail is IDENTICAL +across suites (0.85/1.36 µs) while nightly's drifted (p99 0.85→1.20 same code) — the +nightly tail is regime-sensitive, the 1.1.3 tail is not. The gap is structural, not quantum. + **Also open, no owner:** the serial-handoff trade (fires 0.01–0.03% in game regimes — games-only maintainer call). G25 leftovers: contended regime needs re-pricing with a **15-reload** arm (128 B stride reversal ledgered as G25.1). @@ -126,10 +137,27 @@ is smallest. 6. **`ops.enqueue` reaches 0.142% of a game's dispatches** (vs 23.6% saturated). Every enqueue-side routing decision is nearly inert on games; leverage is on the direct path in `cake_select_cpu`, which serves 99.86%. -7. **Third arm blocked** — shipped 1.1.3 builds but does not attach on kernel 7.1.5 - (`map 'cake_ops': BPF map skeleton link is uninitialized`, libbpf/struct_ops skew). - (Recorded on 7.1.5; host now on 7.1.8 post-rebase — re-test attach of the shipped - 1.1.3 binary before citing this gap.) +7. **Third arm UNBLOCKED 2026-08-19** — shipped 1.1.3 (`/usr/bin/scx_cake`, sha256 + `56f9e886…`) attaches and runs clean on 7.1.8; the libbpf skeleton warning still + prints but is non-fatal. First read: quick wallclock ABBA vs nightly HEAD + (diagnostic tier, `scx_cake_bench_assets/runs/adhoc_wallclock_113_vs_nightly_20260819/`): + nightly pipe **−16.0%**, memcpy −3.9%, but sched-messaging **+70.5%** (4/4, no + overlap) — the many-to-many handoff shape regressed vs 1.1.3 and is unscored at + the sealed tier. n=10 confirm (suite 4, 5×ABBA): schbench-light req p99 **+72% + 10/10** (S sd 7 µs, N sd 459), mutex-handoff p999 **2.0× 10/10** (S sd 0.024 µs), + p99 **BIMODAL** (4/10 runs match 1.1.3 exactly, 6/10 at 1.2–1.9 µs), pipe −9.7% + win 10/10. Slice dose falsified (EXP S.1-1ms). **MODE SWITCH ROOT-CAUSED 2026-08-19 + (`mode_probe/` in the run dir): it is `cake_frame_slice_ns`.** Placement exonerated + (24 runs, pair co-resident on CPU 11 in BOTH modes, sinks 0%). Dose-response with an + injected 1 kHz sleep-majority crowd, `--verbose` clock log as ground truth: crowd + binds in one poll (950.8 Hz published) → p99 1.8–2.1; crowd off → 3-poll re-publish + + ~16 s floor climb → p99 decays to 0.90. A **374.9 Hz desktop voter holds slice at + 2 ms** on this host even quiet — nightly never runs at the 3 ms cap on a live + desktop. 1.1.3 has no frame clock (constant geometry) — hence its sd ≈ 0. Mechanism: + any fast desktop crowd tightens patience windows (shifts of `cake_frame_slice_ns`, + §S.2) for EVERY task; the same-CPU handoff tail pays for it. The registered fix is + already on the board: §G12 KEYSTONE re-base of `FRAME_*_SHIFT` windows onto the + occupant's OWN period decouples bystander tasks from the global clock. 8. **Receipts audit** — 5 load-bearing claims (deletion-queue zeros, 1464 ns, SLICE_NS dose, §R.17 +28-36%, G17/G21 wins); list + rationale: `REVIEW_INDEPENDENT_2026-08-17.md` Addendum (git history). @@ -157,10 +185,11 @@ is smallest. | `edafb27e5` + `d56ad5131` | **G25** — steal-ring queue hint becomes a u64 bitmask (41 insns, 10 branches, 0 spills; rotate+`ctz` design measured and REJECTED, do not restore) | | `3fb89cf05` (`6471262e1`, `b607264ad`) | **R.24** cross-multiplied divide elimination in `cake_frame_observe` + handoff-yields; both exact-pairs pass, kept | -Static budget at tip: **11 divides** (re-counted 2026-08-17). Spills at tip per -`bench/fnspills.py` (re-measured 2026-08-18): `select_cpu` 4/1, `enqueue` 2/4, -`stopping` 1/1, `ring_steal` 1/1, `dispatch`/`running` 0/0; TOTAL 17/11/28. (The -script was BLIND on llvm-objdump 22 until `18581c73c` fixed the regex — any +Static budget at tip: **5 divides** (re-counted 2026-08-19 post-§R.28; was 11 — +`cake_task_slice` became one subprogram, and fixed windows replaced bss loads). +Spills at tip per `bench/fnspills.py` (2026-08-19): `select_cpu` 4/1, `enqueue` +2/4, `stopping` 1/1, `ring_steal` 1/1, `dispatch`/`running` 0/0; TOTAL 16/10/26. +(The script was BLIND on llvm-objdump 22 until `18581c73c` fixed the regex — any zero-spill claim made before it is vacuous.) --- @@ -294,6 +323,7 @@ real session), live replica (loader logic run standalone on the live host), audi | G36 | tick look-ahead: skip a CPU whose timer fires within the hop horizon (§G36) | STATIC | **BUILT; unmeasured** | `cake_cpu_tick_soon` **28 insns, 0 spills**; enqueue spills 2/4, TOTAL 17/11/28; desktop smoke expects timer-race hits → ~0 | | R.24 | cross-multiplied divide elimination in `cake_frame_observe` + handoff-yields (§R.24) | bench exact-pair | ✅ **kept** | both exact-pairs pass | | R.27 | shaped compat ladders for ≤ 6.18 kernels (§R.27) | STATIC + CI | ✅ **CI veristat green ×6** (6.13/6.16/6.18/rolling/for-next/bpf-next, run 32206840388, 2026-08-18) | spills 28 → 26, hot frames flat (`select_cpu` 5, `enqueue` 6); +141 insns of dead arms, pruned at load; dev-kernel bench screen still owed | +| **R.28** | per-task slice cap, fixed patience windows, frame clock demoted to diagnostic (§R.28) | bench dose + n=3 ABBA | ✅ **clock mode mechanism REMOVED; tail gap partially remains; game screen owed** | quiet handoff p99 rests 0.86–0.92 (was 0.85–1.9 drifting); divides 11→5, spills 17/11→16/10; p999 2× + schbench-light +72% vs 1.1.3 persist → IRQ-reactive stack (§G33/§G35/§G36) is the standing suspect | | — | spread placement, co-location returns off (§R.1 fps A/B) | FRAME | **reverted byte-identical (7826cfe3a; hashes now in backup/nightly-12-commits-20260818)** | fps INCONCLUSIVE: scene drift **~7%/h** (nvidia **5044 → 4695/s**) dominated every arm; placement stayed concentrated on ~7 CPUs with all three co-location returns off | ### The frame result (2026-08-01, the campaign's first) @@ -398,7 +428,7 @@ to a heading here.** - **B2 OPEN** — a home-routed wake onto a busy CPU with no idle gets **no kick**; ~0 kills it. - **B3 OPEN** — vtime seals, but the frontier advances only in `cake_running`; wall-rate tracking kills it. - **B4 OPEN** — no `.tick`, a multiplier on B2/B3. -- **B5 OPEN** — 1.1.3 is neither fix nor control, and no longer attaches. +- **B5 OPEN** — 1.1.3 is neither fix nor control; attaches again on 7.1.8 (2026-08-19), so it is usable as a third arm. - **B6 OPEN** — lost zero-spill discipline cannot explain 10-40 ms stalls. ### §G6. The spill law as a proxy @@ -1148,6 +1178,47 @@ makes ≤ 6.18 verify; steps — port 5 `cpu_curr` + 3 `peek` + insert family + hot spills flat; abort — any hot-frame spill regression, or a fallback that changes scheduling behavior on the dev kernel. +#### §R.28 — geometry decoupled from the shared clock (2026-08-19) +The frame clock was the GEOMETRY UNIT: every patience window a shift of +`cake_frame_slice_ns`, so one fast desktop crowd (a 374.9 Hz voter, the mouse at +1 kHz) tightened every task's windows — measured as the 2× handoff-tail mode flip +(`mode_probe/` in the 2026-08-19 run dir). Now: slice cap = half the task's OWN +cycle (`cake_period_ns`, the §G12 KEYSTONE twin divide); occupant-protection and +young-occupant windows = FIXED slice fractions — a per-occupant-period version +inverted semantics for fast occupants (window ~44 ns ⇒ the handoff kick never +fired, p99 2.1) and was reverted same-session; all vtime windows = fixed SLICE_NS. +The clock publishes for --verbose only; §G27's easy-scene endpoint is superseded by +per-task geometry. Object: spills 17/11 → 16/10, divides 11 → **5** (`cake_task_slice` +consolidated to one subprogram). Verdict: quiet handoff p99 rests at 0.86–0.92 +(was 0.85–1.9 drifting) and the clock dose is gone, but **p999 2× and +schbench-light +72% persist** — with the crowd control (1.1.3 +0.05 µs vs nightly ++0.9 under 8×1 kHz hrtimer load) the standing suspect is the IRQ-reactive stack +(§G33/§G35/§G36; schbench is pure timer pressure and 1.1.3 ignores IRQs). GAME +SCREEN OWED before keep (GAME-FIRST). + +**Bisect 2026-08-19 (4 probe commits, all reverted byte-identical to `0d345ed2…`):** +all-vetoes-off closes EVERYTHING — quiet handoff p99 **0.80** (beats 1.1.3's 0.855), +crowd-immune (0.79 under 8×1 kHz), schbench-light **2548** ≈ 1.1.3's 2540, pipe +2.015 s (best of day). Single-feature-on runs, each independently harmful: +**§G36** tick veto → handoff drift 0.84→1.35 + crowd sensitivity (schbench 2964); +**§G35** live bit → quiet p999 2.7, crowd p999 **4.7**, schbench 3796; +**§G33** chronic sinks → schbench **4472, the full +72% alone**, handoff clean. +Their wake-tier game wins (G21 −39.9% main wake, G30 fence tail, G35 staircase) +stand — this is a GAMES-VS-BENCH TRADE, maintainer's call, no deletion on bench +data. Design cut for the next arc: each veto fires on SIGNAL PRESENCE with no +cost comparison against the alternative placement (claiming a briefly-loud CPU +usually beats queueing) — the §R.26 lens, binary thresholds discarding data. + +**Live WoW ABBA closes the trade 2026-08-19 (`wow-vetoAB-s{1..4}` in +`history/wake_latency/`, `--irq`, 22 s slots, active play): the vetoes EARN +THEIR KEEP IN-GAME, 2/2 no overlap on every role.** With vetoes vs all-off: +fence p99 **23–27 → 48 µs**, vkd3d_queue p95 **7.4 → 28–33** (4×), WoW.exe main +p95 14 → 30–32, ThreadPool High p50 **0.86 → 5.0 µs** (6×), same-CPU wakes +86% → 31%. VERDICT under GAME-FIRST: vetoes STAY; the bench/desktop tail cost +(schbench-light +72%, handoff p999 2× vs 1.1.3) is the accepted price, and the +weighed-veto refinement is the registered path to buying both. MangoHud was not +injected — frame screen still owed; wake tier only. + --- ### §S — Constant ledger (from `intf.h`) diff --git a/scheds/rust/scx_cake/src/bpf/cake.bpf.c b/scheds/rust/scx_cake/src/bpf/cake.bpf.c index 60a0b3a63f..978f3eca35 100644 --- a/scheds/rust/scx_cake/src/bpf/cake.bpf.c +++ b/scheds/rust/scx_cake/src/bpf/cake.bpf.c @@ -155,17 +155,17 @@ const volatile u64 cake_handoff_max_ns = 1464; u64 cake_frame_ns __attribute__((aligned(STATE_SLOT_BYTES))); /* - * The same estimate filtered PESSIMISTICALLY: a cap must never widen because - * the estimator wobbled (§G18). + * The same estimate filtered PESSIMISTICALLY (§G18). Diagnostic only: no + * policy consumes it (§R.28). */ u64 cake_frame_floor_ns __attribute__((aligned(STATE_SLOT_BYTES))); /* - * The GEOMETRY UNIT: every patience window (sleeper lag, wake hysteresis, - * preempt margins) is a shift of this, not of the fixed grant. Loader publishes - * min(3/4 x frame floor, SLICE_NS): a display-coupled regime tightens the - * geometry with its engine cadence; a vote-free regime keeps the slice exactly, - * so benches are unchanged by construction (§G27). + * DIAGNOSTIC ONLY: the loader still publishes min(3/4 x frame floor, + * SLICE_NS) for the --verbose clock line, but no policy consumes it. + * As the shared geometry unit it let one fast desktop crowd tighten every + * task's patience windows — measured as a 2x handoff-tail mode flip. + * Geometry is per task now (§R.28). */ u64 cake_frame_slice_ns __attribute__((aligned(STATE_SLOT_BYTES))); @@ -195,6 +195,18 @@ static __always_inline u64 cake_burst_ns(const struct task_struct *p) return p->se.sum_exec_runtime / (p->nvcsw | 1); } +/* + * This task's mean CYCLE: lifetime per voluntary switch, cake_burst_ns's + * wall-axis twin (§G12). Clamped to the fixed slice so a task that rarely + * yields is bounded as compute, not trusted forever (§R.28). + */ +static __always_inline u64 cake_period_ns(const struct task_struct *p) +{ + u64 per = (bpf_ktime_get_ns() - p->start_time) / (p->nvcsw | 1); + + return per > SLICE_NS ? SLICE_NS : per; +} + /* * Does this task wait longer than it runs? run_delay is the kernel's lifetime * runnable-but-not-running total and pcount its dispatch count, so @@ -576,13 +588,14 @@ static __noinline u64 cake_occupant_live(s32 tcpu, u64 *ran_out) * RT/DL or idle, which we neither can nor need preempt. §R.1. */ static __noinline bool cake_wake_preempt(struct task_struct *p, s32 tcpu, - u64 min_ran) + u32 protect_shift) { u64 ran = 0; u64 live = cake_occupant_live(tcpu, &ran); struct task_struct *curr; - if (!live || ran < min_ran || !time_before(p->scx.dsq_vtime, live)) + if (!live || ran < (u64)SLICE_NS >> protect_shift || + !time_before(p->scx.dsq_vtime, live)) return false; /* @@ -662,20 +675,20 @@ static __noinline bool cake_handoff_yields(s32 tcpu) /* - * The slice this task needs: twice its own burst, floored at the chain - * boundary, capped at half a frame -- taken from the PESSIMISTIC frame - * estimate, since a bound must not widen when the estimator wobbles. The grant - * is a PREEMPTION TIMER, not a vtime question (§G10.4, §G11.5, §G18). + * The slice this task needs: twice its own burst, capped at half its OWN + * cycle -- a task must not hold a CPU past its next wake -- floored at the + * handoff cost. The grant is a PREEMPTION TIMER, not a vtime question + * (§G10.4, §G18, §R.28). */ -static __always_inline u64 cake_task_slice(const struct task_struct *p) +static __noinline u64 cake_task_slice(struct task_struct *p __arg_trusted) { u64 want = cake_burst_ns(p) << 1; - u64 cap = cake_frame_floor_ns >> FRAME_SLICE_CAP_SHIFT; + u64 cap = cake_period_ns(p) >> PERIOD_SLICE_CAP_SHIFT; - if (want < cake_handoff_max_ns) - want = cake_handoff_max_ns; if (want > cap) want = cap; + if (want < cake_handoff_max_ns) + want = cake_handoff_max_ns; return want; } @@ -697,7 +710,7 @@ static __always_inline u64 cake_sleeper_dose(u64 unused) static __always_inline u64 cake_cadence_depth(const struct task_struct *p) { u64 burst = cake_burst_ns(p); - u64 vs = cake_frame_slice_ns; + u64 vs = SLICE_NS; if (!cake_starved(p) || burst >= vs) return 0; @@ -712,7 +725,7 @@ static __always_inline u64 cake_cadence_depth(const struct task_struct *p) */ static __noinline u64 cake_wake_vtime(const struct task_struct *p) { - u64 lo = cake.frontier.word - cake_frame_slice_ns - cake_cadence_depth(p); + u64 lo = cake.frontier.word - SLICE_NS - cake_cadence_depth(p); u64 d = p->scx.dsq_vtime - lo; return lo + (d & ~((u64)((s64)d >> 63))); @@ -729,14 +742,12 @@ static __noinline bool cake_home_notify(struct task_struct *p, s32 tcpu) { u64 ran = 0; u64 live = cake_occupant_live(tcpu, &ran); - u64 vs; if (!live) return (u32)tcpu == bpf_get_smp_processor_id(); - vs = cake_frame_slice_ns; - if (ran >= (vs >> 5) || - !time_before(p->scx.dsq_vtime + (vs >> 1) - + if (ran >= ((u64)SLICE_NS >> 5) || + !time_before(p->scx.dsq_vtime + (SLICE_NS >> 1) - (ran >> HOME_PREEMPT_RAN_CREDIT_SHIFT), live)) return false; @@ -916,7 +927,7 @@ s32 BPF_STRUCT_OPS(cake_select_cpu, struct task_struct *p, s32 prev_cpu, * direct-dispatching keeps live-vtime eligibility (§R.20). */ if ((wake_flags & CAKE_WAKE_SYNC) || - time_before(p->scx.dsq_vtime + (cake_frame_slice_ns >> 1), + time_before(p->scx.dsq_vtime + (SLICE_NS >> 1), cake.frontier.word)) { s32 waker_cpu = (s32)bpf_get_smp_processor_id(); @@ -989,8 +1000,7 @@ __noinline s32 cake_wake_notify(struct task_struct *p __arg_trusted, s32 tcpu, * occupant genuinely deserves it. Cake registers no .tick, so an arm * that decides neither leaves the wakee on the 5 s watchdog (§R.14). */ - if (cake_wake_preempt(p, tcpu, - cake_frame_ns >> FRAME_PREEMPT_PROTECT_SHIFT)) + if (cake_wake_preempt(p, tcpu, PREEMPT_PROTECT_SHIFT)) return 0; /* @@ -1009,8 +1019,7 @@ __noinline s32 cake_wake_notify(struct task_struct *p __arg_trusted, s32 tcpu, if (!bpf_cpumask_test_cpu((s32)cand, p->cpus_ptr)) continue; if (cake_wake_preempt(p, (s32)cand, - cake_frame_ns >> - FRAME_PROBE_PROTECT_SHIFT)) + PROBE_PROTECT_SHIFT)) break; } } @@ -1030,7 +1039,7 @@ __noinline s32 cake_wake_notify(struct task_struct *p __arg_trusted, s32 tcpu, static __noinline bool cake_home_claim(struct task_struct *p __arg_trusted, s32 tcpu) { - u64 vs = cake_frame_slice_ns; + u64 vs = SLICE_NS; u64 lo = cake.frontier.word - vs; u64 ran = 0, live; @@ -1135,7 +1144,7 @@ static __noinline void cake_pinned_wake_preempt(struct task_struct *p __arg_trus if (!clive) return; - vs = cake_frame_slice_ns; + vs = SLICE_NS; lo = cake.frontier.word - vs; dd = d + vs; pvt = lo - vs + (dd & ~((u64)((s64)dd >> 63))); @@ -1191,7 +1200,7 @@ void BPF_STRUCT_OPS(cake_enqueue, struct task_struct *p, u64 enq_flags) * Only the continuation arm consumes it; the wake arm derives its own * cadence-deep floor (§R.13). */ - lo = cake.frontier.word - cake_frame_slice_ns; + lo = cake.frontier.word - SLICE_NS; d = p->scx.dsq_vtime - lo; /* @@ -1364,7 +1373,7 @@ static __noinline bool cake_dispatch_search(s32 cpu) * served that queue in a wall-clock window (§R.16, §G11.2). */ if (!own || - time_before(wv + cake_frame_slice_ns, + time_before(wv + SLICE_NS, own->scx.dsq_vtime) || cake_wake_starved()) { first = (u64)WAKE_DSQ; diff --git a/scheds/rust/scx_cake/src/bpf/intf.h b/scheds/rust/scx_cake/src/bpf/intf.h index 7f12c7d951..3b748d9ed2 100644 --- a/scheds/rust/scx_cake/src/bpf/intf.h +++ b/scheds/rust/scx_cake/src/bpf/intf.h @@ -42,13 +42,16 @@ enum consts { /* The slice every task gets. Dose-responsed U-curve minimum (§S.1). */ SLICE_NS = 3000 * NSEC_PER_USEC, - /* Patience windows are shifts of cake_frame_slice_ns (§S.2, §G27). */ + /* Vtime credit for time an occupant already ran (§S.2). */ HOME_PREEMPT_RAN_CREDIT_SHIFT = 1, - /* Occupant protection as a fraction of a FRAME (§G11.4). */ - FRAME_PREEMPT_PROTECT_SHIFT = 4, - FRAME_PROBE_PROTECT_SHIFT = 2, - FRAME_SLICE_CAP_SHIFT = 1, + /* Occupant protection: FIXED slice fractions, so only long-running + * compute is ever preempted and no shared clock moves them (§R.28). */ + PREEMPT_PROTECT_SHIFT = 4, + PROBE_PROTECT_SHIFT = 2, + + /* Slice cap: half the task's OWN mean cycle (§G12, §R.28). */ + PERIOD_SLICE_CAP_SHIFT = 1, /* Pre-scale for the wait:run cross-multiply; it cancels (§G12). */ CAKE_RATIO_SHIFT = 16, diff --git a/scheds/rust/scx_cake/src/main.rs b/scheds/rust/scx_cake/src/main.rs index 2e1320c7cd..b190e81c4a 100644 --- a/scheds/rust/scx_cake/src/main.rs +++ b/scheds/rust/scx_cake/src/main.rs @@ -487,8 +487,8 @@ impl<'a> Scheduler<'a> { if let Some(bss) = self.skel.maps.bss_data.as_mut() { bss.cake_frame_ns = period; bss.cake_frame_floor_ns = self.frame_floor; - // Geometry unit: 3/4 of the pessimistic floor, and never looser - // than the fixed slice — display regimes only TIGHTEN it (§G27). + // Diagnostic only: feeds the --verbose clock line; no policy + // consumes these — geometry is per task (§R.28). bss.cake_frame_slice_ns = ((self.frame_floor >> 1) + (self.frame_floor >> 2)) .min(bpf_intf::consts_SLICE_NS as u64); }