Merge pull request #14143 from jordan-woyak/set-state-from-cpu
Core: Allow CPUManager::SetStepping to be called from the CPU thread to no longer rely on host to exit stepping mode.
This commit is contained in:
@@ -313,16 +313,12 @@ void UndeclareAsGPUThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For the CPU Thread only.
|
// For the CPU Thread only.
|
||||||
static void CPUSetInitialExecutionState(bool force_paused = false)
|
static void CPUSetInitialExecutionState(Core::System& system, bool force_paused = false)
|
||||||
{
|
{
|
||||||
// The CPU starts in stepping state, and will wait until a new state is set before executing.
|
// The CPU starts in stepping state, and will wait until a new state is set before executing.
|
||||||
// SetState isn't safe to call from the CPU thread, so we ask the host thread to call it.
|
const bool paused = SConfig::GetInstance().bBootToPause || force_paused;
|
||||||
QueueHostJob([force_paused](Core::System& system) {
|
SetState(system, paused ? State::Paused : State::Running, true, true);
|
||||||
bool paused = SConfig::GetInstance().bBootToPause || force_paused;
|
Host_UpdateDisasmDialog();
|
||||||
SetState(system, paused ? State::Paused : State::Running, true, true);
|
|
||||||
Host_UpdateDisasmDialog();
|
|
||||||
Host_Message(HostMessageID::WMUserCreate);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the CPU thread, which is a CPU + Video thread in Single Core mode.
|
// Create the CPU thread, which is a CPU + Video thread in Single Core mode.
|
||||||
@@ -371,7 +367,7 @@ static void CpuThread(Core::System& system, const std::optional<std::string>& sa
|
|||||||
if (!gdb_socket.empty() && !AchievementManager::GetInstance().IsHardcoreModeActive())
|
if (!gdb_socket.empty() && !AchievementManager::GetInstance().IsHardcoreModeActive())
|
||||||
{
|
{
|
||||||
GDBStub::InitLocal(gdb_socket.data());
|
GDBStub::InitLocal(gdb_socket.data());
|
||||||
CPUSetInitialExecutionState(true);
|
CPUSetInitialExecutionState(system, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -380,11 +376,11 @@ static void CpuThread(Core::System& system, const std::optional<std::string>& sa
|
|||||||
if (gdb_port > 0 && !AchievementManager::GetInstance().IsHardcoreModeActive())
|
if (gdb_port > 0 && !AchievementManager::GetInstance().IsHardcoreModeActive())
|
||||||
{
|
{
|
||||||
GDBStub::Init(gdb_port);
|
GDBStub::Init(gdb_port);
|
||||||
CPUSetInitialExecutionState(true);
|
CPUSetInitialExecutionState(system, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CPUSetInitialExecutionState();
|
CPUSetInitialExecutionState(system);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,7 +426,7 @@ static void FifoPlayerThread(Core::System& system, const std::optional<std::stri
|
|||||||
s_state.compare_exchange_strong(expected, State::Running);
|
s_state.compare_exchange_strong(expected, State::Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
CPUSetInitialExecutionState();
|
CPUSetInitialExecutionState(system);
|
||||||
|
|
||||||
system.GetCPU().Run();
|
system.GetCPU().Run();
|
||||||
|
|
||||||
|
|||||||
@@ -143,8 +143,7 @@ bool IsGPUThread();
|
|||||||
|
|
||||||
bool WantsDeterminism();
|
bool WantsDeterminism();
|
||||||
|
|
||||||
// SetState can't be called by the CPU thread, but can be called by any thread that isn't launched
|
// SetState can be called from any thread.
|
||||||
// by the emulator core.
|
|
||||||
void SetState(Core::System& system, State state, bool report_state_change = true,
|
void SetState(Core::System& system, State state, bool report_state_change = true,
|
||||||
bool override_achievement_restrictions = false);
|
bool override_achievement_restrictions = false);
|
||||||
State GetState(Core::System& system);
|
State GetState(Core::System& system);
|
||||||
|
|||||||
@@ -308,16 +308,18 @@ void CPUManager::SetStepping(bool stepping)
|
|||||||
{
|
{
|
||||||
SetStateLocked(State::Stepping);
|
SetStateLocked(State::Stepping);
|
||||||
|
|
||||||
while (m_state_cpu_thread_active)
|
if (!Core::IsCPUThread())
|
||||||
{
|
{
|
||||||
m_state_cpu_idle_cvar.wait(state_lock);
|
while (m_state_cpu_thread_active)
|
||||||
|
m_state_cpu_idle_cvar.wait(state_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunAdjacentSystems(false);
|
RunAdjacentSystems(false);
|
||||||
}
|
}
|
||||||
else if (SetStateLocked(State::Running))
|
else if (SetStateLocked(State::Running))
|
||||||
{
|
{
|
||||||
m_state_cpu_cvar.notify_one();
|
if (!Core::IsCPUThread())
|
||||||
|
m_state_cpu_cvar.notify_one();
|
||||||
m_time_played_finish_sync.Set();
|
m_time_played_finish_sync.Set();
|
||||||
RunAdjacentSystems(true);
|
RunAdjacentSystems(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public:
|
|||||||
// StepOpcode (Steps one Opcode)
|
// StepOpcode (Steps one Opcode)
|
||||||
void StepOpcode(Common::Event* event = nullptr);
|
void StepOpcode(Common::Event* event = nullptr);
|
||||||
|
|
||||||
// Enable or Disable Stepping. [Will deadlock if called from a system thread]
|
// Enable or Disable Stepping.
|
||||||
void SetStepping(bool stepping);
|
void SetStepping(bool stepping);
|
||||||
|
|
||||||
// Breakpoint activation for system threads. Similar to SetStepping(true).
|
// Breakpoint activation for system threads. Similar to SetStepping(true).
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ enum class HostMessageID
|
|||||||
{
|
{
|
||||||
// Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
|
// Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
|
||||||
WMUserStop = 10,
|
WMUserStop = 10,
|
||||||
WMUserCreate,
|
|
||||||
WMUserSetCursor,
|
|
||||||
WMUserJobDispatch,
|
WMUserJobDispatch,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user