Process savestates during single stepping.

This way we can handle them on the same thread, without weird delays.
This commit is contained in:
Unknown W. Brackets 2013-09-14 18:43:23 -07:00
parent 2d084ec747
commit 2ac5bcff1f
4 changed files with 34 additions and 22 deletions

View file

@ -25,6 +25,7 @@
#include "Core/Core.h"
#include "Core/Config.h"
#include "Core/MemMap.h"
#include "Core/SaveState.h"
#include "Core/System.h"
#include "Core/MIPS/MIPS.h"
#ifdef _WIN32
@ -36,10 +37,11 @@
#include "Core/Debugger/Breakpoints.h"
event m_hStepEvent;
recursive_mutex m_hStepMutex;
event m_hInactiveEvent;
recursive_mutex m_hInactiveMutex;
static event m_hStepEvent;
static recursive_mutex m_hStepMutex;
static event m_hInactiveEvent;
static recursive_mutex m_hInactiveMutex;
static bool singleStepPending = false;
#ifdef _WIN32
InputState input_state;
@ -151,6 +153,12 @@ void Core_RunLoop()
}
void Core_DoSingleStep()
{
singleStepPending = true;
m_hStepEvent.notify_one();
}
void Core_UpdateSingleStep()
{
m_hStepEvent.notify_one();
}
@ -175,18 +183,22 @@ reswitch:
switch (coreState)
{
case CORE_RUNNING:
//1: enter a fast runloop
// enter a fast runloop
Core_RunLoop();
break;
// We should never get here on Android.
case CORE_STEPPING:
singleStepPending = false;
if (coreStatePending) {
coreStatePending = false;
m_hInactiveEvent.notify_one();
}
//1: wait for step command..
// Check if there's any pending savestate actions.
SaveState::Process();
// wait for step command..
#if defined(USING_QT_UI) || defined(_DEBUG)
host->UpdateDisassembly();
host->UpdateMemView();
@ -198,18 +210,21 @@ reswitch:
#if defined(USING_QT_UI) || defined(_DEBUG)
host->SendCoreWait(false);
#endif
if (coreState == CORE_POWERDOWN)
return;
if (coreState != CORE_STEPPING)
#if defined(USING_QT_UI) && !defined(USING_GLES2)
if (coreState != CORE_STEPPING)
return;
#else
goto reswitch;
#endif
// No step pending? Let's go back to the wait.
if (!singleStepPending || coreState != CORE_STEPPING) {
if (coreState == CORE_POWERDOWN) {
return;
}
goto reswitch;
}
currentCPU = &mipsr4k;
Core_SingleStep();
//4: update disasm dialog
// update disasm dialog
#if defined(USING_QT_UI) || defined(_DEBUG)
host->UpdateDisassembly();
host->UpdateMemView();
@ -218,7 +233,7 @@ reswitch:
case CORE_POWERDOWN:
case CORE_ERROR:
//1: Exit loop!!
// Exit loop!!
if (coreStatePending) {
coreStatePending = false;
m_hInactiveEvent.notify_one();

View file

@ -28,6 +28,7 @@ void Core_ErrorPause();
// called from gui
void Core_EnableStepping(bool step);
void Core_DoSingleStep();
void Core_UpdateSingleStep();
void Core_Halt(const char *msg);

View file

@ -83,15 +83,10 @@ namespace SaveState
std::lock_guard<std::recursive_mutex> guard(mutex);
pending.push_back(op);
// Don't actually run it until next CoreTiming::Advance().
// Don't actually run it until next frame.
// It's possible there might be a duplicate but it won't hurt us.
if (Core_IsInactive() && __KernelIsRunning()) {
// Warning: this may run on a different thread.
needsProcess = true;
Process();
} else {
needsProcess = true;
}
Core_UpdateSingleStep();
}
void Load(const std::string &filename, Callback callback, void *cbUserData)

View file

@ -252,6 +252,7 @@ void Core_UpdateState(CoreState newState) {
if ((coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME) && newState != CORE_RUNNING)
coreStatePending = true;
coreState = newState;
Core_UpdateSingleStep();
}
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) {
@ -286,7 +287,7 @@ bool PSP_IsInited() {
void PSP_Shutdown() {
if (coreState == CORE_RUNNING)
coreState = CORE_ERROR;
Core_UpdateState(CORE_ERROR);
if (cpuThread != NULL) {
CPU_SetState(CPU_THREAD_SHUTDOWN);
CPU_WaitStatus(&CPU_IsShutdown);