mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
8f8325a2fe
With the HLE scheduler (the default), ChangeThread to the thread that is already running returns 1 from psx_request_thread_switch. psx_syscall case 3 then returned 0 with cpu->pc still holding the SYSCALL's own address. Compiled callers fall through on 0, but the dirty-RAM interpreter transfers whenever cpu->pc is non-zero, so it re-executed the SYSCALL forever. A game that yields from its main thread this way hung at the kernel's SYSCALL (EPC 0x650) as soon as that kernel code ran interpreted, for example when its body did not match the compiled kernel. Clear cpu->pc on that continuation, as the SYS01/02 continuations do. The guest-exception syscall path returns before case 3 and is unchanged. syscall_change_thread_self links the production traps.c into a fixture with a one-thread TCB table at -O0 and -O2. fixture_link.py stubs every other runtime seam with abort(), so an unexpected call fails the test.
22 lines
814 B
Python
22 lines
814 B
Python
"""ChangeThread to the running thread must continue after the SYSCALL.
|
|
|
|
Links the production traps.c into test_syscall_change_thread_self.c at -O0 and
|
|
-O2; every other runtime seam is an abort() stub (fixture_link.py).
|
|
"""
|
|
import argparse
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from fixture_link import build_and_run
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--cc', default='gcc')
|
|
args = parser.parse_args()
|
|
here = Path(__file__).resolve().parent
|
|
with tempfile.TemporaryDirectory() as root:
|
|
for opt in ('-O0', '-O2'):
|
|
build_and_run(args.cc, here, here.parent, opt, Path(root),
|
|
['traps.c'], 'test_syscall_change_thread_self.c')
|
|
print('PASS: same-thread ChangeThread continues after SYSCALL (O0/O2)')
|