Memory Management: Observability Contract

Part of the memory management rewrite plan: architecture · observability · maintainability · phases · decisions and risks. Every layer exports counters from its first commit, including counters for subsystems that do not exist yet. This is deliberate: the reason the page cache is easy to add later is that the place to report its hit rate already exists, and the reason a regression is caught is that the number was being watched before it moved.

Exposed through one structure, printed by the kernel console's meminfo command and asserted by the boot gate.

CounterLayerMeaningGate assertion
frames_totalL0frames the table describesnon-zero; covers the whole region
frames_freeL0owners == 0non-zero at every stage
frames_allocatedL0in usematches total minus free
frames_leakedL0put refused for lack of an entrymust be zero
frames_double_putL0put on a frame with no ownersmust be zero
poison_hitsL0write to a page after it was freedmust be zero
maps / unmapsL1PTEs created and destroyedmaps ≥ unmaps; converge at teardown
cow_shared / cow_copiedL1pages shared by fork, copies forcedboth non-zero
tlb_shootdowns / tlb_acks / tlb_timeoutsL1cross-core invalidationacks ≥ shootdowns; timeouts zero
faults_resolved / faults_fatalL1page faults by outcomefatal count matches the deliberate ones
vmas_liveL2regions per processreturns to zero when a process exits
cache_hits / cache_missesL3page cachepresent from P0, zero until P4
cache_evictions / cache_writebacksL3
swap_ins / swap_outs / swap_usedL3present from P0, zero until P5
reclaim_scans / reclaim_freedL4present from P0, zero until P6

Log events follow the existing levelled scheme: every allocation, mapping and release is recorded at DEBUG in the ring, printed only at INFO and above. The ring is already 2048 entries and a boot uses about 500.