starkernel: item 3.7 -- per-VM free lists (Phase 3 core complete, for real)
Punch list §25 item 3.7 complete. Added to §25.4 after starting item 4.1 surfaced it as an unbuilt prerequisite -- 3.6's earlier "Phase 3 core complete" claim is corrected in this same commit. StadiumVMQuota table (size STADIUM_MAX_VM_COUNT, linearly searched by vm_id -- capsule_birth.c's vm_id is monotonic and never reused, so it cannot index a table directly, and a 4-entry scan costs nothing). New per-cell stadium_owner byte array records which quota a cell belongs to, needed so eviction returns a freed cell to the correct VM's list and so eviction search stays scoped to the evicting VM's own residents (quota isolation). Free-list linkage reuses each cell's `link` field as a next-free pointer while unresident -- link is documented only as generic "index into the Stadium, not a pointer," so this is a repurposing, not a header change. Does not answer the separate, still-open question of which field carries a multi-cell patron's first continuation-cell index; item 3.5's mass != 1 refusal stands exactly as it was. Boot-time: every cell chained into one list in ascending index order, granted whole to vm_id 0 (Hera), the only VM that exists. Ascending order preserves item 3.6's "Hera is patron zero" invariant once real birth-wiring lands. stadium_admit()'s signature changed to take vm_id -- a change to code shipped in item 3.5, amended there. Pops the calling VM's free-list head first (O(1)); only falls back to a same-VM-scoped eviction search if empty. Caught a real bug before the boot run: the header zero-fill on eviction (and the initial free-list build) both left contains == 0, but 0 is Hera's valid index -- the same collision item 3.1's STADIUM_CONTAINS_NONE fix addressed, recurring at a new site. Fixed by explicitly setting contains = STADIUM_CONTAINS_NONE at both free-list sites. Explicitly out of scope, reported not invented: granting quota to any VM other than Hera is capacity arbitration (item 1.3 left "how much moves per transfer" open). stadium_owner is set once at boot and never rewritten, so quota_slot_for_vm() refuses every vm_id != 0 permanently until item 4.2 adds the grant path and owner-array writes. Verified: three-architecture boot (amd64, aarch64, riscv64), all reaching ok> with identical dict_hash=0x3d4e1daf289da94f matching the item-3.6 baseline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
72487e7fff
commit
e55111c2c5
@@ -2855,6 +2855,13 @@ document and committing that amendment as its own item.*
|
||||
> `dict_hash=0x3d4e1daf289da94f`, matching the item-3.4 baseline — amd64
|
||||
> (`logs/20260804-172516`), aarch64 (`logs/20260804-172556`), riscv64
|
||||
> (`logs/20260804-172651`).
|
||||
>
|
||||
> **Amended by item 3.7, 2026-08-04, same day.** `stadium_admit()`'s signature changed —
|
||||
> it now takes a `vm_id` parameter and scopes both free-cell placement and eviction-search
|
||||
> to that VM's own quota, per §22.3's per-VM free lists (built in 3.7, not this item). The
|
||||
> two full-array O(N) scans this item shipped are gone in the O(1)-free-list-pop common
|
||||
> case; the "not fixed, minor" note above about them is superseded. The `mass != 1`
|
||||
> refusal and the pin/contains logic described above are otherwise unchanged.
|
||||
- [x] **3.6 — Hera as patron zero, pinned.** Assert at the eviction site; selecting Hera is
|
||||
a panic, not a filtered candidate. *Refs:* §20.5 #3.
|
||||
|
||||
@@ -2889,11 +2896,74 @@ document and committing that amendment as its own item.*
|
||||
> (`logs/20260804-173311`), aarch64 (`logs/20260804-173350`), riscv64
|
||||
> (`logs/20260804-173446`).
|
||||
>
|
||||
> **Phase 3 core complete.** Items 3.1–3.6 close out §25.4. The Stadium has a validated
|
||||
> 64-byte cell, boot-time allocation sized from a real memory query, a closed
|
||||
> compiler-enforced behaviour set, density as a read, admission/eviction with the mass and
|
||||
> Hera invariants both enforced, and nothing yet calling any of it — Phase 4 (§25.5) is
|
||||
> where real patron kinds (words first, per item 4.1) start migrating onto it.
|
||||
> **Correction, 2026-08-04, same day:** the line originally here claimed "Phase 3 core
|
||||
> complete" with items 3.1–3.6. That was premature — starting work on item 4.1 surfaced
|
||||
> that its own prerequisite (the per-VM free lists §22.3 describes) doesn't exist yet.
|
||||
> §25.4 gained a seventh item, 3.7, below. Phase 3 core is not complete until it is.
|
||||
|
||||
- [x] **3.7 — Per-VM free lists.** Each VM holds its own free-list head index into the
|
||||
global array (§22.3); cells are drawn by popping that head, granted by Hera. Added
|
||||
2026-08-04 after starting item 4.1 surfaced this as an unbuilt prerequisite — see item
|
||||
3.6's correction note above. *Refs:* §22.3.
|
||||
|
||||
> **DONE 2026-08-04.** `StadiumVMQuota` table (`stadium.c`, size `STADIUM_MAX_VM_COUNT`,
|
||||
> linearly searched by `vm_id`): `capsule_birth.c`'s `vm_id` is monotonic and never reused
|
||||
> (`next_vm_id` only increments, even across VM death — verified by reading, not assumed),
|
||||
> so it cannot index a table directly; a linear scan over 4 entries costs nothing.
|
||||
>
|
||||
> A new per-cell `stadium_owner` byte array (one byte per cell, same pattern as item 3.1's
|
||||
> discriminator bitmap) records which quota slot a cell belongs to — needed because
|
||||
> eviction must return a freed cell to the *correct* VM's list, and because eviction's
|
||||
> least-dense search must stay scoped to the evicting VM's own residents (quota
|
||||
> isolation: one VM's admission can never evict another VM's patron). A compile-time check
|
||||
> (`STADIUM_MAX_VM_COUNT <= 255`) confirms the quota-slot index fits the byte.
|
||||
>
|
||||
> Free-list linkage reuses each cell's own `link` field as a "next free cell" pointer while
|
||||
> unresident — `link` is documented only as generic "index into the Stadium, not a
|
||||
> pointer," so this is a repurposing of already-permitted, previously-unspecified storage,
|
||||
> not a header change. It does **not** answer the separate, still-open question of which
|
||||
> field would carry a multi-cell patron's first continuation-cell index — item 3.5's
|
||||
> `mass != 1` refusal stands exactly as it was.
|
||||
>
|
||||
> At `stadium_boot_init()`, every cell is chained into one list in ascending index order
|
||||
> and granted in full to `vm_id` 0 (Hera) — the only VM that exists (item 0.1). Ascending
|
||||
> order guarantees the first-ever pop returns cell 0, preserving item 3.6's "Hera is patron
|
||||
> zero" invariant once real birth-wiring calls `stadium_admit()`.
|
||||
>
|
||||
> `stadium_admit()`'s signature changed to `stadium_admit(vm_id, candidate)` — a change to
|
||||
> code shipped in item 3.5, amended there (see above). Pops the calling VM's free-list
|
||||
> head first (O(1)); only falls back to a same-VM-scoped eviction search if that list is
|
||||
> empty.
|
||||
>
|
||||
> **A real bug caught before the boot run, by a second review pass:** the zero-fill that
|
||||
> clears a header on eviction (and the initial free-list build) both leave `contains == 0`
|
||||
> — but 0 is Hera's valid index (item 3.1's earlier `STADIUM_CONTAINS_NONE` fix was about
|
||||
> exactly this collision), so every cell on a free list was silently readable as "contains
|
||||
> Hera." Fixed by explicitly setting `contains = STADIUM_CONTAINS_NONE` at both sites
|
||||
> (the boot-time chain-build loop, and `stadium_evict()`'s free-list-return step) rather
|
||||
> than leaving it to the zero-fill's incidental value.
|
||||
>
|
||||
> **Explicitly out of scope, reported not invented:**
|
||||
> - Granting quota to any VM other than Hera, and transferring capacity between VMs, is
|
||||
> capacity *arbitration* — item 1.3 left "how much capacity moves per eligible transfer"
|
||||
> explicitly open, so this item does not invent it. Only the boot-time all-to-Hera grant
|
||||
> exists; `stadium_owner` is set once at boot and never written again, so
|
||||
> `quota_slot_for_vm()` returns refusal for every `vm_id != 0`, permanently, until
|
||||
> something else writes to it. Item 4.2 ("Hermes native on the Stadium") will need both
|
||||
> the grant path and the owner-array writes — flagging now so it isn't a surprise there.
|
||||
> - Multi-cell continuation-chain attachment remains unresolved (see above); item 3.5's
|
||||
> refusal is untouched.
|
||||
>
|
||||
> **Unexercised at runtime,** same as items 3.4–3.6: nothing calls `stadium_admit()` or
|
||||
> `stadium_evict()` yet. The free-list pop path, the quota-scoped eviction fallback, and
|
||||
> the boot-time chain-build are all unexercised against real data.
|
||||
>
|
||||
> **Regression: clean.** All three architectures boot to `ok>` with identical
|
||||
> `dict_hash=0x3d4e1daf289da94f`, matching the item-3.6 baseline, and the `Stadium: N
|
||||
> cells (M KB)` boot line is unaffected in format — amd64 (`logs/20260804-180453`, `74234
|
||||
> cells (4639 KB)`), aarch64 (`logs/20260804-180541`), riscv64 (`logs/20260804-180637`).
|
||||
>
|
||||
> **Phase 3 core complete, for real this time.** Items 3.1–3.7 close out §25.4.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user