Merge pull request #12117 from JosJuice/config-callback-cpu

Don't call RunAsCPUThread in config callbacks
This commit is contained in:
Admiral H. Curtiss 2023-08-26 16:34:46 +02:00 committed by GitHub
commit 2502e412b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 234 additions and 49 deletions

View File

@ -10,6 +10,7 @@
#include "AudioCommon/SurroundDecoder.h" #include "AudioCommon/SurroundDecoder.h"
#include "AudioCommon/WaveFile.h" #include "AudioCommon/WaveFile.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
class PointerWrap; class PointerWrap;
@ -120,5 +121,5 @@ private:
int m_config_timing_variance; int m_config_timing_variance;
bool m_config_audio_stretch; bool m_config_audio_stretch;
size_t m_config_changed_callback_id; Config::ConfigChangedCallbackID m_config_changed_callback_id;
}; };

View File

@ -16,7 +16,7 @@ namespace Config
using Layers = std::map<LayerType, std::shared_ptr<Layer>>; using Layers = std::map<LayerType, std::shared_ptr<Layer>>;
static Layers s_layers; static Layers s_layers;
static std::vector<std::pair<size_t, ConfigChangedCallback>> s_callbacks; static std::vector<std::pair<ConfigChangedCallbackID, ConfigChangedCallback>> s_callbacks;
static size_t s_next_callback_id = 0; static size_t s_next_callback_id = 0;
static u32 s_callback_guards = 0; static u32 s_callback_guards = 0;
static std::atomic<u64> s_config_version = 0; static std::atomic<u64> s_config_version = 0;
@ -65,15 +65,15 @@ void RemoveLayer(LayerType layer)
OnConfigChanged(); OnConfigChanged();
} }
size_t AddConfigChangedCallback(ConfigChangedCallback func) ConfigChangedCallbackID AddConfigChangedCallback(ConfigChangedCallback func)
{ {
const size_t callback_id = s_next_callback_id; const ConfigChangedCallbackID callback_id{s_next_callback_id};
++s_next_callback_id; ++s_next_callback_id;
s_callbacks.emplace_back(std::make_pair(callback_id, std::move(func))); s_callbacks.emplace_back(std::make_pair(callback_id, std::move(func)));
return callback_id; return callback_id;
} }
void RemoveConfigChangedCallback(size_t callback_id) void RemoveConfigChangedCallback(ConfigChangedCallbackID callback_id)
{ {
for (auto it = s_callbacks.begin(); it != s_callbacks.end(); ++it) for (auto it = s_callbacks.begin(); it != s_callbacks.end(); ++it)
{ {
@ -138,7 +138,6 @@ void Shutdown()
WriteLock lock(s_layers_rw_lock); WriteLock lock(s_layers_rw_lock);
s_layers.clear(); s_layers.clear();
s_callbacks.clear();
} }
void ClearCurrentRunLayer() void ClearCurrentRunLayer()

View File

@ -15,6 +15,14 @@
namespace Config namespace Config
{ {
struct ConfigChangedCallbackID
{
size_t id = -1;
bool operator==(const ConfigChangedCallbackID&) const = default;
bool operator!=(const ConfigChangedCallbackID&) const = default;
};
using ConfigChangedCallback = std::function<void()>; using ConfigChangedCallback = std::function<void()>;
// Layer management // Layer management
@ -22,9 +30,10 @@ void AddLayer(std::unique_ptr<ConfigLayerLoader> loader);
std::shared_ptr<Layer> GetLayer(LayerType layer); std::shared_ptr<Layer> GetLayer(LayerType layer);
void RemoveLayer(LayerType layer); void RemoveLayer(LayerType layer);
// returns an ID that can be passed to RemoveConfigChangedCallback() // Returns an ID that can be passed to RemoveConfigChangedCallback().
size_t AddConfigChangedCallback(ConfigChangedCallback func); // The callback may be called from any thread.
void RemoveConfigChangedCallback(size_t callback_id); ConfigChangedCallbackID AddConfigChangedCallback(ConfigChangedCallback func);
void RemoveConfigChangedCallback(ConfigChangedCallbackID callback_id);
void OnConfigChanged(); void OnConfigChanged();
// Returns the number of times the config has changed in the current execution of the program // Returns the number of times the config has changed in the current execution of the program

View File

@ -59,6 +59,8 @@ add_library(core
Core.h Core.h
CoreTiming.cpp CoreTiming.cpp
CoreTiming.h CoreTiming.h
CPUThreadConfigCallback.cpp
CPUThreadConfigCallback.h
Debugger/CodeTrace.cpp Debugger/CodeTrace.cpp
Debugger/CodeTrace.h Debugger/CodeTrace.h
Debugger/DebugInterface.h Debugger/DebugInterface.h

View File

@ -0,0 +1,75 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/CPUThreadConfigCallback.h"
#include <atomic>
#include "Common/Assert.h"
#include "Common/Config/Config.h"
#include "Core/Core.h"
namespace
{
std::atomic<bool> s_should_run_callbacks = false;
static std::vector<
std::pair<CPUThreadConfigCallback::ConfigChangedCallbackID, Config::ConfigChangedCallback>>
s_callbacks;
static size_t s_next_callback_id = 0;
void RunCallbacks()
{
for (const auto& callback : s_callbacks)
callback.second();
}
void OnConfigChanged()
{
if (Core::IsCPUThread())
{
s_should_run_callbacks.store(false, std::memory_order_relaxed);
RunCallbacks();
}
else
{
s_should_run_callbacks.store(true, std::memory_order_relaxed);
}
}
}; // namespace
namespace CPUThreadConfigCallback
{
ConfigChangedCallbackID AddConfigChangedCallback(Config::ConfigChangedCallback func)
{
static auto s_config_changed_callback_id = Config::AddConfigChangedCallback(&OnConfigChanged);
const ConfigChangedCallbackID callback_id{s_next_callback_id};
++s_next_callback_id;
s_callbacks.emplace_back(std::make_pair(callback_id, std::move(func)));
return callback_id;
}
void RemoveConfigChangedCallback(ConfigChangedCallbackID callback_id)
{
for (auto it = s_callbacks.begin(); it != s_callbacks.end(); ++it)
{
if (it->first == callback_id)
{
s_callbacks.erase(it);
return;
}
}
}
void CheckForConfigChanges()
{
DEBUG_ASSERT(Core::IsCPUThread());
if (s_should_run_callbacks.exchange(false, std::memory_order_relaxed))
RunCallbacks();
}
}; // namespace CPUThreadConfigCallback

View File

@ -0,0 +1,30 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "Common/Config/Config.h"
// This file lets you register callbacks like in Common/Config/Config.h, with the difference that
// callbacks registered here are guaranteed to run on the CPU thread. Callbacks registered here may
// run with a slight delay compared to regular config callbacks.
namespace CPUThreadConfigCallback
{
struct ConfigChangedCallbackID
{
size_t id = -1;
bool operator==(const ConfigChangedCallbackID&) const = default;
bool operator!=(const ConfigChangedCallbackID&) const = default;
};
// returns an ID that can be passed to RemoveConfigChangedCallback()
ConfigChangedCallbackID AddConfigChangedCallback(Config::ConfigChangedCallback func);
void RemoveConfigChangedCallback(ConfigChangedCallbackID callback_id);
// Should be called regularly from the CPU thread
void CheckForConfigChanges();
}; // namespace CPUThreadConfigCallback

View File

@ -41,6 +41,7 @@
#include "Core/AchievementManager.h" #include "Core/AchievementManager.h"
#include "Core/Boot/Boot.h" #include "Core/Boot/Boot.h"
#include "Core/BootManager.h" #include "Core/BootManager.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/CoreTiming.h" #include "Core/CoreTiming.h"
@ -511,6 +512,9 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
DeclareAsCPUThread(); DeclareAsCPUThread();
s_frame_step = false; s_frame_step = false;
// If settings have changed since the previous run, notify callbacks.
CPUThreadConfigCallback::CheckForConfigChanges();
// Switch the window used for inputs to the render window. This way, the cursor position // Switch the window used for inputs to the render window. This way, the cursor position
// is relative to the render window, instead of the main window. // is relative to the render window, instead of the main window.
ASSERT(g_controller_interface.IsInit()); ASSERT(g_controller_interface.IsInit());

View File

@ -16,6 +16,7 @@
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/SPSCQueue.h" #include "Common/SPSCQueue.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
@ -88,8 +89,8 @@ void CoreTimingManager::UnregisterAllEvents()
void CoreTimingManager::Init() void CoreTimingManager::Init()
{ {
m_registered_config_callback_id = Config::AddConfigChangedCallback( m_registered_config_callback_id =
[this]() { Core::RunAsCPUThread([this]() { RefreshConfig(); }); }); CPUThreadConfigCallback::AddConfigChangedCallback([this]() { RefreshConfig(); });
RefreshConfig(); RefreshConfig();
m_last_oc_factor = m_config_oc_factor; m_last_oc_factor = m_config_oc_factor;
@ -118,7 +119,7 @@ void CoreTimingManager::Shutdown()
MoveEvents(); MoveEvents();
ClearPendingEvents(); ClearPendingEvents();
UnregisterAllEvents(); UnregisterAllEvents();
Config::RemoveConfigChangedCallback(m_registered_config_callback_id); CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id);
} }
void CoreTimingManager::RefreshConfig() void CoreTimingManager::RefreshConfig()
@ -311,11 +312,13 @@ void CoreTimingManager::MoveEvents()
void CoreTimingManager::Advance() void CoreTimingManager::Advance()
{ {
auto& power_pc = m_system.GetPowerPC(); CPUThreadConfigCallback::CheckForConfigChanges();
auto& ppc_state = power_pc.GetPPCState();
MoveEvents(); MoveEvents();
auto& power_pc = m_system.GetPowerPC();
auto& ppc_state = power_pc.GetPPCState();
int cyclesExecuted = m_globals.slice_length - DowncountToCycles(ppc_state.downcount); int cyclesExecuted = m_globals.slice_length - DowncountToCycles(ppc_state.downcount);
m_globals.global_timer += cyclesExecuted; m_globals.global_timer += cyclesExecuted;
m_last_oc_factor = m_config_oc_factor; m_last_oc_factor = m_config_oc_factor;

View File

@ -23,6 +23,7 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/SPSCQueue.h" #include "Common/SPSCQueue.h"
#include "Core/CPUThreadConfigCallback.h"
class PointerWrap; class PointerWrap;
@ -182,7 +183,7 @@ private:
EventType* m_ev_lost = nullptr; EventType* m_ev_lost = nullptr;
size_t m_registered_config_callback_id = 0; CPUThreadConfigCallback::ConfigChangedCallbackID m_registered_config_callback_id;
float m_config_oc_factor = 0.0f; float m_config_oc_factor = 0.0f;
float m_config_oc_inv_factor = 0.0f; float m_config_oc_inv_factor = 0.0f;
bool m_config_sync_on_skip_idle = false; bool m_config_sync_on_skip_idle = false;

View File

@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "Common/Assert.h" #include "Common/Assert.h"
#include "Common/Config/Config.h"
#include "Core/FifoPlayer/FifoDataFile.h" #include "Core/FifoPlayer/FifoDataFile.h"
#include "Core/PowerPC/CPUCoreBase.h" #include "Core/PowerPC/CPUCoreBase.h"
#include "VideoCommon/CPMemory.h" #include "VideoCommon/CPMemory.h"
@ -189,7 +190,7 @@ private:
CallbackFunc m_FileLoadedCb = nullptr; CallbackFunc m_FileLoadedCb = nullptr;
CallbackFunc m_FrameWrittenCb = nullptr; CallbackFunc m_FrameWrittenCb = nullptr;
size_t m_config_changed_callback_id; Config::ConfigChangedCallbackID m_config_changed_callback_id;
std::unique_ptr<FifoDataFile> m_File; std::unique_ptr<FifoDataFile> m_File;

View File

@ -2,6 +2,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/FreeLookConfig.h" #include "Core/FreeLookConfig.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/FreeLookSettings.h" #include "Core/Config/FreeLookSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Core.h" #include "Core/Core.h"
@ -37,7 +39,7 @@ void Config::Refresh()
{ {
if (!s_has_registered_callback) if (!s_has_registered_callback)
{ {
::Config::AddConfigChangedCallback([] { Core::RunAsCPUThread([] { s_config.Refresh(); }); }); CPUThreadConfigCallback::AddConfigChangedCallback([] { s_config.Refresh(); });
s_has_registered_callback = true; s_has_registered_callback = true;
} }

View File

@ -10,6 +10,7 @@
#include "AudioCommon/AudioCommon.h" #include "AudioCommon/AudioCommon.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/Host.h" #include "Core/Host.h"
#include "Core/PowerPC/GDBStub.h" #include "Core/PowerPC/GDBStub.h"
@ -75,6 +76,7 @@ void CPUManager::Run()
{ {
m_state_cpu_cvar.wait(state_lock, [this] { return !m_state_paused_and_locked; }); m_state_cpu_cvar.wait(state_lock, [this] { return !m_state_paused_and_locked; });
ExecutePendingJobs(state_lock); ExecutePendingJobs(state_lock);
CPUThreadConfigCallback::CheckForConfigChanges();
Common::Event gdb_step_sync_event; Common::Event gdb_step_sync_event;
switch (m_state) switch (m_state)
@ -113,6 +115,7 @@ void CPUManager::Run()
// Wait for step command. // Wait for step command.
m_state_cpu_cvar.wait(state_lock, [this, &state_lock, &gdb_step_sync_event] { m_state_cpu_cvar.wait(state_lock, [this, &state_lock, &gdb_step_sync_event] {
ExecutePendingJobs(state_lock); ExecutePendingJobs(state_lock);
CPUThreadConfigCallback::CheckForConfigChanges();
state_lock.unlock(); state_lock.unlock();
if (GDBStub::IsActive() && GDBStub::HasControl()) if (GDBStub::IsActive() && GDBStub::HasControl())
{ {

View File

@ -30,7 +30,7 @@ static std::array<u8, MAX_BBMOTES> s_last_connect_request_counter;
namespace namespace
{ {
static std::array<std::atomic<WiimoteSource>, MAX_BBMOTES> s_wiimote_sources; static std::array<std::atomic<WiimoteSource>, MAX_BBMOTES> s_wiimote_sources;
static std::optional<size_t> s_config_callback_id = std::nullopt; static std::optional<Config::ConfigChangedCallbackID> s_config_callback_id = std::nullopt;
WiimoteSource GetSource(unsigned int index) WiimoteSource GetSource(unsigned int index)
{ {

View File

@ -9,6 +9,7 @@
#include <string> #include <string>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/Config/Config.h"
#include "Core/HW/WiimoteCommon/WiimoteReport.h" #include "Core/HW/WiimoteCommon/WiimoteReport.h"
@ -343,6 +344,6 @@ private:
IMUCursorState m_imu_cursor_state; IMUCursorState m_imu_cursor_state;
size_t m_config_changed_callback_id; Config::ConfigChangedCallbackID m_config_changed_callback_id;
}; };
} // namespace WiimoteEmu } // namespace WiimoteEmu

View File

@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/Config/Config.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Common/Flag.h" #include "Common/Flag.h"
#include "Common/SPSCQueue.h" #include "Common/SPSCQueue.h"
@ -157,7 +158,7 @@ private:
bool m_speaker_enabled_in_dolphin_config = false; bool m_speaker_enabled_in_dolphin_config = false;
int m_balance_board_dump_port = 0; int m_balance_board_dump_port = 0;
size_t m_config_changed_callback_id; Config::ConfigChangedCallbackID m_config_changed_callback_id;
}; };
class WiimoteScannerBackend class WiimoteScannerBackend

View File

@ -15,6 +15,7 @@
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/SDCardUtil.h" #include "Common/SDCardUtil.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
#include "Core/Config/SessionSettings.h" #include "Core/Config/SessionSettings.h"
#include "Core/Core.h" #include "Core/Core.h"
@ -32,28 +33,24 @@ SDIOSlot0Device::SDIOSlot0Device(EmulationKernel& ios, const std::string& device
if (!Config::Get(Config::MAIN_ALLOW_SD_WRITES)) if (!Config::Get(Config::MAIN_ALLOW_SD_WRITES))
INFO_LOG_FMT(IOS_SD, "Writes to SD card disabled by user"); INFO_LOG_FMT(IOS_SD, "Writes to SD card disabled by user");
m_config_callback_id = Config::AddConfigChangedCallback([this] { RefreshConfig(); }); m_config_callback_id =
CPUThreadConfigCallback::AddConfigChangedCallback([this] { RefreshConfig(); });
m_sd_card_inserted = Config::Get(Config::MAIN_WII_SD_CARD); m_sd_card_inserted = Config::Get(Config::MAIN_WII_SD_CARD);
} }
SDIOSlot0Device::~SDIOSlot0Device() SDIOSlot0Device::~SDIOSlot0Device()
{ {
Config::RemoveConfigChangedCallback(m_config_callback_id); CPUThreadConfigCallback::RemoveConfigChangedCallback(m_config_callback_id);
} }
void SDIOSlot0Device::RefreshConfig() void SDIOSlot0Device::RefreshConfig()
{ {
if (m_sd_card_inserted != Config::Get(Config::MAIN_WII_SD_CARD))
{
Core::RunAsCPUThread([this] {
const bool sd_card_inserted = Config::Get(Config::MAIN_WII_SD_CARD); const bool sd_card_inserted = Config::Get(Config::MAIN_WII_SD_CARD);
if (m_sd_card_inserted != sd_card_inserted) if (m_sd_card_inserted != sd_card_inserted)
{ {
m_sd_card_inserted = sd_card_inserted; m_sd_card_inserted = sd_card_inserted;
EventNotify(); EventNotify();
} }
});
}
} }
void SDIOSlot0Device::DoState(PointerWrap& p) void SDIOSlot0Device::DoState(PointerWrap& p)

View File

@ -10,6 +10,7 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/IOFile.h" #include "Common/IOFile.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/IOS/Device.h" #include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h" #include "Core/IOS/IOS.h"
@ -166,7 +167,7 @@ private:
File::IOFile m_card; File::IOFile m_card;
size_t m_config_callback_id; CPUThreadConfigCallback::ConfigChangedCallbackID m_config_callback_id;
bool m_sd_card_inserted = false; bool m_sd_card_inserted = false;
}; };
} // namespace IOS::HLE } // namespace IOS::HLE

View File

@ -7,6 +7,8 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/MemoryUtil.h" #include "Common/MemoryUtil.h"
#include "Common/Thread.h" #include "Common/Thread.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/Core.h" #include "Core/Core.h"
@ -64,14 +66,14 @@ JitBase::JitBase(Core::System& system)
: m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState()), : m_code_buffer(code_buffer_size), m_system(system), m_ppc_state(system.GetPPCState()),
m_mmu(system.GetMMU()) m_mmu(system.GetMMU())
{ {
m_registered_config_callback_id = Config::AddConfigChangedCallback( m_registered_config_callback_id =
[this] { Core::RunAsCPUThread([this] { RefreshConfig(); }); }); CPUThreadConfigCallback::AddConfigChangedCallback([this] { RefreshConfig(); });
RefreshConfig(); RefreshConfig();
} }
JitBase::~JitBase() JitBase::~JitBase()
{ {
Config::RemoveConfigChangedCallback(m_registered_config_callback_id); CPUThreadConfigCallback::RemoveConfigChangedCallback(m_registered_config_callback_id);
} }
void JitBase::RefreshConfig() void JitBase::RefreshConfig()

View File

@ -10,6 +10,7 @@
#include "Common/BitSet.h" #include "Common/BitSet.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/x64Emitter.h" #include "Common/x64Emitter.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/MachineContext.h" #include "Core/MachineContext.h"
#include "Core/PowerPC/CPUCoreBase.h" #include "Core/PowerPC/CPUCoreBase.h"
@ -129,7 +130,7 @@ protected:
PPCAnalyst::CodeBuffer m_code_buffer; PPCAnalyst::CodeBuffer m_code_buffer;
PPCAnalyst::PPCAnalyzer analyzer; PPCAnalyst::PPCAnalyzer analyzer;
size_t m_registered_config_callback_id; CPUThreadConfigCallback::ConfigChangedCallbackID m_registered_config_callback_id;
bool bJITOff = false; bool bJITOff = false;
bool bJITLoadStoreOff = false; bool bJITLoadStoreOff = false;
bool bJITLoadStorelXzOff = false; bool bJITLoadStorelXzOff = false;

View File

@ -8,6 +8,7 @@
#include <vector> #include <vector>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
class PointerWrap; class PointerWrap;
@ -61,7 +62,7 @@ struct Cache
struct InstructionCache : public Cache struct InstructionCache : public Cache
{ {
std::optional<size_t> m_config_callback_id = std::nullopt; std::optional<Config::ConfigChangedCallbackID> m_config_callback_id = std::nullopt;
bool m_disable_icache = false; bool m_disable_icache = false;

View File

@ -191,6 +191,7 @@
<ClInclude Include="Core\ConfigManager.h" /> <ClInclude Include="Core\ConfigManager.h" />
<ClInclude Include="Core\Core.h" /> <ClInclude Include="Core\Core.h" />
<ClInclude Include="Core\CoreTiming.h" /> <ClInclude Include="Core\CoreTiming.h" />
<ClInclude Include="Core\CPUThreadConfigCallback.h" />
<ClInclude Include="Core\Debugger\CodeTrace.h" /> <ClInclude Include="Core\Debugger\CodeTrace.h" />
<ClInclude Include="Core\Debugger\DebugInterface.h" /> <ClInclude Include="Core\Debugger\DebugInterface.h" />
<ClInclude Include="Core\Debugger\Debugger_SymbolMap.h" /> <ClInclude Include="Core\Debugger\Debugger_SymbolMap.h" />
@ -837,6 +838,7 @@
<ClCompile Include="Core\ConfigManager.cpp" /> <ClCompile Include="Core\ConfigManager.cpp" />
<ClCompile Include="Core\Core.cpp" /> <ClCompile Include="Core\Core.cpp" />
<ClCompile Include="Core\CoreTiming.cpp" /> <ClCompile Include="Core\CoreTiming.cpp" />
<ClCompile Include="Core\CPUThreadConfigCallback.cpp" />
<ClCompile Include="Core\Debugger\CodeTrace.cpp" /> <ClCompile Include="Core\Debugger\CodeTrace.cpp" />
<ClCompile Include="Core\Debugger\Debugger_SymbolMap.cpp" /> <ClCompile Include="Core\Debugger\Debugger_SymbolMap.cpp" />
<ClCompile Include="Core\Debugger\Dump.cpp" /> <ClCompile Include="Core\Debugger\Dump.cpp" />

View File

@ -219,7 +219,7 @@ private:
SteadyClock::time_point m_next_listports_time; SteadyClock::time_point m_next_listports_time;
std::thread m_hotplug_thread; std::thread m_hotplug_thread;
Common::Flag m_hotplug_thread_running; Common::Flag m_hotplug_thread_running;
std::size_t m_config_change_callback_id; Config::ConfigChangedCallbackID m_config_change_callback_id;
}; };
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface) std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)

View File

@ -23,6 +23,7 @@
#endif #endif
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/Config/Config.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Common/Flag.h" #include "Common/Flag.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
@ -158,7 +159,7 @@ static u8 s_endpoint_out = 0;
static u64 s_last_init = 0; static u64 s_last_init = 0;
static std::optional<size_t> s_config_callback_id = std::nullopt; static std::optional<Config::ConfigChangedCallbackID> s_config_callback_id = std::nullopt;
static bool s_is_adapter_wanted = false; static bool s_is_adapter_wanted = false;
static std::array<bool, SerialInterface::MAX_SI_CHANNELS> s_config_rumble_enabled{}; static std::array<bool, SerialInterface::MAX_SI_CHANNELS> s_config_rumble_enabled{};

View File

@ -62,7 +62,7 @@
namespace UICommon namespace UICommon
{ {
static size_t s_config_changed_callback_id; static Config::ConfigChangedCallbackID s_config_changed_callback_id;
static void CreateDumpPath(std::string path) static void CreateDumpPath(std::string path)
{ {

View File

@ -9,6 +9,7 @@
#include "Common/BlockingLoop.h" #include "Common/BlockingLoop.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Common/Flag.h" #include "Common/Flag.h"
@ -121,7 +122,7 @@ private:
bool m_syncing_suspended = false; bool m_syncing_suspended = false;
Common::Event m_sync_wakeup_event; Common::Event m_sync_wakeup_event;
std::optional<size_t> m_config_callback_id = std::nullopt; std::optional<Config::ConfigChangedCallbackID> m_config_callback_id = std::nullopt;
bool m_config_sync_gpu = false; bool m_config_sync_gpu = false;
int m_config_sync_gpu_max_distance = 0; int m_config_sync_gpu_max_distance = 0;
int m_config_sync_gpu_min_distance = 0; int m_config_sync_gpu_min_distance = 0;

View File

@ -9,6 +9,7 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/GraphicsSettings.h" #include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
@ -19,6 +20,7 @@
#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/BPFunctions.h" #include "VideoCommon/BPFunctions.h"
#include "VideoCommon/DriverDetails.h" #include "VideoCommon/DriverDetails.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/FramebufferManager.h" #include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/FreeLookCamera.h" #include "VideoCommon/FreeLookCamera.h"
#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h" #include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h"
@ -57,14 +59,21 @@ void VideoConfig::Refresh()
{ {
// There was a race condition between the video thread and the host thread here, if // There was a race condition between the video thread and the host thread here, if
// corrections need to be made by VerifyValidity(). Briefly, the config will contain // corrections need to be made by VerifyValidity(). Briefly, the config will contain
// invalid values. Instead, pause emulation first, which will flush the video thread, // invalid values. Instead, pause the video thread first, update the config and correct
// update the config and correct it, then resume emulation, after which the video // it, then resume emulation, after which the video thread will detect the config has
// thread will detect the config has changed and act accordingly. // changed and act accordingly.
Config::AddConfigChangedCallback([]() { CPUThreadConfigCallback::AddConfigChangedCallback([]() {
Core::RunAsCPUThread([]() { auto& system = Core::System::GetInstance();
const bool lock_gpu_thread = Core::IsRunningAndStarted();
if (lock_gpu_thread)
system.GetFifo().PauseAndLock(system, true, false);
g_Config.Refresh(); g_Config.Refresh();
g_Config.VerifyValidity(); g_Config.VerifyValidity();
});
if (lock_gpu_thread)
system.GetFifo().PauseAndLock(system, false, true);
}); });
s_has_registered_callback = true; s_has_registered_callback = true;
} }

View File

@ -5,7 +5,9 @@
#include <fmt/format.h> #include <fmt/format.h>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
#include "Common/Timer.h" #include "Common/Timer.h"
#include "Core/Core.h"
#include "Core/MemTools.h" #include "Core/MemTools.h"
#include "Core/PowerPC/JitCommon/JitBase.h" #include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/JitInterface.h"
@ -75,6 +77,9 @@ TEST(PageFault, PageFault)
EXPECT_NE(data, nullptr); EXPECT_NE(data, nullptr);
Common::WriteProtectMemory(data, PAGE_GRAN, false); Common::WriteProtectMemory(data, PAGE_GRAN, false);
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
auto unique_pfjit = std::make_unique<PageFaultFakeJit>(system); auto unique_pfjit = std::make_unique<PageFaultFakeJit>(system);
auto& pfjit = *unique_pfjit; auto& pfjit = *unique_pfjit;

View File

@ -5,7 +5,9 @@
#include <tuple> #include <tuple>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
#include "Common/x64ABI.h" #include "Common/x64ABI.h"
#include "Core/Core.h"
#include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/Jit64/Jit.h" #include "Core/PowerPC/Jit64/Jit.h"
@ -52,6 +54,9 @@ public:
TEST(Jit64, ConvertDoubleToSingle) TEST(Jit64, ConvertDoubleToSingle)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
TestCommonAsmRoutines routines(Core::System::GetInstance()); TestCommonAsmRoutines routines(Core::System::GetInstance());
for (const u64 input : double_test_values) for (const u64 input : double_test_values)

View File

@ -6,7 +6,9 @@
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/FloatUtils.h" #include "Common/FloatUtils.h"
#include "Common/ScopeGuard.h"
#include "Common/x64ABI.h" #include "Common/x64ABI.h"
#include "Core/Core.h"
#include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/Jit64/Jit.h" #include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h" #include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h"
@ -59,6 +61,9 @@ public:
TEST(Jit64, Frsqrte) TEST(Jit64, Frsqrte)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
TestCommonAsmRoutines routines(Core::System::GetInstance()); TestCommonAsmRoutines routines(Core::System::GetInstance());
UReg_FPSCR fpscr; UReg_FPSCR fpscr;

View File

@ -7,6 +7,8 @@
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/FPURoundMode.h" #include "Common/FPURoundMode.h"
#include "Common/ScopeGuard.h"
#include "Core/Core.h"
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/System.h" #include "Core/System.h"
@ -120,6 +122,9 @@ private:
TEST(JitArm64, ConvertDoubleToSingle) TEST(JitArm64, ConvertDoubleToSingle)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
TestConversion test(Core::System::GetInstance()); TestConversion test(Core::System::GetInstance());
for (const u64 input : double_test_values) for (const u64 input : double_test_values)
@ -155,6 +160,9 @@ TEST(JitArm64, ConvertDoubleToSingle)
TEST(JitArm64, ConvertSingleToDouble) TEST(JitArm64, ConvertSingleToDouble)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
TestConversion test(Core::System::GetInstance()); TestConversion test(Core::System::GetInstance());
for (const u32 input : single_test_values) for (const u32 input : single_test_values)

View File

@ -7,6 +7,8 @@
#include "Common/Arm64Emitter.h" #include "Common/Arm64Emitter.h"
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
#include "Core/Core.h"
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
@ -70,6 +72,9 @@ static u32 RunUpdateFPRF(PowerPC::PowerPCState& ppc_state, const std::function<v
TEST(JitArm64, FPRF) TEST(JitArm64, FPRF)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState(); auto& ppc_state = system.GetPPCState();
TestFPRF test(system); TestFPRF test(system);

View File

@ -6,6 +6,8 @@
#include "Common/Arm64Emitter.h" #include "Common/Arm64Emitter.h"
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
#include "Core/Core.h"
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
@ -51,6 +53,9 @@ public:
TEST(JitArm64, Fres) TEST(JitArm64, Fres)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
TestFres test(Core::System::GetInstance()); TestFres test(Core::System::GetInstance());
for (const u64 ivalue : double_test_values) for (const u64 ivalue : double_test_values)

View File

@ -6,6 +6,8 @@
#include "Common/Arm64Emitter.h" #include "Common/Arm64Emitter.h"
#include "Common/BitUtils.h" #include "Common/BitUtils.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
#include "Core/Core.h"
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
#include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
@ -51,6 +53,9 @@ public:
TEST(JitArm64, Frsqrte) TEST(JitArm64, Frsqrte)
{ {
Core::DeclareAsCPUThread();
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
TestFrsqrte test(Core::System::GetInstance()); TestFrsqrte test(Core::System::GetInstance());
for (const u64 ivalue : double_test_values) for (const u64 ivalue : double_test_values)