mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 07:05:40 +00:00
System: Fix lockup with runahead enabled
This commit is contained in:
parent
18ca0da78d
commit
3e8f2f6b1c
|
@ -2016,7 +2016,7 @@ bool CPU::UpdateDebugDispatcherFlag()
|
|||
return true;
|
||||
}
|
||||
|
||||
void CPU::ExitExecution()
|
||||
[[noreturn]] void CPU::ExitExecution()
|
||||
{
|
||||
// can't exit while running events without messing things up
|
||||
DebugAssert(!TimingEvents::IsRunningEvents());
|
||||
|
|
|
@ -145,7 +145,7 @@ void ExecutionModeChanged();
|
|||
void Execute();
|
||||
|
||||
// Forces an early exit from the CPU dispatcher.
|
||||
void ExitExecution();
|
||||
[[noreturn]] void ExitExecution();
|
||||
|
||||
ALWAYS_INLINE static Registers& GetRegs()
|
||||
{
|
||||
|
|
|
@ -204,7 +204,7 @@ static u32 CompressAndWriteStateData(std::FILE* fp, std::span<const u8> src, Sav
|
|||
static bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display, bool is_memory_state);
|
||||
|
||||
static bool IsExecutionInterrupted();
|
||||
static void ExitExecution();
|
||||
static void CheckForAndExitExecution();
|
||||
|
||||
static void SetRewinding(bool enabled);
|
||||
static bool SaveRewindState();
|
||||
|
@ -557,15 +557,20 @@ bool System::IsRunning()
|
|||
return s_state == State::Running;
|
||||
}
|
||||
|
||||
bool System::IsExecutionInterrupted()
|
||||
ALWAYS_INLINE bool System::IsExecutionInterrupted()
|
||||
{
|
||||
return s_state != State::Running || s_system_interrupted;
|
||||
}
|
||||
|
||||
void System::ExitExecution()
|
||||
ALWAYS_INLINE_RELEASE void System::CheckForAndExitExecution()
|
||||
{
|
||||
TimingEvents::CancelRunningEvent();
|
||||
CPU::ExitExecution();
|
||||
if (IsExecutionInterrupted()) [[unlikely]]
|
||||
{
|
||||
s_system_interrupted = false;
|
||||
|
||||
TimingEvents::CancelRunningEvent();
|
||||
CPU::ExitExecution();
|
||||
}
|
||||
}
|
||||
|
||||
bool System::IsPaused()
|
||||
|
@ -2048,13 +2053,7 @@ void System::FrameDone()
|
|||
Host::PumpMessagesOnCPUThread();
|
||||
InputManager::PollSources();
|
||||
g_gpu->RestoreDeviceContext();
|
||||
|
||||
if (IsExecutionInterrupted())
|
||||
{
|
||||
s_system_interrupted = false;
|
||||
ExitExecution();
|
||||
return;
|
||||
}
|
||||
CheckForAndExitExecution();
|
||||
}
|
||||
|
||||
if (DoRunahead())
|
||||
|
@ -2159,13 +2158,7 @@ void System::FrameDone()
|
|||
{
|
||||
Host::PumpMessagesOnCPUThread();
|
||||
InputManager::PollSources();
|
||||
|
||||
if (IsExecutionInterrupted())
|
||||
{
|
||||
s_system_interrupted = false;
|
||||
ExitExecution();
|
||||
return;
|
||||
}
|
||||
CheckForAndExitExecution();
|
||||
}
|
||||
|
||||
g_gpu->RestoreDeviceContext();
|
||||
|
@ -4831,6 +4824,8 @@ bool System::DoRunahead()
|
|||
|
||||
// we don't want to save the frame we just loaded. but we are "one frame ahead", because the frame we just tossed
|
||||
// was never saved, so return but don't decrement the counter
|
||||
InterruptExecution();
|
||||
CheckForAndExitExecution();
|
||||
return true;
|
||||
}
|
||||
else if (s_runahead_replay_frames == 0)
|
||||
|
|
|
@ -384,7 +384,7 @@ void TimingEvents::CommitLeftoverTicks()
|
|||
{
|
||||
#ifdef _DEBUG
|
||||
if (s_state.event_run_tick_counter > s_state.global_tick_counter)
|
||||
WARNING_LOG("Late-running {} ticks before execution", s_state.event_run_tick_counter - s_state.global_tick_counter);
|
||||
DEV_LOG("Late-running {} ticks before execution", s_state.event_run_tick_counter - s_state.global_tick_counter);
|
||||
#endif
|
||||
|
||||
CommitGlobalTicks(s_state.event_run_tick_counter);
|
||||
|
@ -441,6 +441,7 @@ bool TimingEvents::DoState(StateWrapper& sw)
|
|||
}
|
||||
|
||||
DEBUG_LOG("Loaded {} events from save state.", event_count);
|
||||
s_state.current_event = nullptr;
|
||||
|
||||
// Add pending ticks to the CPU, this'll happen if we saved state when we weren't paused.
|
||||
const TickCount pending_ticks =
|
||||
|
@ -489,7 +490,12 @@ bool TimingEvents::DoState(StateWrapper& sw)
|
|||
}
|
||||
|
||||
DEBUG_LOG("Loaded {} events from save state.", event_count);
|
||||
|
||||
// Even if we're actually running an event, we don't want to set it to a new counter.
|
||||
s_state.current_event = nullptr;
|
||||
|
||||
SortEvents();
|
||||
UpdateCPUDowncount();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -498,7 +504,9 @@ bool TimingEvents::DoState(StateWrapper& sw)
|
|||
for (TimingEvent* event = s_state.active_events_head; event; event = event->next)
|
||||
{
|
||||
sw.Do(&event->m_name);
|
||||
sw.Do(&event->m_next_run_time);
|
||||
GlobalTicks next_run_time =
|
||||
(s_state.current_event == event) ? s_state.current_event_next_run_time : event->m_next_run_time;
|
||||
sw.Do(&next_run_time);
|
||||
sw.Do(&event->m_last_run_time);
|
||||
sw.Do(&event->m_period);
|
||||
sw.Do(&event->m_interval);
|
||||
|
|
Loading…
Reference in a new issue