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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-04T21:34:30Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-04T22:06:22Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48
|
||||
1,10000,10000,0,0,183,4,45,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
2,20000,10000,0,0,173,5,44,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
3,30000,10000,0,0,184,6,60,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
4,40000,10000,0,0,174,8,71,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
5,50000,10000,0,0,150,9,78,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
6,60000,10000,0,0,159,11,73,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
7,70000,10000,0,0,188,15,71,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
8,80000,10000,0,0,214,16,83,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
9,90000,10000,0,0,216,19,82,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
10,100000,10000,0,0,222,21,84,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
11,110000,10000,0,0,207,23,86,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
12,120000,10000,0,0,189,26,83,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
13,130000,10000,0,0,221,28,80,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
14,140000,10000,0,0,204,29,83,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
15,150000,10000,0,0,203,30,82,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
16,160000,10000,0,0,201,32,83,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
17,170000,10000,0,0,190,34,86,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
18,180000,10000,0,0,170,35,73,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
19,190000,10000,0,0,154,28,44,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
20,200000,10000,0,0,154,28,41,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
21,210000,10000,0,0,153,32,39,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
22,220000,10000,0,0,167,35,42,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
23,230000,10000,0,0,176,37,41,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
24,240000,10000,0,0,175,37,39,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
25,250000,10000,0,0,196,38,37,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
26,260000,10000,0,0,192,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
27,270000,10000,0,0,158,40,38,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
28,280000,10000,0,0,158,40,35,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
29,290000,10000,0,0,164,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
30,300000,10000,0,0,154,43,39,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
31,310000,10000,0,0,172,46,35,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
32,320000,10000,0,0,180,49,34,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
33,330000,10000,0,0,145,51,35,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
34,340000,10000,0,0,203,53,37,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
35,350000,10000,0,0,154,55,39,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
36,360000,10000,0,0,144,57,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
37,370000,10000,0,0,144,57,35,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
38,380000,10000,0,0,132,57,34,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
39,390000,10000,0,0,180,57,32,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
40,400000,10000,0,0,220,63,29,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
41,410000,10000,0,0,215,64,28,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
42,420000,10000,0,0,208,68,29,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
43,430000,10000,0,0,177,72,27,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
44,440000,10000,0,0,199,77,28,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
45,450000,10000,0,0,223,82,26,4096,30,0,0,0,65536,0,0,65536,0,0
|
||||
46,460000,10000,0,0,202,85,24,4096,67,0,0,0,65536,0,0,65536,0,0
|
||||
47,470000,10000,0,0,218,91,25,4096,198,0,0,0,65536,0,0,65536,0,0
|
||||
48,480000,10000,0,0,221,92,26,4096,350,0,0,0,65536,0,0,65536,0,0
|
||||
49,490000,10000,0,0,225,97,26,4096,528,0,0,0,65536,0,0,65536,0,0
|
||||
50,500000,10000,0,0,214,100,27,4096,694,0,0,0,65536,0,0,65536,0,0
|
||||
51,510000,10000,0,0,227,102,28,4096,883,0,0,0,65536,0,0,65536,0,0
|
||||
52,520000,10000,0,0,208,102,29,4096,1043,0,0,0,65536,0,0,65536,0,0
|
||||
53,530000,10000,0,0,207,102,30,4096,1202,0,0,0,65536,0,0,65536,0,0
|
||||
54,540000,10000,0,0,200,102,31,4096,1319,0,0,0,65536,0,0,65536,0,0
|
||||
55,550000,10000,0,0,205,103,32,4096,1464,0,0,0,65536,0,0,65536,0,0
|
||||
56,560000,10000,0,0,211,103,32,4096,1620,0,0,0,65536,0,0,65536,0,0
|
||||
57,570000,10000,0,0,193,110,33,4096,1712,0,0,0,65536,0,0,65536,0,0
|
||||
58,580000,10000,0,0,190,5,67,4096,1775,0,0,0,65536,0,0,65536,0,0
|
||||
|
@@ -0,0 +1,59 @@
|
||||
tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48
|
||||
1,10000,10000,0,0,183,4,45,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
2,20000,10000,0,0,173,5,44,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
3,30000,10000,0,0,184,6,60,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
4,40000,10000,0,0,174,8,71,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
5,50000,10000,0,0,150,9,78,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
6,60000,10000,0,0,159,11,73,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
7,70000,10000,0,0,188,15,71,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
8,80000,10000,0,0,214,16,83,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
9,90000,10000,0,0,216,19,82,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
10,100000,10000,0,0,222,21,84,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
11,110000,10000,0,0,207,23,86,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
12,120000,10000,0,0,189,26,83,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
13,130000,10000,0,0,221,28,80,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
14,140000,10000,0,0,204,29,83,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
15,150000,10000,0,0,203,30,82,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
16,160000,10000,0,0,201,32,83,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
17,170000,10000,0,0,190,34,86,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
18,180000,10000,0,0,170,35,73,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
19,190000,10000,0,0,154,28,44,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
20,200000,10000,0,0,154,28,41,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
21,210000,10000,0,0,153,32,39,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
22,220000,10000,0,0,167,35,42,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
23,230000,10000,0,0,176,37,41,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
24,240000,10000,0,0,175,37,39,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
25,250000,10000,0,0,196,38,37,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
26,260000,10000,0,0,192,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
27,270000,10000,0,0,158,40,38,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
28,280000,10000,0,0,158,40,35,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
29,290000,10000,0,0,164,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
30,300000,10000,0,0,154,43,39,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
31,310000,10000,0,0,172,46,35,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
32,320000,10000,0,0,180,49,34,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
33,330000,10000,0,0,145,51,35,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
34,340000,10000,0,0,203,53,37,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
35,350000,10000,0,0,154,55,39,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
36,360000,10000,0,0,144,57,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
37,370000,10000,0,0,144,57,35,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
38,380000,10000,0,0,132,57,34,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
39,390000,10000,0,0,180,57,32,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
40,400000,10000,0,0,220,63,29,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
41,410000,10000,0,0,215,64,28,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
42,420000,10000,0,0,208,68,29,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
43,430000,10000,0,0,177,72,27,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
44,440000,10000,0,0,199,77,28,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
45,450000,10000,0,0,223,82,26,4096,30,0,0,0,65536,0,0,65536,0,0
|
||||
46,460000,10000,0,0,202,85,24,4096,67,0,0,0,65536,0,0,65536,0,0
|
||||
47,470000,10000,0,0,218,91,25,4096,198,0,0,0,65536,0,0,65536,0,0
|
||||
48,480000,10000,0,0,221,92,26,4096,350,0,0,0,65536,0,0,65536,0,0
|
||||
49,490000,10000,0,0,225,97,26,4096,528,0,0,0,65536,0,0,65536,0,0
|
||||
50,500000,10000,0,0,214,100,27,4096,694,0,0,0,65536,0,0,65536,0,0
|
||||
51,510000,10000,0,0,227,102,28,4096,883,0,0,0,65536,0,0,65536,0,0
|
||||
52,520000,10000,0,0,208,102,29,4096,1043,0,0,0,65536,0,0,65536,0,0
|
||||
53,530000,10000,0,0,207,102,30,4096,1202,0,0,0,65536,0,0,65536,0,0
|
||||
54,540000,10000,0,0,200,102,31,4096,1319,0,0,0,65536,0,0,65536,0,0
|
||||
55,550000,10000,0,0,205,103,32,4096,1464,0,0,0,65536,0,0,65536,0,0
|
||||
56,560000,10000,0,0,211,103,32,4096,1620,0,0,0,65536,0,0,65536,0,0
|
||||
57,570000,10000,0,0,193,110,33,4096,1712,0,0,0,65536,0,0,65536,0,0
|
||||
58,580000,10000,0,0,190,5,67,4096,1775,0,0,0,65536,0,0,65536,0,0
|
||||
|
@@ -0,0 +1,59 @@
|
||||
tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48
|
||||
1,10000,10000,0,0,183,4,45,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
2,20000,10000,0,0,173,5,44,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
3,30000,10000,0,0,184,6,60,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
4,40000,10000,0,0,174,8,71,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
5,50000,10000,0,0,150,9,78,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
6,60000,10000,0,0,159,11,73,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
7,70000,10000,0,0,188,15,71,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
8,80000,10000,0,0,214,16,83,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
9,90000,10000,0,0,216,19,82,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
10,100000,10000,0,0,222,21,84,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
11,110000,10000,0,0,207,23,86,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
12,120000,10000,0,0,189,26,83,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
13,130000,10000,0,0,221,28,80,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
14,140000,10000,0,0,204,29,83,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
15,150000,10000,0,0,203,30,82,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
16,160000,10000,0,0,201,32,83,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
17,170000,10000,0,0,190,34,86,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
18,180000,10000,0,0,170,35,73,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
19,190000,10000,0,0,154,28,44,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
20,200000,10000,0,0,154,28,41,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
21,210000,10000,0,0,153,32,39,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
22,220000,10000,0,0,167,35,42,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
23,230000,10000,0,0,176,37,41,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
24,240000,10000,0,0,175,37,39,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
25,250000,10000,0,0,196,38,37,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
26,260000,10000,0,0,192,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
27,270000,10000,0,0,158,40,38,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
28,280000,10000,0,0,158,40,35,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
29,290000,10000,0,0,164,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
30,300000,10000,0,0,154,43,39,685,685,0,0,0,65536,0,0,65536,0,0
|
||||
31,310000,10000,0,0,172,46,35,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
32,320000,10000,0,0,180,49,34,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
33,330000,10000,0,0,145,51,35,567,567,0,0,0,65536,0,0,65536,0,0
|
||||
34,340000,10000,0,0,203,53,37,582,582,0,0,0,65536,0,0,65536,0,0
|
||||
35,350000,10000,0,0,154,55,39,731,731,0,0,0,65536,0,0,65536,0,0
|
||||
36,360000,10000,0,0,144,57,37,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
37,370000,10000,0,0,144,57,35,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
38,380000,10000,0,0,132,57,34,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
39,390000,10000,0,0,180,57,32,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
40,400000,10000,0,0,220,63,29,4096,0,0,0,0,65536,0,0,65536,0,0
|
||||
41,410000,10000,0,0,215,64,28,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
42,420000,10000,0,0,208,68,29,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
43,430000,10000,0,0,177,72,27,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
44,440000,10000,0,0,199,77,28,4096,24,0,0,0,65536,0,0,65536,0,0
|
||||
45,450000,10000,0,0,223,82,26,4096,30,0,0,0,65536,0,0,65536,0,0
|
||||
46,460000,10000,0,0,202,85,24,4096,67,0,0,0,65536,0,0,65536,0,0
|
||||
47,470000,10000,0,0,218,91,25,4096,198,0,0,0,65536,0,0,65536,0,0
|
||||
48,480000,10000,0,0,221,92,26,4096,350,0,0,0,65536,0,0,65536,0,0
|
||||
49,490000,10000,0,0,225,97,26,4096,528,0,0,0,65536,0,0,65536,0,0
|
||||
50,500000,10000,0,0,214,100,27,4096,694,0,0,0,65536,0,0,65536,0,0
|
||||
51,510000,10000,0,0,227,102,28,4096,883,0,0,0,65536,0,0,65536,0,0
|
||||
52,520000,10000,0,0,208,102,29,4096,1043,0,0,0,65536,0,0,65536,0,0
|
||||
53,530000,10000,0,0,207,102,30,4096,1202,0,0,0,65536,0,0,65536,0,0
|
||||
54,540000,10000,0,0,200,102,31,4096,1319,0,0,0,65536,0,0,65536,0,0
|
||||
55,550000,10000,0,0,205,103,32,4096,1464,0,0,0,65536,0,0,65536,0,0
|
||||
56,560000,10000,0,0,211,103,32,4096,1620,0,0,0,65536,0,0,65536,0,0
|
||||
57,570000,10000,0,0,193,110,33,4096,1712,0,0,0,65536,0,0,65536,0,0
|
||||
58,580000,10000,0,0,190,5,67,4096,1775,0,0,0,65536,0,0,65536,0,0
|
||||
|
@@ -116,6 +116,14 @@ typedef char stadium_cell_size_check[(sizeof(StadiumCell) == STADIUM_CELL_BYTES)
|
||||
typedef char stadium_contains_depth_configured_check[(STADIUM_CONTAINS_DEPTH_MAX > 0) ? 1 : -1];
|
||||
typedef char stadium_capacity_tick_configured_check[(STADIUM_CAPACITY_TICK > 0) ? 1 : -1];
|
||||
|
||||
/*
|
||||
* Item 3.7: the per-cell owner array stores a quota-slot index in a single
|
||||
* uint8_t, so STADIUM_MAX_VM_COUNT must fit in one byte. Default 4, so this
|
||||
* holds by a wide margin -- checked because it is depended on, not because
|
||||
* it is expected to fail.
|
||||
*/
|
||||
typedef char stadium_max_vm_count_fits_owner_byte_check[(STADIUM_MAX_VM_COUNT <= 255) ? 1 : -1];
|
||||
|
||||
/*
|
||||
* stadium_boot_init - Boot-time allocation (FABRIC.md item 3.2, §17.6 position
|
||||
* (b)). Sizes the global cell array from the memory budget actually observed
|
||||
@@ -128,10 +136,21 @@ typedef char stadium_capacity_tick_configured_check[(STADIUM_CAPACITY_TICK > 0)
|
||||
* PMM-backed region needed for this) and explicitly zero-filled, since
|
||||
* kmalloc does not zero.
|
||||
*
|
||||
* (Item 3.7) Also allocates a per-cell owner byte array (which VM's quota a
|
||||
* cell belongs to) and chains every cell into a single free list, in
|
||||
* ascending index order, granted in full to vm_id 0 (Hera) -- the only VM
|
||||
* that exists (item 0.1). Ascending order guarantees the first-ever
|
||||
* admission pops cell 0, preserving item 3.6's "Hera is patron zero"
|
||||
* invariant once real birth-wiring calls stadium_admit() for the first
|
||||
* time. The free-list next-pointer reuses each cell's own `link` field
|
||||
* while unresident -- a repurposing of documented-but-unspecified storage,
|
||||
* not a header change; see stadium_admit()'s doc for why this doesn't
|
||||
* answer the separate, still-open continuation-chain question.
|
||||
*
|
||||
* Must be called after M6 (kmalloc_init) and before any VM is born (§6). Does
|
||||
* not halt boot on failure -- nothing downstream consumes the Stadium yet.
|
||||
*
|
||||
* @return 0 on success, -1 if kmalloc failed for either allocation.
|
||||
* @return 0 on success, -1 if kmalloc failed for any of the three allocations.
|
||||
*/
|
||||
int stadium_boot_init(void);
|
||||
|
||||
@@ -224,7 +243,10 @@ uint64_t stadium_density(size_t cell_index);
|
||||
/*
|
||||
* stadium_evict - Reap the patron header at cell_index (FABRIC.md §17.2:
|
||||
* "reap means leaves the floor, not destroyed"). Dispatches its behaviour
|
||||
* (§18.3), clears its item-3.1 discriminator bit, zeroes its header.
|
||||
* (§18.3), clears its item-3.1 discriminator bit, zeroes its header, and
|
||||
* (item 3.7) returns the freed cell to the free list of whichever VM's
|
||||
* quota it was drawn from -- looked up via the internal per-cell owner
|
||||
* record, not passed by the caller.
|
||||
*
|
||||
* PANICS (does not return) if cell_index == STADIUM_HERA_CELL_INDEX and the
|
||||
* cell is actually resident -- FABRIC.md §20.5 #3: Hera is pinned (§3), but
|
||||
@@ -248,29 +270,53 @@ uint64_t stadium_density(size_t cell_index);
|
||||
int stadium_evict(size_t cell_index);
|
||||
|
||||
/*
|
||||
* stadium_admit - Place a candidate patron header into the Stadium (FABRIC.md
|
||||
* §19.3).
|
||||
* StadiumVMQuota - per-VM ownership of a subset of the global cell array
|
||||
* (FABRIC.md §22.3, item 3.7: "each VM holds its own free-list head index
|
||||
* into the global array"). A small table, 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), so it cannot index this table
|
||||
* directly, and STADIUM_MAX_VM_COUNT is small enough (default 4) that a
|
||||
* linear scan costs nothing. Not exposed outside stadium.c: nothing outside
|
||||
* needs to inspect quota state directly yet.
|
||||
*/
|
||||
|
||||
/* Sentinel meaning "no VM owns this slot yet." Distinct from a real vm_id
|
||||
* (capsule_birth.c reserves 0 for Hera, so 0 cannot double as "unused" here
|
||||
* either -- same shape of mistake STADIUM_CONTAINS_NONE was fixed for). */
|
||||
#define STADIUM_QUOTA_SLOT_EMPTY ((uint32_t)-1)
|
||||
|
||||
/*
|
||||
* stadium_admit - Place a candidate patron header into the Stadium, scoped
|
||||
* to vm_id's quota (FABRIC.md §19.3, §22.3, item 3.7).
|
||||
*
|
||||
* First scans for an unused cell (discriminator bit clear and mass == 0) and
|
||||
* places the candidate there directly -- §19.3's density comparison only
|
||||
* governs the full case, not this one. If none is free, finds the
|
||||
* least-dense resident (discriminator bit set, mass > 0, not pinned, not
|
||||
* `contains`-gated -- pinned and gated residents are never eviction
|
||||
* candidates, per §3 and item 1.1) and evicts it via stadium_evict() only if
|
||||
* the candidate is strictly denser (§19.3: "denser than," not "at least as
|
||||
* dense as"). Otherwise refuses.
|
||||
* Pops vm_id's free-list head first (O(1)) if non-empty. Only if that VM's
|
||||
* free list is exhausted does this fall back to eviction -- scoped to that
|
||||
* SAME VM's own resident patrons only (quota isolation: a VM's admission can
|
||||
* never evict another VM's patron), finding the least-dense evictable
|
||||
* resident (not pinned, not `contains`-gated -- per §3 and item 1.1) and
|
||||
* evicting it via stadium_evict() only if the candidate is strictly denser
|
||||
* (§19.3: "denser than," not "at least as dense as"). Otherwise refuses.
|
||||
*
|
||||
* Does not itself assert anything about which resident this turns out to be
|
||||
* -- the item-3.6 rule that patron zero (Hera) must never actually be
|
||||
* selected is a separate, later check at the eviction site.
|
||||
*
|
||||
* REFUSES if vm_id has no quota granted (only Hera, vm_id 0, has one today
|
||||
* -- granted the entire array at stadium_boot_init(), since she is the only
|
||||
* VM that exists per item 0.1). Granting quota to additional VMs, and
|
||||
* transferring capacity between them, 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.
|
||||
*
|
||||
* REFUSES any candidate with mass != 1. A multi-cell patron (mass > 1, e.g.
|
||||
* §23.3's 1024-byte block at mass 19) needs its continuation chain allocated
|
||||
* too, which needs the per-VM free lists §22.3 describes -- item 3.2's DONE
|
||||
* note already deferred those (not this item's scope, they are granted when
|
||||
* Hera assigns a VM its quota). Admitting only the header and leaking the
|
||||
* rest would break capacity conservation, so this refuses rather than doing
|
||||
* that. Revisit when the free lists exist.
|
||||
* §23.3's 1024-byte block at mass 19) needs a continuation chain, and no
|
||||
* header field is documented anywhere as carrying the index of a patron's
|
||||
* first continuation cell -- `link` is described only as generic "index
|
||||
* into the Stadium, not a pointer." This item repurposes `link` for a
|
||||
* different, non-conflicting use (the free-list next-pointer, while a cell
|
||||
* is unresident -- see stadium.c), but does not invent an answer to the
|
||||
* continuation-chain question, which stays open. Item 3.5's refusal
|
||||
* therefore stands exactly as it was.
|
||||
*
|
||||
* REQUIRES candidate->contains to be either STADIUM_CONTAINS_NONE or a valid
|
||||
* index (< the current cell count) -- refuses otherwise. This does NOT catch
|
||||
@@ -281,14 +327,16 @@ int stadium_evict(size_t cell_index);
|
||||
* "meant to be 0" from "forgot to set it" from inside this function --
|
||||
* callers must set every field, `contains` included.
|
||||
*
|
||||
* @param candidate Header to admit. Copied into the winning cell as-is;
|
||||
* @param vm_id Owning VM's id (capsule_birth.c's registry). Allocation
|
||||
* is scoped to this VM's own quota.
|
||||
* @param candidate Header to admit. Copied into the winning cell as-is;
|
||||
* caller fills in every field including mass and heat.
|
||||
* @return The cell index admitted into, or STADIUM_CELL_NONE if refused
|
||||
* (mass != 1, invalid contains, Stadium full and candidate not
|
||||
* denser than the least-dense evictable resident, or no evictable
|
||||
* resident exists at all).
|
||||
* (vm_id has no quota, mass != 1, invalid contains, that VM's
|
||||
* quota full and candidate not denser than its least-dense
|
||||
* evictable resident, or it has no evictable resident at all).
|
||||
*/
|
||||
size_t stadium_admit(const StadiumPatronHeader *candidate);
|
||||
size_t stadium_admit(uint32_t vm_id, const StadiumPatronHeader *candidate);
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+113
-19
@@ -41,9 +41,49 @@
|
||||
|
||||
static StadiumCell *stadium_cell_array = (StadiumCell *)0;
|
||||
static uint8_t *stadium_bitmap = (uint8_t *)0;
|
||||
static uint8_t *stadium_owner = (uint8_t *)0;
|
||||
static size_t stadium_ncells = 0;
|
||||
static int stadium_initialized = 0;
|
||||
|
||||
/* Sentinel for the header's `link` field while it is reused as a free-list
|
||||
* next-pointer (item 3.7): link is uint32_t, but STADIUM_CELL_NONE is
|
||||
* (size_t)-1 -- 64 bits wide on this target. Casting (size_t)-1 down to
|
||||
* uint32_t truncates to the same bit pattern as this constant (safe), but
|
||||
* casting THIS constant back up to size_t does not sign-extend to
|
||||
* STADIUM_CELL_NONE (unsafe) -- hence the explicit link_to_size()/
|
||||
* size_to_link() conversions below rather than a raw cast either direction. */
|
||||
#define STADIUM_LINK_NONE ((uint32_t)-1)
|
||||
|
||||
static uint32_t size_to_link(size_t v) {
|
||||
return (v == STADIUM_CELL_NONE) ? STADIUM_LINK_NONE : (uint32_t)v;
|
||||
}
|
||||
|
||||
static size_t link_to_size(uint32_t v) {
|
||||
return (v == STADIUM_LINK_NONE) ? STADIUM_CELL_NONE : (size_t)v;
|
||||
}
|
||||
|
||||
/*
|
||||
* StadiumVMQuota - one VM's ownership record (item 3.7, FABRIC.md §22.3).
|
||||
* See stadium.h's stadium_admit() doc for why vm_id needs a linear search
|
||||
* rather than direct indexing.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t vm_id;
|
||||
int in_use;
|
||||
size_t free_head;
|
||||
} StadiumVMQuota;
|
||||
|
||||
static StadiumVMQuota stadium_quotas[STADIUM_MAX_VM_COUNT];
|
||||
|
||||
/* Returns the quota slot index for vm_id, or -1 if none is granted. */
|
||||
static int quota_slot_for_vm(uint32_t vm_id) {
|
||||
int i;
|
||||
for (i = 0; i < STADIUM_MAX_VM_COUNT; i++) {
|
||||
if (stadium_quotas[i].in_use && stadium_quotas[i].vm_id == vm_id) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Freestanding: no libc printf. Prints an unsigned decimal, no leading zeros. */
|
||||
static void console_put_u64(uint64_t v) {
|
||||
char buf[21];
|
||||
@@ -73,10 +113,12 @@ int stadium_boot_init(void) {
|
||||
|
||||
StadiumCell *cells = (StadiumCell *)kmalloc(ncells * STADIUM_CELL_BYTES);
|
||||
uint8_t *bitmap = (uint8_t *)kmalloc(bitmap_bytes);
|
||||
if (!cells || !bitmap) {
|
||||
uint8_t *owner = (uint8_t *)kmalloc(ncells);
|
||||
if (!cells || !bitmap || !owner) {
|
||||
console_println("Stadium: kmalloc failed for boot-time allocation");
|
||||
if (cells) kfree(cells);
|
||||
if (bitmap) kfree(bitmap);
|
||||
if (owner) kfree(owner);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -91,8 +133,34 @@ int stadium_boot_init(void) {
|
||||
for (i = 0; i < bitmap_bytes; i++) bitmap[i] = 0;
|
||||
}
|
||||
|
||||
/* Item 3.7: chain every cell into one free list, ascending index order
|
||||
* (so the first-ever pop returns cell 0, per item 3.6), granted whole
|
||||
* to vm_id 0 (Hera) -- the only VM that exists (item 0.1). Reuses each
|
||||
* cell's own `link` field as the next-free-cell pointer while
|
||||
* unresident; see stadium_admit()'s doc for the scope of that reuse. */
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < ncells; i++) {
|
||||
cells[i].header.link = size_to_link((i + 1 < ncells) ? (i + 1) : STADIUM_CELL_NONE);
|
||||
cells[i].header.contains = STADIUM_CONTAINS_NONE;
|
||||
owner[i] = 0;
|
||||
}
|
||||
}
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < STADIUM_MAX_VM_COUNT; i++) {
|
||||
stadium_quotas[i].vm_id = 0;
|
||||
stadium_quotas[i].in_use = 0;
|
||||
stadium_quotas[i].free_head = STADIUM_CELL_NONE;
|
||||
}
|
||||
}
|
||||
stadium_quotas[0].vm_id = 0;
|
||||
stadium_quotas[0].in_use = 1;
|
||||
stadium_quotas[0].free_head = 0;
|
||||
|
||||
stadium_cell_array = cells;
|
||||
stadium_bitmap = bitmap;
|
||||
stadium_owner = owner;
|
||||
stadium_ncells = ncells;
|
||||
stadium_initialized = 1;
|
||||
|
||||
@@ -197,6 +265,7 @@ static void bitmap_clear(size_t cell_index) {
|
||||
*/
|
||||
int stadium_evict(size_t cell_index) {
|
||||
StadiumPatronHeader *header;
|
||||
uint8_t slot;
|
||||
|
||||
if (cell_index >= stadium_ncells) return -1;
|
||||
if (!bitmap_get(cell_index)) return -1;
|
||||
@@ -211,6 +280,7 @@ int stadium_evict(size_t cell_index) {
|
||||
|
||||
stadium_dispatch(cell_index, (StadiumBehaviour)header->behaviour);
|
||||
bitmap_clear(cell_index);
|
||||
slot = stadium_owner[cell_index];
|
||||
|
||||
{
|
||||
uint8_t *raw = (uint8_t *)header;
|
||||
@@ -218,27 +288,40 @@ int stadium_evict(size_t cell_index) {
|
||||
for (i = 0; i < sizeof(*header); i++) raw[i] = 0;
|
||||
}
|
||||
|
||||
/* Item 3.7: return the freed cell to its owning VM's free list. contains
|
||||
* must be set to the real "none" sentinel here, not left at the zero
|
||||
* the fill above just wrote -- 0 is Hera's valid index, so a stray zero
|
||||
* would make this freed cell look permanently "contains Hera" to the
|
||||
* very next admit() that pops it. */
|
||||
header->link = size_to_link(stadium_quotas[slot].free_head);
|
||||
header->contains = STADIUM_CONTAINS_NONE;
|
||||
stadium_quotas[slot].free_head = cell_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FABRIC.md §19.3: admit if denser than the least-dense resident. Free-cell
|
||||
* placement first (no comparison needed -- §19.3 only governs the full
|
||||
* case); otherwise finds the least-dense evictable resident (pinned and
|
||||
* FABRIC.md §19.3, §22.3, item 3.7: admit into vm_id's own quota. Pops that
|
||||
* VM's free-list head first (O(1), no comparison needed -- §19.3's density
|
||||
* rule only governs the full case). Only if that list is empty does this
|
||||
* fall back to eviction, scoped to that SAME VM's own residents (quota
|
||||
* isolation), finding the least-dense evictable one (pinned and
|
||||
* contains-gated residents are skipped, never eviction candidates) and
|
||||
* evicts it only if the candidate is strictly denser.
|
||||
* evicting it only if the candidate is strictly denser.
|
||||
*/
|
||||
size_t stadium_admit(const StadiumPatronHeader *candidate) {
|
||||
size_t stadium_admit(uint32_t vm_id, const StadiumPatronHeader *candidate) {
|
||||
int slot;
|
||||
size_t i;
|
||||
size_t idx;
|
||||
size_t least_dense_index = STADIUM_CELL_NONE;
|
||||
uint64_t least_dense_value = 0;
|
||||
uint64_t candidate_density;
|
||||
|
||||
if (!stadium_initialized || !candidate) return STADIUM_CELL_NONE;
|
||||
|
||||
/* Multi-cell patrons need their continuation chain allocated too, which
|
||||
* needs the per-VM free lists item 3.2 deferred (§22.3) -- not this
|
||||
* item's scope. Refuse rather than admit only the header and leak the
|
||||
/* Multi-cell patrons need a continuation chain, and no header field is
|
||||
* documented as carrying one's first index -- see this function's doc
|
||||
* in stadium.h. Refuse rather than admit only the header and leak the
|
||||
* rest, which would break capacity conservation. */
|
||||
if (candidate->mass != 1) return STADIUM_CELL_NONE;
|
||||
|
||||
@@ -249,18 +332,22 @@ size_t stadium_admit(const StadiumPatronHeader *candidate) {
|
||||
if (candidate->contains != STADIUM_CONTAINS_NONE &&
|
||||
candidate->contains >= stadium_ncells) return STADIUM_CELL_NONE;
|
||||
|
||||
for (i = 0; i < stadium_ncells; i++) {
|
||||
if (!bitmap_get(i) && stadium_cell_array[i].header.mass == 0) {
|
||||
stadium_cell_array[i].header = *candidate;
|
||||
bitmap_set(i);
|
||||
return i;
|
||||
}
|
||||
slot = quota_slot_for_vm(vm_id);
|
||||
if (slot < 0) return STADIUM_CELL_NONE;
|
||||
|
||||
if (stadium_quotas[slot].free_head != STADIUM_CELL_NONE) {
|
||||
idx = stadium_quotas[slot].free_head;
|
||||
stadium_quotas[slot].free_head = link_to_size(stadium_cell_array[idx].header.link);
|
||||
stadium_cell_array[idx].header = *candidate;
|
||||
bitmap_set(idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
for (i = 0; i < stadium_ncells; i++) {
|
||||
StadiumPatronHeader *h;
|
||||
|
||||
if (!bitmap_get(i)) continue;
|
||||
if (stadium_owner[i] != (uint8_t)slot) continue;
|
||||
h = &stadium_cell_array[i].header;
|
||||
if (h->flags & STADIUM_FLAG_PIN) continue;
|
||||
if (h->contains != STADIUM_CONTAINS_NONE) continue;
|
||||
@@ -276,14 +363,21 @@ size_t stadium_admit(const StadiumPatronHeader *candidate) {
|
||||
|
||||
if (least_dense_index == STADIUM_CELL_NONE) return STADIUM_CELL_NONE;
|
||||
|
||||
candidate_density = candidate->mass ? (candidate->heat / (uint64_t)candidate->mass) : 0;
|
||||
candidate_density = candidate->heat / (uint64_t)candidate->mass; /* mass == 1, guaranteed above */
|
||||
if (candidate_density <= least_dense_value) return STADIUM_CELL_NONE;
|
||||
|
||||
if (stadium_evict(least_dense_index) != 0) return STADIUM_CELL_NONE;
|
||||
|
||||
stadium_cell_array[least_dense_index].header = *candidate;
|
||||
bitmap_set(least_dense_index);
|
||||
return least_dense_index;
|
||||
/* stadium_evict() just pushed least_dense_index onto quotas[slot]'s free
|
||||
* list -- its owner is `slot`, the same quota we scoped the search to.
|
||||
* Single-threaded today (§21.1/§21.2: real concurrency is step-one, not
|
||||
* yet built), so nothing else can have touched the list meanwhile; pop
|
||||
* it straight back off. */
|
||||
idx = stadium_quotas[slot].free_head;
|
||||
stadium_quotas[slot].free_head = link_to_size(stadium_cell_array[idx].header.link);
|
||||
stadium_cell_array[idx].header = *candidate;
|
||||
bitmap_set(idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
Reference in New Issue
Block a user