mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
With NX2NAVI_HEAP_LAZY=1, a heap page nothing has touched yet is still reserved. mem_copy_readable holds frz_lock and, for a range with no armed or probed region, copied it with a plain memcpy. A reserved heap page in that range faulted into fault_veh, then access_fault, then heap_lazy_fault, which takes frz_lock on the same thread. The SRW lock is not recursive, so the copy never returned, and every later fault, thaw and freeze waited behind it. Callers are frame_rate.c's floor probe and vk_memory.c mirror_capture (MIRROR_CAPTURE_KB or MIRROR_STAGE). Now, when the lazy heap is on and a range meets the heap, the range is copied run by run as plat_mem_state reports its pages. The heap's reserved runs read zero, as they would once committed, and are not committed, so a diagnostic read or a mirror's first copy does not undo what the setting saves. Readable runs are copied, and anything else leaves the range out (ok = 0). Ranges outside the heap, and every range while the lazy heap is off, keep the copy that asks the system nothing. tests/heap_lazy_copy_check builds memory.c with the Windows platform layer and its fault handler. It copies an untouched heap page, a range from written pages into untouched ones, a range past the heap's end, and a batch of three, each on a worker the main thread gives 3 s. Before the change the first copy hung (exit 4). Checks that passed: heap_lazy_copy_check, pass_cc_check on memory.c, no new -Wall -Wextra warnings, wb_lazy_check, mem_growth_check, mem_budget_check and gpa_check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
"""Build and run tests/heap_lazy_copy_check.c: runtime/memory.c mem_copy_readable with the lazy heap
|
|
(NX2NAVI_HEAP_LAZY=1), where a heap page nothing touched yet is still reserved. The copy holds frz_lock, which the
|
|
fault on such a page waits for; the check needs every copy to return, untouched pages to read zero and stay reserved,
|
|
and pages past the heap's end to be left out.
|
|
|
|
Windows only (the lazy heap is): memory.c is built with the Windows platform layer and its fault handler, the rest of
|
|
the runtime stubbed. No game files: the module layout the runtime includes is a stand-in written to the test's build
|
|
folder.
|
|
|
|
Usage: heap_lazy_copy_check.py
|
|
"""
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
MSYS_BIN = Path(r'C:\msys64\ucrt64\bin')
|
|
|
|
|
|
def compiler():
|
|
if os.environ.get('CC'):
|
|
return os.environ['CC']
|
|
if os.name == 'nt' and (MSYS_BIN / 'clang.exe').exists():
|
|
return str(MSYS_BIN / 'clang.exe')
|
|
return shutil.which('clang') or 'clang'
|
|
|
|
|
|
LAYOUT = '''// A stand-in for the generated layout.h (tests/heap_lazy_copy_check.py).
|
|
#pragma once
|
|
#define MOD_MAIN_BASE 0x7000000000ull
|
|
#define MOD_MAIN_SIZE 0x4ea0000ull
|
|
#define MOD_COUNT 3
|
|
'''
|
|
|
|
|
|
def main():
|
|
if os.name != 'nt':
|
|
print('heap_lazy_copy_check: the lazy heap is Windows only; skipped')
|
|
return 0
|
|
work = ROOT / 'build' / 'test' / 'heap_lazy_copy'
|
|
work.mkdir(parents=True, exist_ok=True)
|
|
(work / 'layout.h').write_text(LAYOUT)
|
|
exe = work / 'heap_lazy_copy_check.exe'
|
|
env = dict(os.environ)
|
|
if MSYS_BIN.exists():
|
|
env['PATH'] = str(MSYS_BIN) + os.pathsep + env.get('PATH', '')
|
|
rt = ROOT / 'runtime'
|
|
plat = [rt / 'platform' / 'win32.c', rt / 'platform' / 'common.c']
|
|
libs = ['-lbcrypt', '-lws2_32', '-lpsapi', '-lwinmm', '-ldbghelp', '-lshell32', '-lole32', '-luser32', '-ladvapi32']
|
|
subprocess.check_call([compiler(), '-O1', '-g', '-Wall', '-Wno-unused-function', '-fno-strict-aliasing',
|
|
'-march=x86-64-v3', '-I', str(rt), '-I', str(work),
|
|
str(ROOT / 'tests' / 'heap_lazy_copy_check.c'), *map(str, plat), '-o', str(exe), '-lm',
|
|
*libs], env=env)
|
|
try:
|
|
return subprocess.run([str(exe)], env=env, timeout=120).returncode
|
|
except subprocess.TimeoutExpired:
|
|
print('heap_lazy_copy_check: FAIL: the check did not end within 120 s')
|
|
return 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|