mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Android VM lifecycle: prompt EE stop + fix 2nd-launch kick-back
- R5900 _cpuEventTest_Shared: bail out early on VMState::Stopping/Shutdown and on IsExecutionInterrupted() so the EE leaves Execute() promptly on stop (previously hit the ~5s shutdown timeout). - native-lib Host::RequestVMShutdown: no-op if already Shutdown. The queued task could re-set Stopping after the run loop already reached Shutdown, sticking s_state at Stopping so the next Initialize failed 'already running' -- kick back to library on the 2nd game boot.
This commit is contained in:
@@ -363,6 +363,20 @@ __fi void _cpuEventTest_Shared()
|
||||
eeEventTestIsActive = true;
|
||||
cpuRegs.nextEventCycle = cpuRegs.cycle + eeWaitCycles;
|
||||
cpuRegs.lastEventCycle = cpuRegs.cycle;
|
||||
|
||||
// Android's in-game Exit/Reset can flip the VM to Stopping from another
|
||||
// thread while the EE recompiler is in its generated-code event path. Once
|
||||
// Stopping is visible, do not continue into IOP counters/VU sync; return
|
||||
// immediately so the recompiler's outer recEventTest can fastjmp out of
|
||||
// Cpu->Execute(). Without this, PSX-vsync/IOP work can keep running after
|
||||
// the stop latch and the Java shutdown call times out.
|
||||
const VMState vm_state = VMManager::GetState();
|
||||
if (vm_state == VMState::Stopping || vm_state == VMState::Shutdown)
|
||||
{
|
||||
eeEventTestIsActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// ---- INTC / DMAC (CPU-level Exceptions) -----------------
|
||||
// Done first because exceptions raised during event tests need to be postponed a few
|
||||
// cycles (fixes Grandia II [PAL], which does a spin loop on a vsync and expects to
|
||||
@@ -427,6 +441,17 @@ __fi void _cpuEventTest_Shared()
|
||||
_cpuTestInterrupts();
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Android pause/stop requests can be pumped during the counter/vsync work
|
||||
// above. Once that happens, return to the rec/interpreter wrapper immediately
|
||||
// instead of continuing through VU sync and scheduling a fresh event.
|
||||
if (VMManager::Internal::IsExecutionInterrupted())
|
||||
{
|
||||
eeEventTestIsActive = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---- VU Sync -------------
|
||||
// We're in a EventTest. All dynarec registers are flushed
|
||||
// so there is no need to freeze registers here.
|
||||
|
||||
@@ -2598,6 +2598,15 @@ void Host::RequestExitBigPicture()
|
||||
|
||||
void Host::RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool default_save_state)
|
||||
{
|
||||
// This runs as a queued CPU-thread task (Host::RunOnCPUThread from the shutdown
|
||||
// JNI). Since the EE now bails out of Execute() promptly on Stopping, the run
|
||||
// loop can reach its post-Shutdown message pump and process THIS task AFTER
|
||||
// VMManager::Shutdown(false) already drove s_state to Shutdown. Re-setting
|
||||
// Stopping here would leave s_state stuck at Stopping, so the next game's
|
||||
// VMManager::Initialize fails with "already running" (kick-back to library on
|
||||
// the 2nd launch). If we're already shut down, there's nothing left to stop.
|
||||
if (VMManager::GetState() == VMState::Shutdown)
|
||||
return;
|
||||
VMManager::SetState(VMState::Stopping);
|
||||
if (!s_execute_exit.load(std::memory_order_acquire) && Cpu)
|
||||
Cpu->ExitExecution();
|
||||
|
||||
Reference in New Issue
Block a user