summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VideoConfig.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2023-08-16 21:16:41 +0200
committerJosJuice <josjuice@gmail.com>2023-08-17 19:19:25 +0200
commit71ce8bb6f00f4d1cbc1012270d6daefdbda4254d (patch)
treec245efb37ef8aa18d481c22f13cbb540aaffac4a /Source/Core/VideoCommon/VideoConfig.cpp
parent23ae8c439c3826973a00a29b6d221d3836bc7415 (diff)
Don't call RunAsCPUThread in config callbacks
In theory, our config system supports calling Set from any thread. But because we have config callbacks that call RunAsCPUThread, it's a lot more restricted in practice. Calling Set from any thread other than the host thread or the CPU thread is formally thread unsafe, and calling Set on the host thread while the CPU thread is showing a panic alert causes a deadlock. This is especially a problem because 04072f0 made the "Ignore for this session" button in panic alerts call Set. Because so many of our config callbacks want their code to run on the CPU thread, I thought it would make sense to have a centralized way to move execution to the CPU thread for config callbacks. To solve the deadlock problem, this new way is non-blocking. This means that threads other than the CPU thread might continue executing before the CPU thread is informed of the new config, but I don't think there's any problem with that. Intends to fix https://bugs.dolphin-emu.org/issues/13108.
Diffstat (limited to 'Source/Core/VideoCommon/VideoConfig.cpp')
-rw-r--r--Source/Core/VideoCommon/VideoConfig.cpp25
1 files changed, 17 insertions, 8 deletions
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index 42bf178047..b00976b9b4 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -9,6 +9,7 @@
#include "Common/CommonTypes.h"
#include "Common/StringUtil.h"
+#include "Core/CPUThreadConfigCallback.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
@@ -19,6 +20,7 @@
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/BPFunctions.h"
#include "VideoCommon/DriverDetails.h"
+#include "VideoCommon/Fifo.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/FreeLookCamera.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
// corrections need to be made by VerifyValidity(). Briefly, the config will contain
- // invalid values. Instead, pause emulation first, which will flush the video thread,
- // update the config and correct it, then resume emulation, after which the video
- // thread will detect the config has changed and act accordingly.
- Config::AddConfigChangedCallback([]() {
- Core::RunAsCPUThread([]() {
- g_Config.Refresh();
- g_Config.VerifyValidity();
- });
+ // invalid values. Instead, pause the video thread first, update the config and correct
+ // it, then resume emulation, after which the video thread will detect the config has
+ // changed and act accordingly.
+ CPUThreadConfigCallback::AddConfigChangedCallback([]() {
+ 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.VerifyValidity();
+
+ if (lock_gpu_thread)
+ system.GetFifo().PauseAndLock(system, false, true);
});
s_has_registered_callback = true;
}