mirror of
https://github.com/libretro/ppsspp.git
synced 2024-12-03 14:40:49 +00:00
Merge pull request #774 from unknownbrackets/savestates
Wait for jit to exit the runloop in debug, quit, and savestates
This commit is contained in:
commit
2891576549
@ -33,13 +33,24 @@
|
||||
// HANDLE m_hStepEvent;
|
||||
event m_hStepEvent;
|
||||
recursive_mutex m_hStepMutex;
|
||||
event m_hInactiveEvent;
|
||||
recursive_mutex m_hInactiveMutex;
|
||||
|
||||
// This can be read and written from ANYWHERE.
|
||||
volatile CoreState coreState = CORE_STEPPING;
|
||||
// Note: intentionally not used for CORE_NEXTFRAME.
|
||||
volatile bool coreStatePending = false;
|
||||
|
||||
void Core_UpdateState(CoreState newState)
|
||||
{
|
||||
if ((coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME) && newState != CORE_RUNNING)
|
||||
coreStatePending = true;
|
||||
coreState = newState;
|
||||
}
|
||||
|
||||
void Core_ErrorPause()
|
||||
{
|
||||
coreState = CORE_ERROR;
|
||||
Core_UpdateState(CORE_ERROR);
|
||||
}
|
||||
|
||||
void Core_Pause()
|
||||
@ -56,7 +67,7 @@ void Core_Halt(const char *msg)
|
||||
|
||||
void Core_Stop()
|
||||
{
|
||||
coreState = CORE_POWERDOWN;
|
||||
Core_UpdateState(CORE_POWERDOWN);
|
||||
m_hStepEvent.notify_one();
|
||||
}
|
||||
|
||||
@ -65,6 +76,23 @@ bool Core_IsStepping()
|
||||
return coreState == CORE_STEPPING || coreState == CORE_POWERDOWN;
|
||||
}
|
||||
|
||||
bool Core_IsInactive()
|
||||
{
|
||||
return coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME && !coreStatePending;
|
||||
}
|
||||
|
||||
void Core_WaitInactive()
|
||||
{
|
||||
while (!Core_IsInactive())
|
||||
m_hInactiveEvent.wait(m_hInactiveMutex);
|
||||
}
|
||||
|
||||
void Core_WaitInactive(int milliseconds)
|
||||
{
|
||||
while (!Core_IsInactive())
|
||||
m_hInactiveEvent.wait_for(m_hInactiveMutex, milliseconds);
|
||||
}
|
||||
|
||||
void Core_RunLoop()
|
||||
{
|
||||
while (!coreState) {
|
||||
@ -110,6 +138,10 @@ reswitch:
|
||||
|
||||
// We should never get here on Android.
|
||||
case CORE_STEPPING:
|
||||
if (coreStatePending)
|
||||
m_hInactiveEvent.notify_one();
|
||||
coreStatePending = false;
|
||||
|
||||
//1: wait for step command..
|
||||
#if defined(USING_QT_UI) || defined(_DEBUG)
|
||||
host->UpdateDisassembly();
|
||||
@ -142,8 +174,13 @@ reswitch:
|
||||
|
||||
case CORE_POWERDOWN:
|
||||
case CORE_ERROR:
|
||||
case CORE_NEXTFRAME:
|
||||
//1: Exit loop!!
|
||||
if (coreStatePending)
|
||||
m_hInactiveEvent.notify_one();
|
||||
coreStatePending = false;
|
||||
return;
|
||||
|
||||
case CORE_NEXTFRAME:
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -158,7 +195,7 @@ void Core_EnableStepping(bool step)
|
||||
#if defined(_DEBUG)
|
||||
host->SetDebugMode(true);
|
||||
#endif
|
||||
coreState = CORE_STEPPING;
|
||||
Core_UpdateState(CORE_STEPPING);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -166,6 +203,7 @@ void Core_EnableStepping(bool step)
|
||||
host->SetDebugMode(false);
|
||||
#endif
|
||||
coreState = CORE_RUNNING;
|
||||
coreStatePending = false;
|
||||
m_hStepEvent.notify_one();
|
||||
}
|
||||
}
|
||||
|
@ -43,5 +43,10 @@ enum CoreState
|
||||
CORE_NEXTFRAME,
|
||||
};
|
||||
|
||||
void Core_UpdateState(CoreState newState);
|
||||
bool Core_IsInactive();
|
||||
void Core_WaitInactive();
|
||||
void Core_WaitInactive(int milliseconds);
|
||||
|
||||
|
||||
extern volatile CoreState coreState;
|
||||
|
@ -133,14 +133,14 @@ void CBreakPoints::AddBreakPoint(u32 _iAddress, bool temp)
|
||||
void CBreakPoints::InvalidateJit(u32 _iAddress)
|
||||
{
|
||||
// Don't want to clear cache while running, I think?
|
||||
if (MIPSComp::jit && coreState == CORE_STEPPING)
|
||||
if (MIPSComp::jit && Core_IsInactive())
|
||||
MIPSComp::jit->ClearCacheAt(_iAddress);
|
||||
}
|
||||
|
||||
void CBreakPoints::InvalidateJit()
|
||||
{
|
||||
// Don't want to clear cache while running, I think?
|
||||
if (MIPSComp::jit && coreState == CORE_STEPPING)
|
||||
if (MIPSComp::jit && Core_IsInactive())
|
||||
MIPSComp::jit->ClearCache();
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ namespace MIPSInt
|
||||
void Int_Break(u32 op)
|
||||
{
|
||||
ERROR_LOG(CPU, "BREAK!");
|
||||
coreState = CORE_STEPPING;
|
||||
Core_UpdateState(CORE_STEPPING);
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ void Jit::WriteExitDestInEAX()
|
||||
|
||||
// TODO: "Ignore" this so other threads can continue?
|
||||
if (g_Config.bIgnoreBadMemAccess)
|
||||
MOV(32, M((void*)&coreState), Imm32(CORE_ERROR));
|
||||
ABI_CallFunctionA(thunks.ProtectFunction((void *) Core_UpdateState, 1), Imm32(CORE_ERROR));
|
||||
JMP(asm_.dispatcherCheckCoreState, true);
|
||||
}
|
||||
else
|
||||
|
@ -56,6 +56,10 @@ u8 *GetPointer(const u32 address)
|
||||
else
|
||||
{
|
||||
ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
if (!g_Config.bIgnoreBadMemAccess) {
|
||||
Core_EnableStepping(true);
|
||||
host->SetDebugMode(true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ namespace SaveState
|
||||
|
||||
// Don't actually run it until next CoreTiming::Advance().
|
||||
// It's possible there might be a duplicate but it won't hurt us.
|
||||
if (Core_IsStepping() && __KernelIsRunning())
|
||||
if (Core_IsInactive() && __KernelIsRunning())
|
||||
{
|
||||
// Warning: this may run on a different thread.
|
||||
Process(0, 0);
|
||||
|
@ -388,26 +388,10 @@ void SaveStateActionFinished(bool result, void *userdata)
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
MainWindow* mainWindow = (MainWindow*)userdata;
|
||||
|
||||
if (g_State.bEmuThreadStarted && mainWindow->GetNextState() == CORE_RUNNING)
|
||||
{
|
||||
if(mainWindow->GetDialogDisasm())
|
||||
mainWindow->GetDialogDisasm()->Go();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_FileLoadStateFile_triggered()
|
||||
{
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
if(dialogDisasm)
|
||||
{
|
||||
dialogDisasm->Stop();
|
||||
}
|
||||
}
|
||||
QFileDialog dialog(0,"Load state");
|
||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||
QStringList filters;
|
||||
@ -425,14 +409,6 @@ void MainWindow::on_action_FileLoadStateFile_triggered()
|
||||
|
||||
void MainWindow::on_action_FileSaveStateFile_triggered()
|
||||
{
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
if(dialogDisasm)
|
||||
{
|
||||
dialogDisasm->Stop();
|
||||
}
|
||||
}
|
||||
QFileDialog dialog(0,"Save state");
|
||||
dialog.setFileMode(QFileDialog::AnyFile);
|
||||
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
@ -449,27 +425,11 @@ void MainWindow::on_action_FileSaveStateFile_triggered()
|
||||
|
||||
void MainWindow::on_action_FileQuickloadState_triggered()
|
||||
{
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
if(dialogDisasm)
|
||||
{
|
||||
dialogDisasm->Stop();
|
||||
}
|
||||
}
|
||||
SaveState::LoadSlot(0, SaveStateActionFinished, this);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_FileQuickSaveState_triggered()
|
||||
{
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
if(dialogDisasm)
|
||||
{
|
||||
dialogDisasm->Stop();
|
||||
}
|
||||
}
|
||||
SaveState::SaveSlot(0, SaveStateActionFinished, this);
|
||||
}
|
||||
|
||||
|
@ -308,7 +308,7 @@ namespace MainWindow
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
|
||||
|
||||
Sleep(100);//UGLY wait for event instead
|
||||
Core_WaitInactive();
|
||||
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
@ -328,7 +328,7 @@ namespace MainWindow
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
|
||||
|
||||
Sleep(100);//UGLY wait for event instead
|
||||
Core_WaitInactive();
|
||||
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
@ -354,13 +354,6 @@ namespace MainWindow
|
||||
break;
|
||||
|
||||
case ID_FILE_LOADSTATEFILE:
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
|
||||
}
|
||||
if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn))
|
||||
{
|
||||
SetCursor(LoadCursor(0,IDC_WAIT));
|
||||
@ -369,13 +362,6 @@ namespace MainWindow
|
||||
break;
|
||||
|
||||
case ID_FILE_SAVESTATEFILE:
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
|
||||
}
|
||||
if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn))
|
||||
{
|
||||
SetCursor(LoadCursor(0,IDC_WAIT));
|
||||
@ -386,25 +372,11 @@ namespace MainWindow
|
||||
// TODO: Add UI for multiple slots
|
||||
|
||||
case ID_FILE_QUICKLOADSTATE:
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
|
||||
}
|
||||
SetCursor(LoadCursor(0,IDC_WAIT));
|
||||
SaveState::LoadSlot(0, SaveStateActionFinished);
|
||||
break;
|
||||
|
||||
case ID_FILE_QUICKSAVESTATE:
|
||||
if (g_State.bEmuThreadStarted)
|
||||
{
|
||||
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
|
||||
}
|
||||
SetCursor(LoadCursor(0,IDC_WAIT));
|
||||
SaveState::SaveSlot(0, SaveStateActionFinished);
|
||||
break;
|
||||
@ -643,7 +615,8 @@ namespace MainWindow
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
Sleep(100);//UGLY wait for event instead
|
||||
Core_Stop();
|
||||
Core_WaitInactive(200);
|
||||
EmuThread_Stop();
|
||||
|
||||
/*
|
||||
@ -896,13 +869,6 @@ namespace MainWindow
|
||||
if (!result)
|
||||
MessageBox(0, "Savestate failure. Please try again later.", "Sorry", MB_OK);
|
||||
SetCursor(LoadCursor(0, IDC_ARROW));
|
||||
|
||||
if (g_State.bEmuThreadStarted && nextState == CORE_RUNNING)
|
||||
{
|
||||
for (int i=0; i<numCPUs; i++)
|
||||
if (disasmWindow[i])
|
||||
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_GO, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SetNextState(CoreState state)
|
||||
|
2
native
2
native
@ -1 +1 @@
|
||||
Subproject commit a9a067ef8473628f170dfdab1f7692b53a5f130b
|
||||
Subproject commit 9c183fcca8416a34d510880d483ccf5f2ec573f4
|
Loading…
Reference in New Issue
Block a user