CPU: Fix deadlocks by periodically yielding to the UI message pump.

This commit is contained in:
Jules Blok 2016-11-10 23:40:05 +01:00
parent 8203ea929b
commit 05a3f927ee
1 changed files with 23 additions and 17 deletions

View File

@ -160,11 +160,15 @@ void Stop()
std::unique_lock<std::mutex> state_lock(s_state_change_lock); std::unique_lock<std::mutex> state_lock(s_state_change_lock);
s_state = CPU_POWERDOWN; s_state = CPU_POWERDOWN;
s_state_cpu_cvar.notify_one(); s_state_cpu_cvar.notify_one();
// FIXME: MsgHandler can cause this to deadlock the GUI Thread. Remove the timeout.
bool success = s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::seconds(5), while (s_state_cpu_thread_active)
[] { return !s_state_cpu_thread_active; }); {
if (!success) std::cv_status status =
ERROR_LOG(POWERPC, "CPU Thread failed to acknowledge CPU_POWERDOWN. It may be deadlocked."); s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::milliseconds(100));
if (status == std::cv_status::timeout)
Host_YieldToUI();
}
RunAdjacentSystems(false); RunAdjacentSystems(false);
FlushStepSyncEventLocked(); FlushStepSyncEventLocked();
} }
@ -226,12 +230,13 @@ void EnableStepping(bool stepping)
{ {
SetStateLocked(CPU_STEPPING); SetStateLocked(CPU_STEPPING);
// Wait for the CPU Thread to leave the run loop while (s_state_cpu_thread_active)
// FIXME: MsgHandler can cause this to deadlock the GUI Thread. Remove the timeout. {
bool success = s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::seconds(5), std::cv_status status =
[] { return !s_state_cpu_thread_active; }); s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::milliseconds(100));
if (!success) if (status == std::cv_status::timeout)
ERROR_LOG(POWERPC, "Abandoned waiting for CPU Thread! The Core may be deadlocked."); Host_YieldToUI();
}
RunAdjacentSystems(false); RunAdjacentSystems(false);
} }
@ -276,12 +281,13 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
was_unpaused = s_state == CPU_RUNNING; was_unpaused = s_state == CPU_RUNNING;
SetStateLocked(CPU_STEPPING); SetStateLocked(CPU_STEPPING);
// FIXME: MsgHandler can cause this to deadlock the GUI Thread. Remove the timeout. while (s_state_cpu_thread_active)
bool success = s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::seconds(10), {
[] { return !s_state_cpu_thread_active; }); std::cv_status status =
if (!success) s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::milliseconds(100));
PanicAlert( if (status == std::cv_status::timeout)
"Abandoned CPU Thread synchronization in CPU::PauseAndLock! We'll probably crash now."); Host_YieldToUI();
}
if (control_adjacent) if (control_adjacent)
RunAdjacentSystems(false); RunAdjacentSystems(false);