Stage B proof: add per-VM consumed term to stadium_conserved -- FABRIC-3.6.md task 2.7

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-20 21:31:45 -04:00
co-authored by Claude Sonnet 5
parent 313ffc89e6
commit 2a2bf6eb35
12 changed files with 55566 additions and 8 deletions
+2
View File
@@ -151,6 +151,7 @@ int sk_hermes_alloc(VMUuid vm_id, SkHermesMessage **out_msg) {
memset(&sk_hermes_msgs[slot], 0, sizeof(SkHermesMessage));
sk_hermes_msgs[slot].in_use = 1;
sk_hermes_msgs[slot].stadium_cell = (int32_t)cell;
sk_hermes_msgs[slot].owner = vm_id;
*out_msg = &sk_hermes_msgs[slot];
/* Task 2.4: the one site where held/pulled increment -- only reached
@@ -222,6 +223,7 @@ int sk_hermes_decay(SkHermesMessage *msg) {
* pays for it). SXXXVII.3: decay's delta is exact and in hand here. */
sk_hermes_consumed += before - after;
sk_hermes_held -= before - after;
stadium_consumed_record(msg->owner, before - after);
sk_hermes_audit();
return 0;
+22 -1
View File
@@ -107,6 +107,10 @@ typedef struct {
* Invariant: Σ(resident patron heat) + reservoir ==
* Q48_ONE, checked the same way vm_physics_conserved()
* checks the fleet sum. */
uint64_t consumed; /* FABRIC-3.5.md §XL.4 -- Q48.16, heat this VM's messages
* have decayed away (recorded by kernel-Hermes,
* FABRIC-3.6.md task 2.7). Full invariant:
* Σ(resident) + reservoir + consumed == Q48_ONE. */
} StadiumVMQuota;
/* kmalloc'd at stadium_boot_init() to stadium_max_vm_count_val entries,
@@ -275,6 +279,7 @@ int stadium_boot_init(void) {
quotas[i].free_count = 0;
quotas[i].resident_head = STADIUM_CELL_NONE;
quotas[i].reservoir = 0;
quotas[i].consumed = 0;
}
}
quotas[0].vm_id = vm_uuid_hera();
@@ -642,6 +647,7 @@ int stadium_grant_quota(VMUuid new_vm_id, VMUuid from_vm_id) {
stadium_quotas[new_slot].free_count = half;
stadium_quotas[new_slot].resident_head = STADIUM_CELL_NONE;
stadium_quotas[new_slot].reservoir = Q48_ONE;
stadium_quotas[new_slot].consumed = 0;
return 0;
}
@@ -764,8 +770,23 @@ uint64_t stadium_resident_sum(VMUuid vm_id) {
return sum;
}
void stadium_consumed_record(VMUuid vm_id, uint64_t amount) {
int slot = quota_slot_for_vm(vm_id);
if (slot < 0) return;
stadium_quotas[slot].consumed += amount;
}
uint64_t stadium_consumed_peek(VMUuid vm_id) {
int slot = quota_slot_for_vm(vm_id);
if (slot < 0) return 0;
return stadium_quotas[slot].consumed;
}
int stadium_conserved(VMUuid vm_id) {
return (stadium_resident_sum(vm_id) + stadium_reservoir_peek(vm_id)) == (uint64_t)Q48_ONE;
return (stadium_resident_sum(vm_id) + stadium_reservoir_peek(vm_id) +
stadium_consumed_peek(vm_id)) == (uint64_t)Q48_ONE;
}
/*