From 56ea1c1d74f349a1ed412b7e604decf0fadc9f6c Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 5 Feb 2022 19:49:06 +0100 Subject: [PATCH 1/2] Core/State: Guard SaveAs() and LoadAs() with a mutex. --- Source/Core/Core/State.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index f89c1fc79e..e3f382a610 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -64,7 +64,7 @@ static AfterLoadCallbackFunc s_on_after_load_callback; // Temporary undo state buffer static std::vector g_undo_load_buffer; static std::vector g_current_buffer; -static bool s_load_or_save_in_progress; +static std::mutex s_load_or_save_in_progress_mutex; static std::mutex g_cs_undo_load_buffer; static std::mutex g_cs_current_buffer; @@ -403,11 +403,10 @@ static void CompressAndDumpState(CompressAndDumpState_args save_args) void SaveAs(const std::string& filename, bool wait) { - if (s_load_or_save_in_progress) + std::unique_lock lk(s_load_or_save_in_progress_mutex, std::try_to_lock); + if (!lk) return; - s_load_or_save_in_progress = true; - Core::RunOnCPUThread( [&] { // Measure the size of the buffer. @@ -446,8 +445,6 @@ void SaveAs(const std::string& filename, bool wait) } }, true); - - s_load_or_save_in_progress = false; } bool ReadHeader(const std::string& filename, StateHeader& header) @@ -550,17 +547,18 @@ static void LoadFileStateData(const std::string& filename, std::vector& ret_ void LoadAs(const std::string& filename) { - if (!Core::IsRunning() || s_load_or_save_in_progress) - { + if (!Core::IsRunning()) return; - } - else if (NetPlay::IsNetPlayRunning()) + + if (NetPlay::IsNetPlayRunning()) { OSD::AddMessage("Loading savestates is disabled in Netplay to prevent desyncs"); return; } - s_load_or_save_in_progress = true; + std::unique_lock lk(s_load_or_save_in_progress_mutex, std::try_to_lock); + if (!lk) + return; Core::RunOnCPUThread( [&] { @@ -617,8 +615,6 @@ void LoadAs(const std::string& filename) s_on_after_load_callback(); }, true); - - s_load_or_save_in_progress = false; } void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback) From 73311694b04cc3830689726ddda879e0a0d8b069 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 5 Feb 2022 19:56:44 +0100 Subject: [PATCH 2/2] Core/State: Guard g_save_thread with a mutex. --- Source/Core/Core/State.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index e3f382a610..b1a3c70910 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -70,6 +70,7 @@ static std::mutex g_cs_undo_load_buffer; static std::mutex g_cs_current_buffer; static Common::Event g_compressAndDumpStateSyncEvent; +static std::recursive_mutex g_save_thread_mutex; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system @@ -434,8 +435,12 @@ void SaveAs(const std::string& filename, bool wait) save_args.filename = filename; save_args.wait = wait; - Flush(); - g_save_thread = std::thread(CompressAndDumpState, save_args); + { + std::lock_guard lk(g_save_thread_mutex); + Flush(); + g_save_thread = std::thread(CompressAndDumpState, save_args); + } + g_compressAndDumpStateSyncEvent.Wait(); } else @@ -695,6 +700,8 @@ void SaveFirstSaved() void Flush() { + std::lock_guard lk(g_save_thread_mutex); + // If already saving state, wait for it to finish if (g_save_thread.joinable()) g_save_thread.join();