The previous write-up argued the leak from adjacency -- 22 failed releases next
to the failed allocation. memory.cc closes the loop outright:
* the "parent free N/M pages" in the error is
parent_heap_->unreserved_page_count() (memory.cc:1807);
* unreserved_page_count_ is incremented in exactly ONE place, memory.cc:1445,
inside BaseHeap::Release's page-table loop;
* the failing path returns at memory.cc:1399, at the top of that same
function, before the loop -- page table untouched, no free block inserted;
* and PhysicalHeap::Release delegates to parent_heap_->Release, so the release
that fails and the allocation that later comes up short are the same heap.
So every "address is not a region start" returns zero pages to the counter the
allocator consults, and those pages stay reserved for the life of the process.
That is control flow, not correlation.
Magnitude is still open and I am not claiming it: 512 - 113 = 399 MB missing
against only 22-23 failed releases would need ~18 MB average each, which is
implausible as the whole story. Leaked releases are a contributor, maybe not
the dominant one. An allocation ledger -- log every MmAllocatePhysicalMemoryEx
and MmFreePhysicalMemory with sizes and balance them -- would settle it, and is
a better use of a run than reproducing the freeze again.
Also recorded so nobody hunts for it: there is NO cvar for guest memory size.
memory.cc has only protect_zero / protect_on_release / scribble_heap and the
MMIO ones, and xboxkrnl_memory.cc says "We don't support separate devkit
memory, so just ignore this flag". 512 MB is hardcoded to the retail console,
so the freeze cannot be dodged by giving the emulator more -- a fix has to be
the release path itself.