mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Log the guest's ExitProcess line after the exit guard, and bring the comments on gfx_window_closed's return up to date.
The review of the exit sequence found that svc.c case 0x07 logged "guest ExitProcess at ...; exiting" before rt_exit_begin. When a close had already begun, the guest thread that the guard then parks still claimed to exit, and past the log cap the line fell outside the end's reserve, which rt_exit_begin opens. It also found that host.h and gfx_wsys.h still said gfx_window_closed does not return, though it returns for its own thread coming back, and that rt_exit_begin's comment spoke of the window thread handling a message inside the sequence, which since the close runs on a thread of its own happens only in the fallback. svc.c logs the line after rt_exit_begin returns 1. The two header comments say gfx_window_closed returns only for its own thread coming back (gfx_present.c rt_exit_begin), and rt_exit_begin's comment says the window thread runs the sequence itself only when gfx_window_win.c exit_start could make no thread. tests/exit_order_check.py checks statically that 0x07's rt_log comes after rt_exit_begin; it fails on the code before this change and passes after it. exit_order_check and the compile check of every runtime file (a header changed) pass, with no new -Wall warnings in svc.c and gfx_present.c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -115,8 +115,9 @@ void gfx_window_focus_changed(int in) {
|
||||
// Once per process, whichever comes first. The window's close and the console's (main.c console_closed) can come
|
||||
// together, or the guest's ExitProcess beside either: each ran its own sequence, so two pipeline saves and two
|
||||
// frame-time summaries were written while both raced. 1 for the first caller; a caller on another thread waits here
|
||||
// for good while the first ends the process; 0 for the first caller's own thread coming back (a message the window
|
||||
// thread handles inside the sequence), which goes on with the sequence it is in.
|
||||
// for good while the first ends the process; 0 for the first caller's own thread coming back, which goes on with the
|
||||
// sequence it is in. The window's close runs on a thread of its own (gfx_window_win.c exit_start); the window thread
|
||||
// runs the sequence itself, and may handle a message inside it, only when that thread could not be made.
|
||||
static volatile uint32_t exit_tid; // the thread that runs the orderly end, 0 before one started
|
||||
|
||||
int rt_exit_begin(void) {
|
||||
|
||||
@@ -19,7 +19,9 @@ int wsys_probe_click(int where);
|
||||
// ---- what gfx_present.c provides the back end
|
||||
void gfx_window_mark_dirty(void); // the window changed size: the next present rebuilds the swapchain
|
||||
void gfx_window_focus_changed(int in); // the window gained (1) or lost (0) the focus
|
||||
void gfx_window_closed(void); // the player closed the window: saves, then ends the process
|
||||
// the player closed the window: saves, then ends the process. It does not return, but for its own thread coming back
|
||||
// (gfx_present.c rt_exit_begin)
|
||||
void gfx_window_closed(void);
|
||||
void gfx_window_set_refresh(double hz); // the refresh rate of the window's monitor, 0 unknown
|
||||
int gfx_cfg_fullscreen(void); // NX2NAVI_FULLSCREEN
|
||||
void gfx_cfg_window_size(int *w, int *h); // NX2NAVI_WINDOW_SIZE, the default when unparsable or out of range
|
||||
|
||||
@@ -116,7 +116,9 @@ void perf_summary_flush(void); // prints the frame-time summary
|
||||
void perf_summary_flush_try(void); // the same at a fatal error, the stutter map only if its lock is free
|
||||
void perf_focus_lost(void); // the window lost the focus: the session's reports at the next present, in play
|
||||
void gfx_exit_log(void); // back end's lines for the exit summary (weak no-op in prof_win.c)
|
||||
void gfx_window_closed(void); // gfx_present.c (gfx_wsys.h): the end of a closed window; does not return
|
||||
// gfx_present.c (gfx_wsys.h): the end of a closed window. It does not return, but for its own thread coming back
|
||||
// (gfx_present.c rt_exit_begin)
|
||||
void gfx_window_closed(void);
|
||||
// gfx_present.c: the orderly end every exit the game asks for shares (the window's close, svc.c ExitProcess, boot.c
|
||||
// --seconds). rt_exit_begin: 1 for the first caller; another thread waits there for good; 0 for that caller's own
|
||||
// thread again. rt_exit_steps: the saves and the put-backs, the slow pipeline save late and the final save flush last.
|
||||
|
||||
@@ -240,11 +240,12 @@ static void svc_body(Cpu *c, uint32_t imm, uint64_t pc) {
|
||||
}
|
||||
case 0x29: get_info(c, pc); return;
|
||||
case 0x07: { // ExitProcess, as closing the window: the orderly end (gfx_present.c rt_exit_steps), exit code 0
|
||||
char at[160];
|
||||
rt_log("guest ExitProcess at %s; exiting", ldr_describe(pc, at, sizeof at));
|
||||
// once, shared with the window's close: a close already ending the process keeps this thread there; this
|
||||
// thread coming back would resume guest code after its ExitProcess, so it ends the process instead
|
||||
// once, shared with the window's close: a close already ending the process keeps this thread there, and the
|
||||
// exit line is that close's alone; this thread coming back would resume guest code after its ExitProcess, so it
|
||||
// ends the process instead
|
||||
if (!rt_exit_begin()) plat_exit(0);
|
||||
char at[160]; // after the guard, which also lets the line reach the log file past its cap (main.c log_sink)
|
||||
rt_log("guest ExitProcess at %s; exiting", ldr_describe(pc, at, sizeof at));
|
||||
rt_exit_steps(RT_EXIT_SETTINGS);
|
||||
fflush(NULL);
|
||||
if (svc_test_exit_hook) return svc_test_exit_hook(0);
|
||||
|
||||
@@ -151,6 +151,11 @@ def static_checks():
|
||||
print(f'{name}: {"rt_exit_begin, then " + steps + ", then plat_exit" if ok else "FAIL"}'
|
||||
+ (f'; calls exit steps of its own: {", ".join(own)}' if own else ''), flush=True)
|
||||
bad += not ok
|
||||
# the guest's exit line comes after the guard: a thread the guard parks (a close already ending) logs no exit
|
||||
code = strip_comments(exit07)
|
||||
ok = 0 <= code.find('rt_exit_begin()') < code.find('rt_log(')
|
||||
print(f'svc.c ExitProcess (0x07): its exit line after rt_exit_begin: {"ok" if ok else "FAIL"}', flush=True)
|
||||
bad += not ok
|
||||
# the cheats rebuild's end, before the guest runs: the guard, RTSS, the boot's marker and journal, the summary
|
||||
cheats = (RT / 'cheats.c').read_text(encoding='utf-8')
|
||||
body = strip_comments(function(cheats, 'static void rebuild_if_needed(const char *dir)'))
|
||||
|
||||
Reference in New Issue
Block a user