starkernel: item 3.1 -- the Stadium cell and header

Punch list §25 item 3.1 complete.

Defines StadiumPatronHeader and StadiumContinuationCell in new
include/starkernel/vm/stadium.h, unioned as StadiumCell per §3's
closed two-valued union. src/starkernel/vm/stadium.c added to
Makefile.starkernel's LOADER_EXTRA_SRCS/KERNEL_EXTRA_SRCS so the
header's compile-time size checks are actually compiled, not merely
included by something that never builds.

Discriminator ruled an external side bitmap (Captain Bob), not a
header field -- amended into §3 and §23.3 before this code was
written. Item 3.1 declares the bitmap's purpose/indexing in a comment
only; allocating it is item 3.2's scope.

Both cell shapes counted for real at exactly 64 bytes with zero
compiler-inserted padding (three C99-portable negative-array-size
assertions -- no _Static_assert, this project targets C99). Header
matches §23.3's original 32+32 split unchanged, since the
discriminator moving outside the cell left nothing to compete for that
space. Continuation cell matches item 1.12's 4+60 figure unchanged for
the same reason.

Verified the size assertion is actually live: broke it to 63,
confirmed the build failed with the expected negative-array-size
error, restored it, confirmed a clean compile.

Verified: three-architecture boot (amd64, aarch64, riscv64), all
reaching ok> with identical dict_hash=0x3d4e1daf289da94f matching the
item-2.2 baseline. Confirmed stadium.o present in both obj/loader/vm
and obj/kernel/vm post-build on amd64, closing the gap the item-2.2 WIP
exposed (an uncompiled header proves nothing).

