Files
NX2navi/tests/evo_peek_check.py
chrg6 688b250673 Let held_resume ask whether held work can go on from a published copy, not from a continuation another thread frees.
vk_exec_held_ready runs without sub_lock (vk_backend.c held_resume and submit_sync). It followed evq[s].head into the
continuation and read the wait in the continuation's private copy of the recording. Meanwhile another submitting
thread, inside vk_sync_submit, could run evo_resume and cont_free that continuation. A reused block then gave
vk_exec_event_met an event address pointing anywhere, so the unlocked reader could fault, not only read a stale state.

Now the holder of sub_lock publishes what the decision needs into a per-queue sequence lock (runtime/vk_evo_peek.h),
wherever a queue's first continuation, or that continuation's wait or stop, changes: in cont_push when the pushed one
becomes the first, in evo_resume after the head moves on, and after cont_walk stops at another wait. The copy holds
the wait by value. vk_exec_held_ready decides from a copy taken from one publish. It never waits for the writer:
after three tries that overlap a publish it answers "not ready", which is what losing that race answered before.
This fixes F-1-06 without the front-end lock. F-2-01's lock is still the answer for the other unlocked front-end
state.

Not reproduced before the change. Checks that passed: the new tests/evo_peek_check (one writer publishing 1,000,000
times while three readers copy: no copy mixed two publishes, and the decision cont_ready makes, with a stand-in for
vk_exec_event_met; with the sequence check removed it reports over a million mixed copies), pass_cc_check on every
runtime file (a header was added), no new -Wall -Wextra warnings in vk_exec.c, target_frames_check, oq_hold_check,
sync_hw_check, mesh_path_check and gpa_check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 18:41:40 -05:00

47 lines
1.7 KiB
Python

"""Build and run tests/evo_peek_check.c: runtime/vk_evo_peek.h, the copy of each event-ordered queue's first held wait
that vk_exec.c vk_exec_held_ready reads without the submission lock, and the decision it makes from that copy. One
writer republishes while three readers copy: no copy may mix two publishes, and no reader waits for the writer.
No GPU, no game files, any Python.
Usage: evo_peek_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():
"""$CC, else MSYS2 UCRT64's clang, else clang on PATH (as tests/diff/common.py picks it, without its Unicorn)."""
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'
def main():
work = ROOT / 'build' / 'test' / 'evo_peek'
work.mkdir(parents=True, exist_ok=True)
exe = work / ('evo_peek_check.exe' if os.name == 'nt' else 'evo_peek_check')
env = dict(os.environ)
if os.name == 'nt' and MSYS_BIN.exists():
env['PATH'] = str(MSYS_BIN) + os.pathsep + env.get('PATH', '')
extra = [] if os.name == 'nt' else ['-pthread']
subprocess.check_call([compiler(), '-std=gnu11', '-O2', '-Wall', '-Werror', '-I', str(ROOT / 'runtime'),
str(ROOT / 'tests' / 'evo_peek_check.c'), '-o', str(exe), *extra], env=env)
try:
return subprocess.run([str(exe)], env=env, timeout=120).returncode
except subprocess.TimeoutExpired:
print('evo_peek_check: FAIL: the check did not end within 120 s')
return 1
if __name__ == '__main__':
sys.exit(main())