diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 62e8ba1118..7e9df77b0e 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -163,7 +163,7 @@ bool isRunning() bool IsRunningInCurrentThread() { - return isRunning() && ((cpuThread.joinable()) || cpuThread.get_id() == std::this_thread::get_id()); + return isRunning() && ((!cpuThread.joinable()) || cpuThread.get_id() == std::this_thread::get_id()); } // This is called from the GUI thread. See the booting call schedule in diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index a01a232af8..a102f3ef84 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -68,7 +68,7 @@ u64 fakeDecStartTicks; u64 fakeTBStartValue; u64 fakeTBStartTicks; -Common::CriticalSection externalEventSection; +static Common::CriticalSection externalEventSection; void (*advanceCallback)(int cyclesExecuted) = NULL; diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index b622a19dc1..df63930019 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -27,7 +27,7 @@ #include "HW/Wiimote.h" #include "HW/DSP.h" #include "HW/HW.h" -#include "PowerPC/PowerPC.h" +#include "HW/CPU.h" #include "PowerPC/JitCommon/JitBase.h" #include "PluginManager.h" @@ -93,6 +93,7 @@ void DoState(PointerWrap &p) if (Core::g_CoreStartupParameter.bWii) Wiimote::DoState(p.GetPPtr(), p.GetMode()); + PowerPC::DoState(p); HW::DoState(p); CoreTiming::DoState(p); @@ -170,6 +171,9 @@ void CompressAndDumpState(saveStruct* saveArg) delete saveArg; + // For easy debugging + Common::SetCurrentThreadName("SaveState thread"); + // Moving to last overwritten save-state if (File::Exists(cur_filename.c_str())) { @@ -233,8 +237,8 @@ void CompressAndDumpState(saveStruct* saveArg) void SaveStateCallback(u64 userdata, int cyclesLate) { - // Stop the clock while we save the state - PowerPC::Pause(); + // Pause the core while we save the state + CCPU::EnableStepping(true); // Wait for the other threaded sub-systems to stop too SLEEP(100); @@ -264,16 +268,16 @@ void SaveStateCallback(u64 userdata, int cyclesLate) saveThread = std::thread(CompressAndDumpState, saveData); - // Resume the clock - PowerPC::Start(); + // Resume the core and disable stepping + CCPU::EnableStepping(false); } void LoadStateCallback(u64 userdata, int cyclesLate) { bool bCompressedState; - // Stop the clock while we load the state - PowerPC::Pause(); + // Stop the core while we load the state + CCPU::EnableStepping(true); // Wait for the other threaded sub-systems to stop too SLEEP(100); @@ -295,7 +299,7 @@ void LoadStateCallback(u64 userdata, int cyclesLate) { Core::DisplayMessage("State not found", 2000); // Resume the clock - PowerPC::Start(); + CCPU::EnableStepping(false); return; } @@ -314,7 +318,7 @@ void LoadStateCallback(u64 userdata, int cyclesLate) fclose(f); // Resume the clock - PowerPC::Start(); + CCPU::EnableStepping(false); return; } @@ -330,7 +334,7 @@ void LoadStateCallback(u64 userdata, int cyclesLate) { PanicAlertT("Error allocating buffer"); // Resume the clock - PowerPC::Start(); + CCPU::EnableStepping(false); return; } while (true) @@ -351,7 +355,7 @@ void LoadStateCallback(u64 userdata, int cyclesLate) fclose(f); delete[] buffer; // Resume the clock - PowerPC::Start(); + CCPU::EnableStepping(false); return; } @@ -388,7 +392,7 @@ void LoadStateCallback(u64 userdata, int cyclesLate) state_op_in_progress = false; // Resume the clock - PowerPC::Start(); + CCPU::EnableStepping(false); } void VerifyStateCallback(u64 userdata, int cyclesLate) diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 89e7c6aebe..54b411897e 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -34,7 +34,6 @@ namespace static volatile bool fifoStateRun = false; static volatile bool EmuRunning = false; static u8 *videoBuffer; -static Common::EventEx fifo_run_event; // STATE_TO_SAVE static int size = 0; } // namespace @@ -55,14 +54,12 @@ void Fifo_DoState(PointerWrap &p) void Fifo_Init() { videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE); - fifo_run_event.Init(); fifoStateRun = false; } void Fifo_Shutdown() { if (fifoStateRun) PanicAlert("Fifo shutting down while active"); - fifo_run_event.Shutdown(); FreeMemoryPages(videoBuffer, FIFO_SIZE); } @@ -89,6 +86,7 @@ void Fifo_SetRendering(bool enabled) void Fifo_ExitLoop() { Fifo_ExitLoopNonBlocking(); + EmuRunning = true; } // May be executed from any thread, even the graphics thread. @@ -100,14 +98,12 @@ void Fifo_ExitLoopNonBlocking() CommandProcessor::SetFifoIdleFromVideoPlugin(); // Terminate GPU thread loop fifoStateRun = false; - fifo_run_event.Set(); + EmuRunning = true; } void Fifo_RunLoop(bool run) { EmuRunning = run; - if (run) - fifo_run_event.Set(); } // Description: Fifo_EnterLoop() sends data through this function. @@ -164,8 +160,8 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) if (!fifoStateRun) break; - CommandProcessor::FifoCriticalEnter(); + // Create pointer to video data and send it to the VideoPlugin u32 readPtr = _fifo.CPReadPointer; u8 *uData = video_initialize.pGetMemoryPointer(readPtr); @@ -191,22 +187,28 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) CommandProcessor::SetStatus(); CommandProcessor::FifoCriticalLeave(); - - // Those two are pretty important and must be called in the FIFO Loop. - // If we don't, s_swapRequested (OGL only) or s_efbAccessRequested won't be set to false + + // This call is pretty important in DualCore mode and must be called in the FIFO Loop. + // If we don't, s_swapRequested or s_efbAccessRequested won't be set to false // leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down. - - VideoFifo_CheckAsyncRequest(); - + VideoFifo_CheckAsyncRequest(); } CommandProcessor::isFifoBusy = false; - CommandProcessor::SetFifoIdleFromVideoPlugin(); + if (EmuRunning) Common::YieldCPU(); else - fifo_run_event.MsgWait(); + { + // While the emu is paused, we still handle async request such as Savestates then sleep. + while (!EmuRunning) + { + video_initialize.pPeekMessages(); + VideoFifo_CheckAsyncRequest(); + Common::SleepCurrentThread(10); + } + } } } diff --git a/Source/Core/VideoCommon/Src/MainBase.cpp b/Source/Core/VideoCommon/Src/MainBase.cpp index 109a9fb977..3d1ede9caf 100644 --- a/Source/Core/VideoCommon/Src/MainBase.cpp +++ b/Source/Core/VideoCommon/Src/MainBase.cpp @@ -170,7 +170,8 @@ static volatile struct int mode; } s_doStateArgs; -// Run from the GPU thread on X11, CPU thread on the rest +// Depending on the threading mode (DC/SC) this can be called +// from either the GPU thread or the CPU thread static void check_DoState() { if (Common::AtomicLoadAcquire(s_doStateRequested)) { @@ -194,7 +195,7 @@ static void check_DoState() { } } -// Run from the CPU thread +// Run from the GUI thread void DoState(unsigned char **ptr, int mode) { s_doStateArgs.ptr = ptr; @@ -207,7 +208,7 @@ void DoState(unsigned char **ptr, int mode) Common::YieldCPU(); } else - check_DoState(); + check_DoState(); } void VideoFifo_CheckAsyncRequest()