mirror of https://github.com/PCSX2/pcsx2.git
Delegate systems teardown to EE Core when pausing
Fixes issues caused by Cleanup/Init on the Main Thread instead of the EE Core thread. Now systems are only set up and torn down on one thread.
This commit is contained in:
parent
e6e7a55d7e
commit
4c941f81ec
|
@ -182,7 +182,7 @@ void DebugInterface::pauseCpu()
|
|||
{
|
||||
SysCoreThread& core = GetCoreThread();
|
||||
if (!core.IsPaused())
|
||||
core.Pause(true);
|
||||
core.Pause({}, true);
|
||||
}
|
||||
|
||||
void DebugInterface::resumeCpu()
|
||||
|
|
|
@ -385,8 +385,8 @@ protected:
|
|||
void OnResumeReady();
|
||||
|
||||
void OnSuspendInThread();
|
||||
void OnPauseInThread() {}
|
||||
void OnResumeInThread( bool IsSuspended );
|
||||
void OnPauseInThread(SystemsMask systemsToTearDown) override {}
|
||||
void OnResumeInThread(SystemsMask systemsToReinstate) override;
|
||||
void OnCleanupInThread();
|
||||
|
||||
void GenericStall( uint size );
|
||||
|
|
|
@ -603,12 +603,12 @@ void SysMtgsThread::OnSuspendInThread()
|
|||
_parent::OnSuspendInThread();
|
||||
}
|
||||
|
||||
void SysMtgsThread::OnResumeInThread(bool isSuspended)
|
||||
void SysMtgsThread::OnResumeInThread(SystemsMask systemsToReinstate)
|
||||
{
|
||||
if (isSuspended)
|
||||
if (systemsToReinstate & System_GS)
|
||||
OpenGS();
|
||||
|
||||
_parent::OnResumeInThread(isSuspended);
|
||||
_parent::OnResumeInThread(systemsToReinstate);
|
||||
}
|
||||
|
||||
void SysMtgsThread::OnCleanupInThread()
|
||||
|
|
|
@ -962,13 +962,9 @@ ExtraWndProcResult StatusWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
|
||||
void PADconfigure()
|
||||
{
|
||||
HWND tmp = hWnd;
|
||||
PADclose();
|
||||
ScopedCoreThreadPause paused_core;
|
||||
ScopedCoreThreadPause paused_core(SystemsMask::System_PAD);
|
||||
Configure();
|
||||
paused_core.AllowResume();
|
||||
if(tmp != nullptr)
|
||||
PADopen(tmp);
|
||||
}
|
||||
|
||||
s32 PADopen(void* pDsp)
|
||||
|
|
|
@ -40,25 +40,9 @@ u32 lClocks = 0;
|
|||
|
||||
void SPU2configure()
|
||||
{
|
||||
ScopedCoreThreadPause paused_core;
|
||||
|
||||
SndBuffer::Cleanup();
|
||||
ScopedCoreThreadPause paused_core(SystemsMask::System_SPU2);
|
||||
|
||||
configure();
|
||||
|
||||
if (IsOpened)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.Warning("SPU2: Sound output module reset");
|
||||
SndBuffer::Init();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
fprintf(stderr, "SPU2 Error: Could not initialize device, or something.\nReason: %s", ex.what());
|
||||
SPU2close();
|
||||
}
|
||||
}
|
||||
paused_core.AllowResume();
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,12 @@ void SysCoreThread::OnStart()
|
|||
_parent::OnStart();
|
||||
}
|
||||
|
||||
void SysCoreThread::OnSuspendInThread()
|
||||
{
|
||||
TearDownSystems(static_cast<SystemsMask>(-1)); // All systems
|
||||
GetMTGS().Suspend();
|
||||
}
|
||||
|
||||
void SysCoreThread::Start()
|
||||
{
|
||||
GSinit();
|
||||
|
@ -302,30 +308,26 @@ void SysCoreThread::ExecuteTaskInThread()
|
|||
PCSX2_PAGEFAULT_EXCEPT;
|
||||
}
|
||||
|
||||
void SysCoreThread::OnSuspendInThread()
|
||||
void SysCoreThread::TearDownSystems(SystemsMask systemsToTearDown)
|
||||
{
|
||||
DEV9close();
|
||||
USBclose();
|
||||
DoCDVDclose();
|
||||
FWclose();
|
||||
PADclose();
|
||||
SPU2close();
|
||||
FileMcd_EmuClose();
|
||||
GetMTGS().Suspend();
|
||||
if (systemsToTearDown & System_DEV9) DEV9close();
|
||||
if (systemsToTearDown & System_USB) USBclose();
|
||||
if (systemsToTearDown & System_CDVD) DoCDVDclose();
|
||||
if (systemsToTearDown & System_FW) FWclose();
|
||||
if (systemsToTearDown & System_PAD) PADclose();
|
||||
if (systemsToTearDown & System_SPU2) SPU2close();
|
||||
if (systemsToTearDown & System_MCD) FileMcd_EmuClose();
|
||||
}
|
||||
|
||||
void SysCoreThread::OnResumeInThread(bool isSuspended)
|
||||
void SysCoreThread::OnResumeInThread(SystemsMask systemsToReinstate)
|
||||
{
|
||||
GetMTGS().WaitForOpen();
|
||||
if (isSuspended)
|
||||
{
|
||||
DEV9open((void*)pDsp);
|
||||
USBopen((void*)pDsp);
|
||||
}
|
||||
FWopen();
|
||||
SPU2open((void*)pDsp);
|
||||
PADopen((void*)pDsp);
|
||||
FileMcd_EmuOpen();
|
||||
if (systemsToReinstate & System_DEV9) DEV9open((void*)pDsp);
|
||||
if (systemsToReinstate & System_USB) USBopen((void*)pDsp);
|
||||
if (systemsToReinstate & System_FW) FWopen();
|
||||
if (systemsToReinstate & System_SPU2) SPU2open((void*)pDsp);
|
||||
if (systemsToReinstate & System_PAD) PADopen((void*)pDsp);
|
||||
if (systemsToReinstate & System_MCD) FileMcd_EmuOpen();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ void SysThreadBase::Suspend(bool isBlocking)
|
|||
// The previous suspension state; true if the thread was running or false if it was
|
||||
// closed, not running, or paused.
|
||||
//
|
||||
void SysThreadBase::Pause(bool debug)
|
||||
void SysThreadBase::Pause(SystemsMask systemsToTearDown, bool debug)
|
||||
{
|
||||
if (IsSelf() || !IsRunning())
|
||||
return;
|
||||
|
@ -146,6 +146,7 @@ void SysThreadBase::Pause(bool debug)
|
|||
if ((m_ExecMode == ExecMode_Closed) || (m_ExecMode == ExecMode_Paused))
|
||||
return;
|
||||
|
||||
m_SystemsToTearDown.store(systemsToTearDown, std::memory_order_relaxed);
|
||||
if (m_ExecMode == ExecMode_Opened)
|
||||
m_ExecMode = ExecMode_Pausing;
|
||||
|
||||
|
@ -281,7 +282,7 @@ void SysThreadBase::OnCleanupInThread()
|
|||
}
|
||||
|
||||
void SysThreadBase::OnSuspendInThread() {}
|
||||
void SysThreadBase::OnResumeInThread(bool isSuspended) {}
|
||||
void SysThreadBase::OnResumeInThread(SystemsMask systemsToReinstate) {}
|
||||
|
||||
// Tests for Pause and Suspend/Close requests. If the thread is trying to be paused or
|
||||
// closed, it will enter a wait/holding pattern here in this method until the managing
|
||||
|
@ -294,6 +295,8 @@ void SysThreadBase::OnResumeInThread(bool isSuspended) {}
|
|||
// continued execution unimpeded.
|
||||
bool SysThreadBase::StateCheckInThread()
|
||||
{
|
||||
SystemsMask systemsToTearDown {}; // Used for Pausing/Paused
|
||||
|
||||
switch (m_ExecMode.load())
|
||||
{
|
||||
|
||||
|
@ -314,7 +317,9 @@ bool SysThreadBase::StateCheckInThread()
|
|||
// -------------------------------------
|
||||
case ExecMode_Pausing:
|
||||
{
|
||||
OnPauseInThread();
|
||||
systemsToTearDown = m_SystemsToTearDown.exchange({}, std::memory_order_relaxed);
|
||||
|
||||
OnPauseInThread(systemsToTearDown);
|
||||
m_ExecMode = ExecMode_Paused;
|
||||
m_RunningLock.Release();
|
||||
}
|
||||
|
@ -328,8 +333,12 @@ bool SysThreadBase::StateCheckInThread()
|
|||
if (m_ExecMode != ExecMode_Closing)
|
||||
{
|
||||
if (g_CDVDReset)
|
||||
//AppCoreThread deals with Reseting CDVD
|
||||
OnResumeInThread(false);
|
||||
// AppCoreThread deals with Reseting CDVD
|
||||
// Reinit all but GS, USB, DEV9, CDVD (just like with isSuspend = false previously)
|
||||
OnResumeInThread(static_cast<SystemsMask>(~(System_GS|System_USB|System_DEV9|System_CDVD)));
|
||||
else
|
||||
// Reinit previously torn down systems
|
||||
OnResumeInThread(systemsToTearDown);
|
||||
|
||||
g_CDVDReset = false;
|
||||
break;
|
||||
|
@ -353,7 +362,7 @@ bool SysThreadBase::StateCheckInThread()
|
|||
m_sem_Resume.WaitWithoutYield();
|
||||
|
||||
m_RunningLock.Acquire();
|
||||
OnResumeInThread(true);
|
||||
OnResumeInThread(static_cast<SystemsMask>(-1)); // All systems
|
||||
g_CDVDReset = false;
|
||||
break;
|
||||
|
||||
|
|
|
@ -26,6 +26,18 @@ using namespace Threading;
|
|||
|
||||
typedef SafeArray<u8> VmStateBuffer;
|
||||
|
||||
enum SystemsMask : uint8_t
|
||||
{
|
||||
System_GS = 1 << 0,
|
||||
System_SPU2 = 1 << 1,
|
||||
System_PAD = 1 << 2,
|
||||
System_FW = 1 << 3,
|
||||
System_CDVD = 1 << 4,
|
||||
System_USB = 1 << 5,
|
||||
System_DEV9 = 1 << 6,
|
||||
System_MCD = 1 << 7,
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// SysThreadBase
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -65,6 +77,7 @@ public:
|
|||
|
||||
protected:
|
||||
std::atomic<ExecutionMode> m_ExecMode;
|
||||
std::atomic<SystemsMask> m_SystemsToTearDown {};
|
||||
|
||||
// This lock is used to avoid simultaneous requests to Suspend/Resume/Pause from
|
||||
// contending threads.
|
||||
|
@ -113,7 +126,7 @@ public:
|
|||
|
||||
virtual void Suspend(bool isBlocking = true);
|
||||
virtual void Resume();
|
||||
virtual void Pause(bool debug = false);
|
||||
virtual void Pause(SystemsMask systemsToTearDown, bool debug = false);
|
||||
virtual void PauseSelf();
|
||||
virtual void PauseSelfDebug();
|
||||
|
||||
|
@ -146,15 +159,16 @@ protected:
|
|||
// prior to pausing the thread (ie, when Pause() has been called on a separate thread,
|
||||
// requesting this thread pause itself temporarily). After this is called, the thread
|
||||
// enters a waiting state on the m_sem_Resume semaphore.
|
||||
virtual void OnPauseInThread() = 0;
|
||||
// Parameter:
|
||||
// systemsToTearDown - a bitmask of systems to call Close functions on.
|
||||
virtual void OnPauseInThread(SystemsMask systemsToTearDown) = 0;
|
||||
|
||||
// Extending classes should implement this, but should not call it. The parent class
|
||||
// handles invocation by the following guidelines: Called from StateCheckInThread() after the
|
||||
// thread has been suspended and then subsequently resumed.
|
||||
// Parameter:
|
||||
// isSuspended - set to TRUE if the thread is returning from a suspended state, or
|
||||
// FALSE if it's returning from a paused state.
|
||||
virtual void OnResumeInThread(bool isSuspended) = 0;
|
||||
// systemsToTearDown - a bitmask of systems to call Open functions on.
|
||||
virtual void OnResumeInThread(SystemsMask systemsToReinstate) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -220,15 +234,18 @@ protected:
|
|||
|
||||
virtual void Start();
|
||||
virtual void OnStart();
|
||||
virtual void OnSuspendInThread();
|
||||
virtual void OnPauseInThread() {}
|
||||
virtual void OnResumeInThread(bool IsSuspended);
|
||||
virtual void OnSuspendInThread() override;
|
||||
virtual void OnPauseInThread(SystemsMask systemsToTearDown) override { TearDownSystems(systemsToTearDown); }
|
||||
virtual void OnResumeInThread(SystemsMask systemsToReinstate) override;
|
||||
virtual void OnCleanupInThread();
|
||||
virtual void ExecuteTaskInThread();
|
||||
virtual void DoCpuReset();
|
||||
virtual void DoCpuExecute();
|
||||
|
||||
void _StateCheckThrows();
|
||||
|
||||
private:
|
||||
void TearDownSystems(SystemsMask systemsToTearDown);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -577,7 +577,7 @@ void AppCoreThread::DoCpuReset()
|
|||
_parent::DoCpuReset();
|
||||
}
|
||||
|
||||
void AppCoreThread::OnResumeInThread(bool isSuspended)
|
||||
void AppCoreThread::OnResumeInThread(SystemsMask systemsToReinstate)
|
||||
{
|
||||
if (m_resetCdvd)
|
||||
{
|
||||
|
@ -586,10 +586,10 @@ void AppCoreThread::OnResumeInThread(bool isSuspended)
|
|||
DoCDVDopen();
|
||||
m_resetCdvd = false;
|
||||
}
|
||||
else if (isSuspended)
|
||||
else if (systemsToReinstate & System_CDVD)
|
||||
DoCDVDopen();
|
||||
|
||||
_parent::OnResumeInThread(isSuspended);
|
||||
_parent::OnResumeInThread(systemsToReinstate);
|
||||
PostCoreStatus(CoreThread_Resumed);
|
||||
}
|
||||
|
||||
|
@ -720,7 +720,7 @@ void SysExecEvent_CoreThreadClose::InvokeEvent()
|
|||
|
||||
void SysExecEvent_CoreThreadPause::InvokeEvent()
|
||||
{
|
||||
ScopedCoreThreadPause paused_core;
|
||||
ScopedCoreThreadPause paused_core(m_systemsToTearDown);
|
||||
_post_and_wait(paused_core);
|
||||
paused_core.AllowResume();
|
||||
}
|
||||
|
@ -820,7 +820,7 @@ ScopedCoreThreadClose::~ScopedCoreThreadClose()
|
|||
DESTRUCTOR_CATCHALL
|
||||
}
|
||||
|
||||
ScopedCoreThreadPause::ScopedCoreThreadPause()
|
||||
ScopedCoreThreadPause::ScopedCoreThreadPause(SystemsMask systemsToTearDown)
|
||||
{
|
||||
if (ScopedCore_IsFullyClosed || ScopedCore_IsPaused)
|
||||
{
|
||||
|
@ -829,11 +829,11 @@ ScopedCoreThreadPause::ScopedCoreThreadPause()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!PostToSysExec(std::make_unique<SysExecEvent_CoreThreadPause>()))
|
||||
if (!PostToSysExec(std::make_unique<SysExecEvent_CoreThreadPause>(systemsToTearDown)))
|
||||
{
|
||||
m_alreadyStopped = CoreThread.IsPaused();
|
||||
if (!m_alreadyStopped)
|
||||
CoreThread.Pause();
|
||||
CoreThread.Pause(systemsToTearDown);
|
||||
}
|
||||
|
||||
ScopedCore_IsPaused = true;
|
||||
|
|
|
@ -119,13 +119,17 @@ public:
|
|||
virtual ~SysExecEvent_CoreThreadPause() = default;
|
||||
SysExecEvent_CoreThreadPause* Clone() const { return new SysExecEvent_CoreThreadPause(*this); }
|
||||
|
||||
SysExecEvent_CoreThreadPause(SynchronousActionState* sync = NULL, SynchronousActionState* resume_sync = NULL, Threading::Mutex* mtx_resume = NULL)
|
||||
SysExecEvent_CoreThreadPause(SystemsMask systemsToTearDown, SynchronousActionState* sync = NULL, SynchronousActionState* resume_sync = NULL, Threading::Mutex* mtx_resume = NULL)
|
||||
: BaseSysExecEvent_ScopedCore(sync, resume_sync, mtx_resume)
|
||||
, m_systemsToTearDown(systemsToTearDown)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void InvokeEvent();
|
||||
|
||||
private:
|
||||
SystemsMask m_systemsToTearDown;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -160,7 +164,7 @@ protected:
|
|||
virtual void OnResumeReady();
|
||||
virtual void OnPause();
|
||||
virtual void OnPauseDebug();
|
||||
virtual void OnResumeInThread(bool IsSuspended);
|
||||
virtual void OnResumeInThread(SystemsMask systemsToReinstate) override;
|
||||
virtual void OnSuspendInThread();
|
||||
virtual void OnCleanupInThread();
|
||||
virtual void VsyncInThread();
|
||||
|
@ -242,7 +246,7 @@ struct ScopedCoreThreadPause : public BaseScopedCoreThread
|
|||
typedef BaseScopedCoreThread _parent;
|
||||
|
||||
public:
|
||||
ScopedCoreThreadPause();
|
||||
ScopedCoreThreadPause(SystemsMask systemsToTearDown = {});
|
||||
virtual ~ScopedCoreThreadPause();
|
||||
};
|
||||
|
||||
|
|
|
@ -1016,7 +1016,7 @@ void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_As_Click(wxCommandEvent& e
|
|||
// Ensure emulation is paused so that the correct image is captured
|
||||
bool wasPaused = CoreThread.IsPaused();
|
||||
if (!wasPaused)
|
||||
CoreThread.Pause();
|
||||
CoreThread.Pause({});
|
||||
|
||||
wxFileDialog fileDialog(this, _("Select a file"), g_Conf->Folders.Snapshots.ToAscii(), wxEmptyString, "PNG files (*.png)|*.png", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
|
||||
|
|
|
@ -681,7 +681,7 @@ protected:
|
|||
|
||||
PatchesVerboseReset();
|
||||
|
||||
GetCoreThread().Pause();
|
||||
GetCoreThread().Pause({});
|
||||
SysClearExecutionCache();
|
||||
|
||||
for (uint i = 0; i < ArraySize(SavestateEntries); ++i)
|
||||
|
|
Loading…
Reference in New Issue