Add the four ledger counters (held/pulled/returned/consumed) -- FABRIC-3.6.md task 2.4
FABRIC-3.5.md SXL.4's ledger: held == pulled - returned - consumed,
epsilon zero. Added sk_hermes_ledger() (an accessor, not a mutator)
plus four static counters in kernel_hermes.c.
Each counter has exactly one increment/decrement site: held/pulled
both move at sk_hermes_alloc()'s single success path, after every
refusal branch has already returned; held/returned both move at
sk_hermes_release()'s single success path. consumed is declared and
always reads 0 -- its one increment site doesn't exist yet, and won't
until task 2.5 gives decay something to record.
sk_hermes_release() now reads the Stadium cell's live header.heat
immediately before calling stadium_evict(), rather than assuming the
original pulled amount -- stadium_evict() zeroes the header as part of
freeing the cell and its own return value is a success code, not the
credited amount, so this is the only point the true remaining heat is
available. Today this always equals the original Q.SLOT pull; once
task 2.5's decay exists, this is what keeps returned correct without
touching this function again.
Self-test (kernel_main.c) extended: snapshots the ledger before
running so it checks its own deltas, verifies held/pulled grow by
exactly got_n * Q_SLOT on allocation with returned/consumed untouched,
then verifies held returns to its starting value and returned grows by
the same amount on release, and checks the audit invariant itself as a
bonus (task 2.6 formalizes this properly).
Three-arch boot clean: amd64/aarch64/riscv64 all reach [zuse@Hera] ok>,
zero UNKNOWN WORD, dict_hash unmoved. All three print PASS with
identical final ledger: held=0 pulled=65536 returned=65536 consumed=0.
No compiler warnings.
Authorized by Captain Bob ("keep going with rhe 6.5 document").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
2c1dc1753a
commit
493d410028
@@ -855,6 +855,14 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
SkHermesMessage *msg;
|
||||
int ok = 1;
|
||||
size_t i;
|
||||
uint64_t held0, pulled0, returned0, consumed0;
|
||||
uint64_t held1, pulled1, returned1, consumed1;
|
||||
uint64_t held2, pulled2, returned2, consumed2;
|
||||
|
||||
/* Task 2.4: snapshot the ledger before touching it, so this
|
||||
* test checks its own deltas rather than assuming it is the
|
||||
* only thing that has ever called these functions. */
|
||||
sk_hermes_ledger(&held0, &pulled0, &returned0, &consumed0);
|
||||
|
||||
while (got_n < SK_HERMES_MSG_MAX && sk_hermes_alloc(alloc_test_id, &msg) == 0) {
|
||||
msgs[got_n] = msg;
|
||||
@@ -869,6 +877,15 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
if (stadium_reservoir_peek(alloc_test_id) != reservoir_after_alloc) ok = 0;
|
||||
if (reservoir_after_alloc != reservoir0 - got_n * SK_HERMES_Q_SLOT) ok = 0;
|
||||
|
||||
/* Task 2.4: held/pulled must both have grown by exactly
|
||||
* got_n * Q_SLOT; returned/consumed must be untouched by
|
||||
* allocation alone. */
|
||||
sk_hermes_ledger(&held1, &pulled1, &returned1, &consumed1);
|
||||
if (held1 - held0 != got_n * SK_HERMES_Q_SLOT) ok = 0;
|
||||
if (pulled1 - pulled0 != got_n * SK_HERMES_Q_SLOT) ok = 0;
|
||||
if (returned1 != returned0) ok = 0;
|
||||
if (consumed1 != consumed0) ok = 0;
|
||||
|
||||
/* Task 2.3: release every allocated message via the Stadium
|
||||
* eviction path and confirm the reservoir is restored
|
||||
* exactly -- "reservoir restored exactly for an undecayed
|
||||
@@ -882,6 +899,21 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
uint64_t reservoir_final = stadium_reservoir_peek(alloc_test_id);
|
||||
if (reservoir_final != reservoir0) ok = 0;
|
||||
|
||||
/* Task 2.4: held must fall back to held0 (every message this
|
||||
* test allocated is now released); returned must have grown
|
||||
* by exactly what held grew by; consumed still untouched
|
||||
* (nothing decayed). This is the ledger side of "reservoir
|
||||
* restored exactly." */
|
||||
sk_hermes_ledger(&held2, &pulled2, &returned2, &consumed2);
|
||||
if (held2 != held0) ok = 0;
|
||||
if (pulled2 != pulled1) ok = 0; /* release never touches pulled */
|
||||
if (returned2 - returned0 != got_n * SK_HERMES_Q_SLOT) ok = 0;
|
||||
if (consumed2 != consumed0) ok = 0;
|
||||
/* The audit invariant itself (task 2.6 formalizes this as its
|
||||
* own check; verified here too since the ledger is already in
|
||||
* hand): held == pulled - returned - consumed, at rest. */
|
||||
if (held2 != pulled2 - returned2 - consumed2) ok = 0;
|
||||
|
||||
console_println(ok ? "PASS" : "FAIL");
|
||||
print_uint(" reservoir0=", reservoir0);
|
||||
print_uint(" Q_SLOT=", SK_HERMES_Q_SLOT);
|
||||
@@ -889,6 +921,10 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
print_uint(" got_n=", got_n);
|
||||
print_uint(" reservoir_after_alloc=", reservoir_after_alloc);
|
||||
print_uint(" reservoir_final=", reservoir_final);
|
||||
print_uint(" held(final)=", held2);
|
||||
print_uint(" pulled(final)=", pulled2);
|
||||
print_uint(" returned(final)=", returned2);
|
||||
print_uint(" consumed(final)=", consumed2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user