Left open, not fabricated: §23.4 #2 ("does a typical message fit in
one cell") is unanswerable today -- no message patron struct exists
anywhere in this tree yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-04 14:55:30 -04:00
co-authored by Claude Sonnet 5
parent 05c9eba360
commit d55ec3241b
11 changed files with 31498 additions and 10 deletions
+67 -8
View File
@@ -138,6 +138,16 @@ never reaped and never dispatched — it is floor space, accounted for in its ow
> the Stadium, resolved and ranked exactly as any other patron. `contains` is a reference to
> that residency, not a physical embedding of one patron's cells inside another's. See §8 for
> what this wire is for and why it replaced a lock.
>
> **Amended by item 3.1 (2026-08-04) — the header/continuation discriminator is an
> external side bitmap, not a header field.** A flat-array scan must tell a header cell
> from a continuation cell before it knows which shape it is looking at. That rules out
> folding a tag into either variant's own bytes: a continuation cell has no header fields
> to place one in, and forcing a common leading tag byte into both shapes would eat into
> the continuation cell's usable payload, contradicting §23.3's 60-byte figure. Ruled: one
> bit per cell, in a bitmap kept outside the 64-byte cell array. Item 3.1 declares the
> bitmap's purpose and indexing; item 3.2 (boot-time allocation) allocates it, since it is
> Stadium-sized memory decided at boot alongside the cell array itself.
**The code field is the entire type system.** A block's code field migrates. A message's
delivers. A VM's ticks. The engine never asks what kind of thing it is holding; it
@@ -1899,13 +1909,14 @@ These are numbers to check against a real build, not derived truths.
| Continuation cell | **undetermined** | see below — depends on an unsettled encoding |
The four reserved bytes are deliberate rather than a rounding artefact. The fields above sum
to 28; padding to 32 keeps the header a clean half-cell, leaves room for the
header/continuation discriminator §3 now requires, and gives the `contains` wire item 1.1
resolved to somewhere to live. Whether 4 bytes actually covers `contains` at whatever width
gets chosen (it is an index, the same kind of quantity as `link`, currently sized at 4 bytes
itself) is exactly the kind of thing item 3.1's real byte count settles, not this section —
flagged here rather than assumed. Reserved space in a header that is expected to grow is
cheaper than repacking one later.
to 28; padding to 32 keeps the header a clean half-cell and gives the `contains` wire item
1.1 resolved to somewhere to live — a 4-byte index, the same width as `link`. (The
header/continuation discriminator does not compete for this space: item 3.1 ruled it an
external side bitmap, not a header field — see §3's amendment.) Whether 4 bytes is the
final byte count item 3.1 settles on for `contains`, or whether it can shrink, is exactly
the kind of thing item 3.1's real byte count settles, not this section — flagged here
rather than assumed. Reserved space in a header that is expected to grow is cheaper than
repacking one later.
256 KB per VM is comfortable against QEMU's `-m 1024`, and the outer Stadium's capacity
(§20.5 #1) then follows from how many VMs the machine is willing to host.
@@ -2608,13 +2619,61 @@ document and committing that amendment as its own item.*
*Blocked on Phase 0 complete, and on items 1.11.7 and 1.12.*
- [ ] **3.1 — Cell and header.** Define the entry with all eight wires (§3) — **nine if
- [x] **3.1 — Cell and header.** Define the entry with all eight wires (§3) — **nine if
item 1.1 resolves to a holder index.** Define both members of §3's closed two-valued
union: patron header and continuation cell. Validate the 64-byte cell by counting real
bytes; adjust and record if it does not fit.
**Blocked on:** item 1.1 (may add a wire) and item 1.12 (the continuation-cell encoding —
contiguous or linked — which sets the mass of every large patron and cannot be guessed).
*Refs:* §3, §23.3, §23.4 #4.
> **DONE 2026-08-04.** `StadiumPatronHeader` and `StadiumContinuationCell` defined in the
> new `include/starkernel/vm/stadium.h`, unioned as `StadiumCell`; translation unit
> `src/starkernel/vm/stadium.c` added to `Makefile.starkernel`'s `LOADER_EXTRA_SRCS` /
> `KERNEL_EXTRA_SRCS` so the header actually gets compiled, not merely included by
> something that never builds.
>
> **Discriminator ruling, made before this item's code was written (Captain Bob's call):**
> the header/continuation discriminator is an external side bitmap, one bit per cell, kept
> outside the 64-byte cell array — not a header field. Amended into §3 and §23.3
> accordingly. Item 3.1 declares the bitmap's purpose and indexing contract in a comment;
> it does not allocate it — that is item 3.2's scope, since sizing depends on the memory
> budget item 3.2 works from.
>
> **Byte count, both counted for real, both exactly 64 with zero compiler-inserted
> padding** (verified via three C99-portable negative-array-size assertions, no
> `_Static_assert` — this project targets C99, not C11):
> - `StadiumPatronHeader`: `identity` u64(8) + `heat` u64(8) + `ttl` u32(4) + `link` u32(4)
> + `contains` u32(4) + `mass` u16(2) + `flags` u8(1) + `behaviour` u8(1) +
> `payload` u8[32] = 64. `pin` lives as bit 0 of `flags`, not its own field, matching
> §3/§23.3. Fields ordered largest-to-smallest so every offset is already a multiple of
> its own alignment and the 64-byte total is a multiple of the struct's 8-byte max
> alignment — no padding, without resorting to a `packed` attribute (a GNU extension,
> forbidden by CLAUDE.md's strict-ANSI-C99 rule).
> Because the discriminator moved outside the cell, this matches §23.3's original
> 32-byte-header / 32-byte-inline-payload proposal exactly — no adjustment needed here,
> unlike the continuation cell below.
> - `StadiumContinuationCell`: `next` u32(4) + `payload` u8[60] = 64, unchanged from
> item 1.12's figure — the discriminator living outside the cell means neither variant's
> byte budget was disturbed by it.
>
> **Assertion proven live, not just present:** temporarily changed the header check's
> expected size to 63, recompiled `stadium.c` standalone
> (`cc -std=c99 -Wall -Werror -Wextra -D__STARKERNEL__`), confirmed the build failed with
> `error: size of array 'stadium_header_size_check' is negative`, then restored it and
> confirmed a clean compile.
>
> **Regression: clean, and `stadium.o` confirmed present.** All three architectures boot to
> `ok>` with identical `dict_hash=0x3d4e1daf289da94f`, matching the item-2.2 baseline —
> amd64 (`logs/20260804-145132`), aarch64 (`logs/20260804-145232`), riscv64
> (`logs/20260804-145329`). `find build/<arch> -iname stadium*` confirmed
> `obj/loader/vm/stadium.o` and `obj/kernel/vm/stadium.o` both exist post-build, closing
> the gap the WIP on item 2.2 exposed: a header nothing compiles proves nothing.
>
> **Open, deferred honestly:** §23.4 #2 ("does a typical message still fit in one cell")
> remains unanswered — there is no message patron struct anywhere in this tree yet
> (messages are undesigned future work), so there is nothing concrete to check the 32-byte
> inline payload against. Not fabricated a number to close this; left open.
- [ ] **3.2 — Boot-time allocation.** One global cell array, sized from the memory budget,
before any VM exists. *Refs:* §6, §17.6, §22.3.
- [ ] **3.3 — Behaviour enumeration and dispatch.** Closed tag set fixed at build time.