avoid deadlock when sh4 cpu is restarted while emu is being stopped
The sh4 cpu is stopped/restarted during a soft reset, and dynarec code reset (arm64, arm, x86). If the emulator is stopped concurrently, the call may hang. Use a mutex-protected method to restart the cpu only if the emu is still running.
This commit is contained in:
parent
6d2ed417be
commit
9793e54646
|
@ -688,7 +688,8 @@ void Emulator::runInternal()
|
|||
{
|
||||
nvmem::saveFiles();
|
||||
dc_reset(false);
|
||||
sh4_cpu.Start();
|
||||
if (!restartCpu())
|
||||
resetRequested = false;
|
||||
}
|
||||
} while (resetRequested);
|
||||
}
|
||||
|
@ -750,9 +751,12 @@ void Emulator::stop()
|
|||
// Avoid race condition with GGPO restarting the sh4 for a new frame
|
||||
if (config::GGPOEnable)
|
||||
NetworkHandshake::term();
|
||||
// must be updated after GGPO is stopped since it may run some rollback frames
|
||||
state = Loaded;
|
||||
sh4_cpu.Stop();
|
||||
{
|
||||
const std::lock_guard<std::mutex> _(mutex);
|
||||
// must be updated after GGPO is stopped since it may run some rollback frames
|
||||
state = Loaded;
|
||||
sh4_cpu.Stop();
|
||||
}
|
||||
if (config::ThreadedRendering)
|
||||
{
|
||||
rend_cancel_emu_wait();
|
||||
|
@ -1039,4 +1043,13 @@ void Emulator::vblank()
|
|||
sh4_cpu.Stop();
|
||||
}
|
||||
|
||||
bool Emulator::restartCpu()
|
||||
{
|
||||
const std::lock_guard<std::mutex> _(mutex);
|
||||
if (state != Running)
|
||||
return false;
|
||||
sh4_cpu.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
Emulator emu;
|
||||
|
|
|
@ -165,6 +165,11 @@ public:
|
|||
* Called internally on vblank.
|
||||
*/
|
||||
void vblank();
|
||||
/**
|
||||
* Restart the cpu iff the emu is still running
|
||||
* Returns true if the cpu was started
|
||||
*/
|
||||
bool restartCpu();
|
||||
|
||||
private:
|
||||
bool checkStatus(bool wait = false);
|
||||
|
|
|
@ -50,6 +50,7 @@ using namespace vixl::aarch32;
|
|||
#include "cfg/option.h"
|
||||
#include "arm_unwind.h"
|
||||
#include "oslib/virtmem.h"
|
||||
#include "emulator.h"
|
||||
|
||||
//#define CANONICALTEST
|
||||
|
||||
|
@ -428,8 +429,8 @@ public:
|
|||
generate_mainloop();
|
||||
|
||||
::mainloop(context);
|
||||
if (restarting)
|
||||
p_sh4rcb->cntx.CpuRunning = 1;
|
||||
if (restarting && !emu.restartCpu())
|
||||
restarting = false;
|
||||
} while (restarting);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ using namespace vixl::aarch64;
|
|||
#include "arm64_regalloc.h"
|
||||
#include "hw/mem/addrspace.h"
|
||||
#include "oslib/virtmem.h"
|
||||
#include "emulator.h"
|
||||
|
||||
#undef do_sqw_nommu
|
||||
|
||||
|
@ -2213,8 +2214,8 @@ public:
|
|||
generate_mainloop();
|
||||
|
||||
::mainloop(v_cntx);
|
||||
if (restarting)
|
||||
p_sh4rcb->cntx.CpuRunning = 1;
|
||||
if (restarting && !emu.restartCpu())
|
||||
restarting = false;
|
||||
} while (restarting);
|
||||
} catch (const SH4ThrownException&) {
|
||||
ERROR_LOG(DYNAREC, "SH4ThrownException in mainloop");
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "hw/sh4/sh4_mem.h"
|
||||
#include "hw/mem/addrspace.h"
|
||||
#include "oslib/unwind_info.h"
|
||||
#include "emulator.h"
|
||||
|
||||
static void (*mainloop)();
|
||||
static void (*ngen_FailedToFindBlock_)();
|
||||
|
@ -900,8 +901,8 @@ public:
|
|||
generate_mainloop();
|
||||
|
||||
::mainloop();
|
||||
if (restarting)
|
||||
p_sh4rcb->cntx.CpuRunning = 1;
|
||||
if (restarting && !emu.restartCpu())
|
||||
restarting = false;
|
||||
} while (restarting);
|
||||
} catch (const SH4ThrownException& e) {
|
||||
ERROR_LOG(DYNAREC, "SH4ThrownException in mainloop %x pc %x", e.expEvn, e.epc);
|
||||
|
|
Loading…
Reference in New Issue