Merge pull request #12828 from JosJuice/unify-state-variables-2

Clean up Core::GetState
This commit is contained in:
Admiral H. Curtiss authored and GitHub committed 2024-06-22 20:20:54 +02:00
commit 9b33b777cf
40 files changed
+191 -178

No files matched your search

@@ -33,7 +33,7 @@ namespace ConfigLoaders
{
void SaveToSYSCONF(Config::LayerType layer, std::function<bool(const Config::Location&)> predicate)
{
if (Core::IsRunning(Core::System::GetInstance()))
if (!Core::IsUninitialized(Core::System::GetInstance()))
return;
IOS::HLE::Kernel ios;
@@ -183,7 +183,7 @@ public:
private:
void LoadFromSYSCONF(Config::Layer* layer)
{
if (Core::IsRunning(Core::System::GetInstance()))
if (!Core::IsUninitialized(Core::System::GetInstance()))
return;
IOS::HLE::Kernel ios;
+5 -5
View File
@@ -185,22 +185,22 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri
m_title_description = title_database.Describe(m_gametdb_id, language);
NOTICE_LOG_FMT(CORE, "Active title: {}", m_title_description);
Host_TitleChanged();
if (Core::IsRunning(system))
{
const bool is_running_or_starting = Core::IsRunningOrStarting(system);
if (is_running_or_starting)
Core::UpdateTitle(system);
}
Config::AddLayer(ConfigLoaders::GenerateGlobalGameConfigLoader(game_id, revision));
Config::AddLayer(ConfigLoaders::GenerateLocalGameConfigLoader(game_id, revision));
if (Core::IsRunning(system))
if (is_running_or_starting)
DolphinAnalytics::Instance().ReportGameStart();
}
void SConfig::OnNewTitleLoad(const Core::CPUThreadGuard& guard)
{
auto& system = guard.GetSystem();
if (!Core::IsRunning(system))
if (!Core::IsRunningOrStarting(system))
return;
auto& ppc_symbol_db = system.GetPPCSymbolDB();
+43 -54
View File
@@ -101,10 +101,6 @@ namespace Core
static bool s_wants_determinism;
// Declarations and definitions
static bool s_is_stopping = false;
static bool s_hardware_initialized = false;
static bool s_is_started = false;
static Common::Flag s_is_booting;
static std::thread s_emu_thread;
static std::vector<StateChangedCallbackFunc> s_on_state_changed_callbacks;
@@ -114,6 +110,10 @@ static std::atomic<double> s_last_actual_emulation_speed{1.0};
static bool s_frame_step = false;
static std::atomic<bool> s_stop_frame_step;
// The value Paused is never stored in this variable. The core is considered to be in
// the Paused state if this variable is Running and the CPU reports that it's stepping.
static std::atomic<State> s_state = State::Uninitialized;
#ifdef USE_MEMORYWATCHER
static std::unique_ptr<MemoryWatcher> s_memory_watcher;
#endif
@@ -190,7 +190,7 @@ std::string StopMessage(bool main_thread, std::string_view message)
void DisplayMessage(std::string message, int time_in_ms)
{
if (!IsRunning(Core::System::GetInstance()))
if (!IsRunningOrStarting(Core::System::GetInstance()))
return;
// Actually displaying non-ASCII could cause things to go pear-shaped
@@ -202,12 +202,18 @@ void DisplayMessage(std::string message, int time_in_ms)
bool IsRunning(Core::System& system)
{
return (GetState(system) != State::Uninitialized || s_hardware_initialized) && !s_is_stopping;
return s_state.load() == State::Running;
}
bool IsRunningAndStarted()
bool IsRunningOrStarting(Core::System& system)
{
return s_is_started && !s_is_stopping;
const State state = s_state.load();
return state == State::Running || state == State::Starting;
}
bool IsUninitialized(Core::System& system)
{
return s_state.load() == State::Uninitialized;
}
bool IsCPUThread()
@@ -236,7 +242,7 @@ bool Init(Core::System& system, std::unique_ptr<BootParameters> boot, const Wind
{
if (s_emu_thread.joinable())
{
if (IsRunning(system))
if (!IsUninitialized(system))
{
PanicAlertFmtT("Emu Thread already running");
return false;
@@ -262,7 +268,7 @@ bool Init(Core::System& system, std::unique_ptr<BootParameters> boot, const Wind
g_video_backend->PrepareWindow(prepared_wsi);
// Start the emu thread
s_is_booting.Set();
s_state.store(State::Starting);
s_emu_thread = std::thread(EmuThread, std::ref(system), std::move(boot), prepared_wsi);
return true;
}
@@ -281,15 +287,13 @@ static void ResetRumble()
// Called from GUI thread
void Stop(Core::System& system) // - Hammertime!
{
if (const State state = GetState(system);
state == State::Stopping || state == State::Uninitialized)
{
const State state = s_state.load();
if (state == State::Stopping || state == State::Uninitialized)
return;
}
AchievementManager::GetInstance().CloseGame();
s_is_stopping = true;
s_state.store(State::Stopping);
CallOnStateChangedCallbacks(State::Stopping);
@@ -394,7 +398,11 @@ static void CpuThread(Core::System& system, const std::optional<std::string>& sa
File::Delete(*savestate_path);
}
s_is_started = true;
// If s_state is Starting, change it to Running. But if it's already been set to Stopping
// by the host thread, don't change it.
State expected = State::Starting;
s_state.compare_exchange_strong(expected, State::Running);
{
#ifndef _WIN32
std::string gdb_socket = Config::Get(Config::MAIN_GDB_SOCKET);
@@ -426,8 +434,6 @@ static void CpuThread(Core::System& system, const std::optional<std::string>& sa
s_memory_watcher.reset();
#endif
s_is_started = false;
if (exception_handler)
EMM::UninstallExceptionHandler();
@@ -453,12 +459,15 @@ static void FifoPlayerThread(Core::System& system, const std::optional<std::stri
if (auto cpu_core = system.GetFifoPlayer().GetCPUCore())
{
system.GetPowerPC().InjectExternalCPUCore(cpu_core.get());
s_is_started = true;
// If s_state is Starting, change it to Running. But if it's already been set to Stopping
// by the host thread, don't change it.
State expected = State::Starting;
s_state.compare_exchange_strong(expected, State::Running);
CPUSetInitialExecutionState();
system.GetCPU().Run();
s_is_started = false;
system.GetPowerPC().InjectExternalCPUCore(nullptr);
system.GetFifoPlayer().Close();
}
@@ -479,10 +488,7 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
{
CallOnStateChangedCallbacks(State::Starting);
Common::ScopeGuard flag_guard{[] {
s_is_booting.Clear();
s_is_started = false;
s_is_stopping = false;
s_wants_determinism = false;
s_state.store(State::Uninitialized);
CallOnStateChangedCallbacks(State::Uninitialized);
@@ -557,8 +563,6 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
NetPlay::IsNetPlayRunning() ? &(boot_session_data.GetNetplaySettings()->sram) : nullptr);
Common::ScopeGuard hw_guard{[&system] {
// We must set up this flag before executing HW::Shutdown()
s_hardware_initialized = false;
INFO_LOG_FMT(CONSOLE, "{}", StopMessage(false, "Shutting down HW"));
HW::Shutdown(system);
INFO_LOG_FMT(CONSOLE, "{}", StopMessage(false, "HW shutdown"));
@@ -602,10 +606,6 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
AudioCommon::PostInitSoundStream(system);
// The hardware is initialized.
s_hardware_initialized = true;
s_is_booting.Clear();
// Set execution state to known values (CPU/FIFO/Audio Paused)
system.GetCPU().Break();
@@ -701,7 +701,7 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
void SetState(Core::System& system, State state, bool report_state_change)
{
// State cannot be controlled until the CPU Thread is operational
if (!IsRunningAndStarted())
if (s_state.load() != State::Running)
return;
switch (state)
@@ -732,21 +732,11 @@ void SetState(Core::System& system, State state, bool report_state_change)
State GetState(Core::System& system)
{
if (s_is_stopping)
return State::Stopping;
if (s_hardware_initialized)
{
if (system.GetCPU().IsStepping())
return State::Paused;
return State::Running;
}
if (s_is_booting.IsSet())
return State::Starting;
return State::Uninitialized;
const State state = s_state.load();
if (state == State::Running && system.GetCPU().IsStepping())
return State::Paused;
else
return state;
}
static std::string GenerateScreenshotFolderPath()
@@ -800,7 +790,7 @@ static bool PauseAndLock(Core::System& system, bool do_lock, bool unpause_on_unl
{
// WARNING: PauseAndLock is not fully threadsafe so is only valid on the Host Thread
if (!IsRunningAndStarted())
if (!IsRunning(system))
return true;
bool was_unpaused = true;
@@ -1027,13 +1017,12 @@ void HostDispatchJobs(Core::System& system)
HostJob job = std::move(s_host_jobs_queue.front());
s_host_jobs_queue.pop();
// NOTE: Memory ordering is important. The booting flag needs to be
// checked first because the state transition is:
// Core::State::Uninitialized: s_is_booting -> s_hardware_initialized
// We need to check variables in the same order as the state
// transition, otherwise we race and get transient failures.
if (!job.run_after_stop && !s_is_booting.IsSet() && !IsRunning(system))
continue;
if (!job.run_after_stop)
{
const State state = s_state.load();
if (state == State::Stopping || state == State::Uninitialized)
continue;
}
guard.unlock();
job.job(system);
+7 -2
View File
@@ -134,9 +134,14 @@ void UndeclareAsHostThread();
std::string StopMessage(bool main_thread, std::string_view message);
// Returns true when GetState returns Running or Paused.
bool IsRunning(Core::System& system);
bool IsRunningAndStarted(); // is running and the CPU loop has been entered
bool IsCPUThread(); // this tells us whether we are the CPU thread.
// Returns true when GetState returns Starting, Running or Paused.
bool IsRunningOrStarting(Core::System& system);
// Returns true when GetState returns Uninitialized.
bool IsUninitialized(Core::System& system);
bool IsCPUThread(); // this tells us whether we are the CPU thread.
bool IsGPUThread();
bool IsHostThread();
@@ -349,7 +349,7 @@ u32 PPCDebugInterface::ReadInstruction(const Core::CPUThreadGuard& guard, u32 ad
bool PPCDebugInterface::IsAlive() const
{
return Core::IsRunningAndStarted();
return Core::IsRunning(m_system);
}
bool PPCDebugInterface::IsBreakpoint(u32 address) const
+4 -4
View File
@@ -112,9 +112,9 @@ ESCore::~ESCore() = default;
ESDevice::ESDevice(EmulationKernel& ios, ESCore& core, const std::string& device_name)
: EmulationDevice(ios, device_name), m_core(core)
{
if (Core::IsRunningAndStarted())
auto& system = ios.GetSystem();
if (Core::IsRunning(system))
{
auto& system = ios.GetSystem();
auto& core_timing = system.GetCoreTiming();
core_timing.RemoveEvent(s_finish_init_event);
core_timing.ScheduleEvent(GetESBootTicks(ios.GetVersion()), s_finish_init_event);
@@ -446,7 +446,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
}
const u64 required_ios = tmd.GetIOSId();
if (!Core::IsRunningAndStarted())
if (!Core::IsRunning(system))
return LaunchTitle(required_ios, HangPPC::Yes);
core_timing.RemoveEvent(s_reload_ios_for_ppc_launch_event);
core_timing.ScheduleEvent(ticks, s_reload_ios_for_ppc_launch_event, required_ios);
@@ -475,7 +475,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
return false;
m_pending_ppc_boot_content_path = m_core.GetContentPath(tmd.GetTitleId(), content);
if (!Core::IsRunningAndStarted())
if (!Core::IsRunning(system))
return BootstrapPPC();
INFO_LOG_FMT(ACHIEVEMENTS,
+1 -1
View File
@@ -518,7 +518,7 @@ bool EmulationKernel::BootIOS(const u64 ios_title_id, HangPPC hang_ppc,
if (hang_ppc == HangPPC::Yes)
ResetAndPausePPC(m_system);
if (Core::IsRunningAndStarted())
if (Core::IsRunning(m_system))
{
m_system.GetCoreTiming().ScheduleEvent(GetIOSBootTicks(GetVersion()), s_event_finish_ios_boot,
ios_title_id);
+3 -3
View File
@@ -536,7 +536,7 @@ bool MovieManager::BeginRecordingInput(const ControllerTypeArray& controllers,
m_bongos |= (1 << i);
}
if (Core::IsRunningAndStarted())
if (Core::IsRunning(m_system))
{
const std::string save_path = File::GetUserPath(D_STATESAVES_IDX) + "dtm.sav";
if (File::Exists(save_path))
@@ -551,7 +551,7 @@ bool MovieManager::BeginRecordingInput(const ControllerTypeArray& controllers,
}
// Wiimotes cause desync issues if they're not reset before launching the game
if (!Core::IsRunningAndStarted())
if (!Core::IsRunning(m_system))
{
// This will also reset the Wiimotes for GameCube games, but that shouldn't do anything
Wiimote::ResetAllWiimotes();
@@ -1339,7 +1339,7 @@ void MovieManager::EndPlayInput(bool cont)
{
// We can be called by EmuThread during boot (CPU::State::PowerDown)
auto& cpu = m_system.GetCPU();
const bool was_running = Core::IsRunningAndStarted() && !cpu.IsStepping();
const bool was_running = Core::IsRunning(m_system) && !cpu.IsStepping();
if (was_running && Config::Get(Config::MAIN_MOVIE_PAUSE_MOVIE))
cpu.Break();
m_rerecords = 0;
+1 -1
View File
@@ -854,7 +854,7 @@ static void LoadFileStateData(const std::string& filename, std::vector<u8>& ret_
void LoadAs(Core::System& system, const std::string& filename)
{
if (!Core::IsRunning(system))
if (!Core::IsRunningOrStarting(system))
return;
if (NetPlay::IsNetPlayRunning())