From f106a9637df3f1cb31a09d451729cae1acdc63cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 21 Jul 2017 14:06:02 +0800 Subject: [PATCH 1/2] Replace balanced Core::PauseAndLock calls with RunAsCPUThread Core::PauseAndLock requires all calls to it to be balanced, like this: const bool was_unpaused = Core::PauseAndLock(true); // do stuff on the CPU thread Core::PauseAndLock(false, was_unpaused); Aside from being a bit cumbersome, it turns out all callers really don't need to know about was_unpaused at all. They just need to do something on the CPU thread safely, including locking/unlocking. So this commit replaces Core::PauseAndLock with a function that makes both the purpose and the scope of what is being run on the CPU thread visually clear. This makes it harder to accidentally run something on the wrong thread, or forget the second call to PauseAndLock to unpause, or forget that it needs to be passed was_unpaused at the end. We also don't need comments to indicate code X is being run on the CPU thread anymore, as the function name makes it obvious. --- Source/Core/Core/Core.cpp | 43 +-- Source/Core/Core/Core.h | 14 +- Source/Core/Core/HW/DVD/DVDInterface.cpp | 7 +- Source/Core/Core/Movie.cpp | 104 ++++---- Source/Core/Core/PowerPC/BreakPoints.cpp | 28 +- Source/Core/Core/State.cpp | 250 ++++++++---------- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 14 +- .../DolphinQt2/Config/Mapping/IOWindow.cpp | 29 +- .../Config/Mapping/MappingWindow.cpp | 28 +- .../DolphinWX/Config/GCAdapterConfigDiag.cpp | 12 +- Source/Core/DolphinWX/Frame.cpp | 4 +- Source/Core/DolphinWX/FrameTools.cpp | 56 ++-- .../Core/DolphinWX/Input/InputConfigDiag.cpp | 28 +- 13 files changed, 300 insertions(+), 317 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 941115f777..fefe7d7888 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -759,7 +759,7 @@ void RequestRefreshInfo() s_request_refresh_info = true; } -bool PauseAndLock(bool do_lock, bool unpause_on_unlock) +static bool PauseAndLock(bool do_lock, bool unpause_on_unlock) { // WARNING: PauseAndLock is not fully threadsafe so is only valid on the Host Thread if (!IsRunning()) @@ -806,6 +806,19 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock) return was_unpaused; } +void RunAsCPUThread(std::function function) +{ + const bool is_cpu_thread = IsCPUThread(); + bool was_unpaused = false; + if (!is_cpu_thread) + was_unpaused = PauseAndLock(true, true); + + function(); + + if (!is_cpu_thread) + PauseAndLock(false, was_unpaused); +} + // Display FPS info // This should only be called from VI void VideoThrottle() @@ -955,22 +968,20 @@ void UpdateWantDeterminism(bool initial) { NOTICE_LOG(COMMON, "Want determinism <- %s", new_want_determinism ? "true" : "false"); - bool was_unpaused = Core::PauseAndLock(true); + RunAsCPUThread([&] { + s_wants_determinism = new_want_determinism; + const auto ios = IOS::HLE::GetIOS(); + if (ios) + ios->UpdateWantDeterminism(new_want_determinism); + Fifo::UpdateWantDeterminism(new_want_determinism); + // We need to clear the cache because some parts of the JIT depend on want_determinism, + // e.g. use of FMA. + JitInterface::ClearCache(); - s_wants_determinism = new_want_determinism; - const auto ios = IOS::HLE::GetIOS(); - if (ios) - ios->UpdateWantDeterminism(new_want_determinism); - Fifo::UpdateWantDeterminism(new_want_determinism); - // We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use - // of FMA. - JitInterface::ClearCache(); - - // Don't call InitializeWiiRoot during boot, because IOS already does it. - if (!initial) - Core::InitializeWiiRoot(s_wants_determinism); - - Core::PauseAndLock(false, was_unpaused); + // Don't call InitializeWiiRoot during boot, because IOS already does it. + if (!initial) + Core::InitializeWiiRoot(s_wants_determinism); + }); } } diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 78b5f5d6c7..e604843a2c 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -74,12 +74,14 @@ void RequestRefreshInfo(); void UpdateTitle(); -// waits until all systems are paused and fully idle, and acquires a lock on that state. -// or, if doLock is false, releases a lock on that state and optionally unpauses. -// calls must be balanced (once with doLock true, then once with doLock false) but may be recursive. -// the return value of the first call should be passed in as the second argument of the second call. -// [NOT THREADSAFE] Host only -bool PauseAndLock(bool doLock, bool unpauseOnUnlock = true); +// Run a function as the CPU thread. +// +// If called from the Host thread, the CPU thread is paused and the current thread temporarily +// becomes the CPU thread while running the function. +// If called from the CPU thread, the function will be run directly. +// +// This should only be called from the CPU thread or the host thread. +void RunAsCPUThread(std::function function); // for calling back into UI code without introducing a dependency on it in core using StoppedCallbackFunc = std::function; diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 4876ba6063..ffee201a97 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -476,12 +476,7 @@ static void InsertDiscCallback(u64 userdata, s64 cyclesLate) // Can only be called by the host thread void ChangeDiscAsHost(const std::string& new_path) { - bool was_unpaused = Core::PauseAndLock(true); - - // The host thread is now temporarily the CPU thread - ChangeDiscAsCPU(new_path); - - Core::PauseAndLock(false, was_unpaused); + Core::RunAsCPUThread([&] { ChangeDiscAsCPU(new_path); }); } // Can only be called by the CPU thread diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 79104e02c3..d793d908d5 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -544,68 +544,66 @@ bool BeginRecordingInput(int controllers) if (s_playMode != MODE_NONE || controllers == 0) return false; - bool was_unpaused = Core::PauseAndLock(true); + Core::RunAsCPUThread([controllers] { + s_controllers = controllers; + s_currentFrame = s_totalFrames = 0; + s_currentLagCount = s_totalLagCount = 0; + s_currentInputCount = s_totalInputCount = 0; + s_totalTickCount = s_tickCountAtLastInput = 0; + s_bongos = 0; + s_memcards = 0; + if (NetPlay::IsNetPlayRunning()) + { + s_bNetPlay = true; + s_recordingStartTime = ExpansionInterface::CEXIIPL::NetPlay_GetEmulatedTime(); + } + else if (SConfig::GetInstance().bEnableCustomRTC) + { + s_recordingStartTime = SConfig::GetInstance().m_customRTCValue; + } + else + { + s_recordingStartTime = Common::Timer::GetLocalTimeSinceJan1970(); + } - s_controllers = controllers; - s_currentFrame = s_totalFrames = 0; - s_currentLagCount = s_totalLagCount = 0; - s_currentInputCount = s_totalInputCount = 0; - s_totalTickCount = s_tickCountAtLastInput = 0; - s_bongos = 0; - s_memcards = 0; - if (NetPlay::IsNetPlayRunning()) - { - s_bNetPlay = true; - s_recordingStartTime = ExpansionInterface::CEXIIPL::NetPlay_GetEmulatedTime(); - } - else if (SConfig::GetInstance().bEnableCustomRTC) - { - s_recordingStartTime = SConfig::GetInstance().m_customRTCValue; - } - else - { - s_recordingStartTime = Common::Timer::GetLocalTimeSinceJan1970(); - } + s_rerecords = 0; - s_rerecords = 0; + for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i) + { + if (SConfig::GetInstance().m_SIDevice[i] == SerialInterface::SIDEVICE_GC_TARUKONGA) + s_bongos |= (1 << i); + } - for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i) - { - if (SConfig::GetInstance().m_SIDevice[i] == SerialInterface::SIDEVICE_GC_TARUKONGA) - s_bongos |= (1 << i); - } + if (Core::IsRunningAndStarted()) + { + const std::string save_path = File::GetUserPath(D_STATESAVES_IDX) + "dtm.sav"; + if (File::Exists(save_path)) + File::Delete(save_path); - if (Core::IsRunningAndStarted()) - { - const std::string save_path = File::GetUserPath(D_STATESAVES_IDX) + "dtm.sav"; - if (File::Exists(save_path)) - File::Delete(save_path); + State::SaveAs(save_path); + s_bRecordingFromSaveState = true; - State::SaveAs(save_path); - s_bRecordingFromSaveState = true; + std::thread md5thread(GetMD5); + md5thread.detach(); + GetSettings(); + } - std::thread md5thread(GetMD5); - md5thread.detach(); - GetSettings(); - } + // Wiimotes cause desync issues if they're not reset before launching the game + if (!Core::IsRunningAndStarted()) + { + // This will also reset the wiimotes for gamecube games, but that shouldn't do anything + Wiimote::ResetAllWiimotes(); + } - // Wiimotes cause desync issues if they're not reset before launching the game - if (!Core::IsRunningAndStarted()) - { - // This will also reset the wiimotes for gamecube games, but that shouldn't do anything - Wiimote::ResetAllWiimotes(); - } + s_playMode = MODE_RECORDING; + s_author = SConfig::GetInstance().m_strMovieAuthor; + s_temp_input.clear(); - s_playMode = MODE_RECORDING; - s_author = SConfig::GetInstance().m_strMovieAuthor; - s_temp_input.clear(); + s_currentByte = 0; - s_currentByte = 0; - - if (Core::IsRunning()) - Core::UpdateWantDeterminism(); - - Core::PauseAndLock(false, was_unpaused); + if (Core::IsRunning()) + Core::UpdateWantDeterminism(); + }); Core::DisplayMessage("Starting movie recording", 2000); return true; diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index 864793f5e8..e87143bcf8 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -174,14 +174,14 @@ void MemChecks::Add(const TMemCheck& memory_check) if (GetMemCheck(memory_check.start_address) == nullptr) { bool had_any = HasAny(); - bool lock = Core::PauseAndLock(true); - m_mem_checks.push_back(memory_check); - // If this is the first one, clear the JIT cache so it can switch to - // watchpoint-compatible code. - if (!had_any && g_jit) - g_jit->ClearCache(); - PowerPC::DBATUpdated(); - Core::PauseAndLock(false, lock); + Core::RunAsCPUThread([&] { + m_mem_checks.push_back(memory_check); + // If this is the first one, clear the JIT cache so it can switch to + // watchpoint-compatible code. + if (!had_any && g_jit) + g_jit->ClearCache(); + PowerPC::DBATUpdated(); + }); } } @@ -191,12 +191,12 @@ void MemChecks::Remove(u32 address) { if (i->start_address == address) { - bool lock = Core::PauseAndLock(true); - m_mem_checks.erase(i); - if (!HasAny() && g_jit) - g_jit->ClearCache(); - PowerPC::DBATUpdated(); - Core::PauseAndLock(false, lock); + Core::RunAsCPUThread([&] { + m_mem_checks.erase(i); + if (!HasAny() && g_jit) + g_jit->ClearCache(); + PowerPC::DBATUpdated(); + }); return; } } diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 5fbc446e16..9af7b25439 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -207,42 +207,36 @@ void LoadFromBuffer(std::vector& buffer) return; } - bool wasUnpaused = Core::PauseAndLock(true); - - u8* ptr = &buffer[0]; - PointerWrap p(&ptr, PointerWrap::MODE_READ); - DoState(p); - - Core::PauseAndLock(false, wasUnpaused); + Core::RunAsCPUThread([&] { + u8* ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_READ); + DoState(p); + }); } void SaveToBuffer(std::vector& buffer) { - bool wasUnpaused = Core::PauseAndLock(true); + Core::RunAsCPUThread([&] { + u8* ptr = nullptr; + PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); - u8* ptr = nullptr; - PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); + DoState(p); + const size_t buffer_size = reinterpret_cast(ptr); + buffer.resize(buffer_size); - DoState(p); - const size_t buffer_size = reinterpret_cast(ptr); - buffer.resize(buffer_size); - - ptr = &buffer[0]; - p.SetMode(PointerWrap::MODE_WRITE); - DoState(p); - - Core::PauseAndLock(false, wasUnpaused); + ptr = &buffer[0]; + p.SetMode(PointerWrap::MODE_WRITE); + DoState(p); + }); } void VerifyBuffer(std::vector& buffer) { - bool wasUnpaused = Core::PauseAndLock(true); - - u8* ptr = &buffer[0]; - PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); - DoState(p); - - Core::PauseAndLock(false, wasUnpaused); + Core::RunAsCPUThread([&] { + u8* ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); + DoState(p); + }); } // return state number not in map @@ -399,48 +393,44 @@ static void CompressAndDumpState(CompressAndDumpState_args save_args) void SaveAs(const std::string& filename, bool wait) { - // Pause the core while we save the state - bool wasUnpaused = Core::PauseAndLock(true); - - // Measure the size of the buffer. - u8* ptr = nullptr; - PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); - DoState(p); - const size_t buffer_size = reinterpret_cast(ptr); - - // Then actually do the write. - { - std::lock_guard lk(g_cs_current_buffer); - g_current_buffer.resize(buffer_size); - ptr = &g_current_buffer[0]; - p.SetMode(PointerWrap::MODE_WRITE); + Core::RunAsCPUThread([&] { + // Measure the size of the buffer. + u8* ptr = nullptr; + PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); DoState(p); - } + const size_t buffer_size = reinterpret_cast(ptr); - if (p.GetMode() == PointerWrap::MODE_WRITE) - { - Core::DisplayMessage("Saving State...", 1000); + // Then actually do the write. + { + std::lock_guard lk(g_cs_current_buffer); + g_current_buffer.resize(buffer_size); + ptr = &g_current_buffer[0]; + p.SetMode(PointerWrap::MODE_WRITE); + DoState(p); + } - CompressAndDumpState_args save_args; - save_args.buffer_vector = &g_current_buffer; - save_args.buffer_mutex = &g_cs_current_buffer; - save_args.filename = filename; - save_args.wait = wait; + if (p.GetMode() == PointerWrap::MODE_WRITE) + { + Core::DisplayMessage("Saving State...", 1000); - Flush(); - g_save_thread = std::thread(CompressAndDumpState, save_args); - g_compressAndDumpStateSyncEvent.Wait(); + CompressAndDumpState_args save_args; + save_args.buffer_vector = &g_current_buffer; + save_args.buffer_mutex = &g_cs_current_buffer; + save_args.filename = filename; + save_args.wait = wait; - g_last_filename = filename; - } - else - { - // someone aborted the save by changing the mode? - Core::DisplayMessage("Unable to save: Internal DoState Error", 4000); - } + Flush(); + g_save_thread = std::thread(CompressAndDumpState, save_args); + g_compressAndDumpStateSyncEvent.Wait(); - // Resume the core and disable stepping - Core::PauseAndLock(false, wasUnpaused); + g_last_filename = filename; + } + else + { + // someone aborted the save by changing the mode? + Core::DisplayMessage("Unable to save: Internal DoState Error", 4000); + } + }); } bool ReadHeader(const std::string& filename, StateHeader& header) @@ -549,72 +539,68 @@ void LoadAs(const std::string& filename) return; } - // Stop the core while we load the state - bool wasUnpaused = Core::PauseAndLock(true); + Core::RunAsCPUThread([&] { + g_loadDepth++; - g_loadDepth++; - - // Save temp buffer for undo load state - if (!Movie::IsJustStartingRecordingInputFromSaveState()) - { - std::lock_guard lk(g_cs_undo_load_buffer); - SaveToBuffer(g_undo_load_buffer); - if (Movie::IsMovieActive()) - Movie::SaveRecording(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); - else if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm")) - File::Delete(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); - } - - bool loaded = false; - bool loadedSuccessfully = false; - std::string version_created_by; - - // brackets here are so buffer gets freed ASAP - { - std::vector buffer; - LoadFileStateData(filename, buffer); - - if (!buffer.empty()) + // Save temp buffer for undo load state + if (!Movie::IsJustStartingRecordingInputFromSaveState()) { - u8* ptr = &buffer[0]; - PointerWrap p(&ptr, PointerWrap::MODE_READ); - version_created_by = DoState(p); - loaded = true; - loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); + std::lock_guard lk(g_cs_undo_load_buffer); + SaveToBuffer(g_undo_load_buffer); + if (Movie::IsMovieActive()) + Movie::SaveRecording(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); + else if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm")) + File::Delete(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"); } - } - if (loaded) - { - if (loadedSuccessfully) + bool loaded = false; + bool loadedSuccessfully = false; + std::string version_created_by; + + // brackets here are so buffer gets freed ASAP { - Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000); - if (File::Exists(filename + ".dtm")) - Movie::LoadInput(filename + ".dtm"); - else if (!Movie::IsJustStartingRecordingInputFromSaveState() && - !Movie::IsJustStartingPlayingInputFromSaveState()) - Movie::EndPlayInput(false); + std::vector buffer; + LoadFileStateData(filename, buffer); + + if (!buffer.empty()) + { + u8* ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_READ); + version_created_by = DoState(p); + loaded = true; + loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); + } } - else + + if (loaded) { - // failed to load - Core::DisplayMessage("Unable to load: Can't load state from other versions!", 4000); - if (!version_created_by.empty()) - Core::DisplayMessage("The savestate was created using " + version_created_by, 4000); + if (loadedSuccessfully) + { + Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000); + if (File::Exists(filename + ".dtm")) + Movie::LoadInput(filename + ".dtm"); + else if (!Movie::IsJustStartingRecordingInputFromSaveState() && + !Movie::IsJustStartingPlayingInputFromSaveState()) + Movie::EndPlayInput(false); + } + else + { + // failed to load + Core::DisplayMessage("Unable to load: Can't load state from other versions!", 4000); + if (!version_created_by.empty()) + Core::DisplayMessage("The savestate was created using " + version_created_by, 4000); - // since we could be in an inconsistent state now (and might crash or whatever), undo. - if (g_loadDepth < 2) - UndoLoadState(); + // since we could be in an inconsistent state now (and might crash or whatever), undo. + if (g_loadDepth < 2) + UndoLoadState(); + } } - } - if (s_on_after_load_callback) - s_on_after_load_callback(); + if (s_on_after_load_callback) + s_on_after_load_callback(); - g_loadDepth--; - - // resume dat core - Core::PauseAndLock(false, wasUnpaused); + g_loadDepth--; + }); } void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback) @@ -624,24 +610,22 @@ void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback) void VerifyAt(const std::string& filename) { - bool wasUnpaused = Core::PauseAndLock(true); + Core::RunAsCPUThread([&] { + std::vector buffer; + LoadFileStateData(filename, buffer); - std::vector buffer; - LoadFileStateData(filename, buffer); + if (!buffer.empty()) + { + u8* ptr = &buffer[0]; + PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); + DoState(p); - if (!buffer.empty()) - { - u8* ptr = &buffer[0]; - PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); - DoState(p); - - if (p.GetMode() == PointerWrap::MODE_VERIFY) - Core::DisplayMessage(StringFromFormat("Verified state at %s", filename.c_str()), 2000); - else - Core::DisplayMessage("Unable to Verify : Can't verify state from other revisions !", 4000); - } - - Core::PauseAndLock(false, wasUnpaused); + if (p.GetMode() == PointerWrap::MODE_VERIFY) + Core::DisplayMessage(StringFromFormat("Verified state at %s", filename.c_str()), 2000); + else + Core::DisplayMessage("Unable to Verify : Can't verify state from other revisions !", 4000); + } + }); } void Init() diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index b62cf0e22c..dc55d41ec6 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -137,13 +137,13 @@ void Host_ConnectWiimote(int wm_idx, bool connect) const auto ios = IOS::HLE::GetIOS(); if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) return; - bool was_unpaused = Core::PauseAndLock(true); - const auto bt = std::static_pointer_cast( - ios->GetDeviceByName("/dev/usb/oh1/57e/305")); - if (bt) - bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); - Host_UpdateMainFrame(); - Core::PauseAndLock(false, was_unpaused); + Core::RunAsCPUThread([&] { + const auto bt = std::static_pointer_cast( + ios->GetDeviceByName("/dev/usb/oh1/57e/305")); + if (bt) + bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); + Host_UpdateMainFrame(); + }); }); } diff --git a/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp b/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp index ac2b22eb1d..16f0186cb2 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/IOWindow.cpp @@ -237,25 +237,24 @@ void IOWindow::UpdateDeviceList() m_block.Set(true); m_devices_combo->clear(); - const bool paused = Core::PauseAndLock(true); + Core::RunAsCPUThread([&] { + g_controller_interface.RefreshDevices(); + m_controller->UpdateReferences(g_controller_interface); + m_controller->UpdateDefaultDevice(); - g_controller_interface.RefreshDevices(); - m_controller->UpdateReferences(g_controller_interface); - m_controller->UpdateDefaultDevice(); + // Adding default device regardless if it's currently connected or not + const auto default_device = m_controller->default_device.ToString(); - // Adding default device regardless if it's currently connected or not - const auto default_device = m_controller->default_device.ToString(); + m_devices_combo->addItem(QString::fromStdString(default_device)); - m_devices_combo->addItem(QString::fromStdString(default_device)); + for (const auto& name : g_controller_interface.GetAllDeviceStrings()) + { + if (name != default_device) + m_devices_combo->addItem(QString::fromStdString(name)); + } - for (const auto& name : g_controller_interface.GetAllDeviceStrings()) - { - if (name != default_device) - m_devices_combo->addItem(QString::fromStdString(name)); - } + m_devices_combo->setCurrentIndex(0); + }); - m_devices_combo->setCurrentIndex(0); - - Core::PauseAndLock(false, paused); m_block.Set(false); } diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp index f7406a5a8b..2885385f33 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp @@ -229,25 +229,23 @@ void MappingWindow::RefreshDevices() { m_devices_combo->clear(); - const bool paused = Core::PauseAndLock(true); + Core::RunAsCPUThread([&] { + g_controller_interface.RefreshDevices(); + m_controller->UpdateReferences(g_controller_interface); + m_controller->UpdateDefaultDevice(); - g_controller_interface.RefreshDevices(); - m_controller->UpdateReferences(g_controller_interface); - m_controller->UpdateDefaultDevice(); + const auto default_device = m_controller->default_device.ToString(); - const auto default_device = m_controller->default_device.ToString(); + m_devices_combo->addItem(QString::fromStdString(default_device)); - m_devices_combo->addItem(QString::fromStdString(default_device)); + for (const auto& name : g_controller_interface.GetAllDeviceStrings()) + { + if (name != default_device) + m_devices_combo->addItem(QString::fromStdString(name)); + } - for (const auto& name : g_controller_interface.GetAllDeviceStrings()) - { - if (name != default_device) - m_devices_combo->addItem(QString::fromStdString(name)); - } - - m_devices_combo->setCurrentIndex(0); - - Core::PauseAndLock(false, paused); + m_devices_combo->setCurrentIndex(0); + }); } void MappingWindow::ChangeMappingType(MappingWindow::Type type) diff --git a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp index 9cf3110e09..b5a862461d 100644 --- a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp +++ b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp @@ -71,12 +71,12 @@ void GCAdapterConfigDiag::ScheduleAdapterUpdate() void GCAdapterConfigDiag::OnUpdateAdapter(wxCommandEvent& WXUNUSED(event)) { - bool unpause = Core::PauseAndLock(true); - if (GCAdapter::IsDetected()) - m_adapter_status->SetLabelText(_("Adapter Detected")); - else - m_adapter_status->SetLabelText(_("Adapter Not Detected")); - Core::PauseAndLock(false, unpause); + Core::RunAsCPUThread([this] { + if (GCAdapter::IsDetected()) + m_adapter_status->SetLabelText(_("Adapter Detected")); + else + m_adapter_status->SetLabelText(_("Adapter Not Detected")); + }); } void GCAdapterConfigDiag::OnAdapterRumble(wxCommandEvent& event) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 29a7b526c3..fc5efddb34 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1249,9 +1249,7 @@ void CFrame::DoExclusiveFullscreen(bool enable_fullscreen) if (!g_renderer || g_renderer->IsFullscreen() == enable_fullscreen) return; - bool was_unpaused = Core::PauseAndLock(true); - g_renderer->SetFullscreen(enable_fullscreen); - Core::PauseAndLock(false, was_unpaused); + Core::RunAsCPUThread([enable_fullscreen] { g_renderer->SetFullscreen(enable_fullscreen); }); } void CFrame::PollHotkeys(wxTimerEvent& event) diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index a403118000..d633561cfd 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -1411,19 +1411,19 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect) if (Core::IsRunning() && SConfig::GetInstance().bWii && !SConfig::GetInstance().m_bt_passthrough_enabled) { - bool was_unpaused = Core::PauseAndLock(true); - const auto ios = IOS::HLE::GetIOS(); - if (!ios) - return; + Core::RunAsCPUThread([&] { + const auto ios = IOS::HLE::GetIOS(); + if (!ios) + return; - const auto bt = std::static_pointer_cast( - ios->GetDeviceByName("/dev/usb/oh1/57e/305")); - if (bt) - bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); - const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected"; - Core::DisplayMessage(StringFromFormat(message, wm_idx + 1), 3000); - Host_UpdateMainFrame(); - Core::PauseAndLock(false, was_unpaused); + const auto bt = std::static_pointer_cast( + ios->GetDeviceByName("/dev/usb/oh1/57e/305")); + if (bt) + bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); + const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected"; + Core::DisplayMessage(StringFromFormat(message, wm_idx + 1), 3000); + Host_UpdateMainFrame(); + }); } } @@ -1432,13 +1432,13 @@ void CFrame::OnConnectWiimote(wxCommandEvent& event) const auto ios = IOS::HLE::GetIOS(); if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) return; - bool was_unpaused = Core::PauseAndLock(true); - const auto bt = std::static_pointer_cast( - ios->GetDeviceByName("/dev/usb/oh1/57e/305")); - const bool is_connected = - bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected(); - ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected); - Core::PauseAndLock(false, was_unpaused); + Core::RunAsCPUThread([&] { + const auto bt = std::static_pointer_cast( + ios->GetDeviceByName("/dev/usb/oh1/57e/305")); + const bool is_connected = + bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected(); + ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected); + }); } // Toggle fullscreen. In Windows the fullscreen mode is accomplished by expanding the m_panel to @@ -1603,15 +1603,15 @@ void CFrame::UpdateGUI() GetMenuBar()->FindItem(IDM_CONNECT_BALANCEBOARD)->Enable(ShouldEnableWiimotes); if (ShouldEnableWiimotes) { - bool was_unpaused = Core::PauseAndLock(true); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(bt->AccessWiiMote(0x0100)->IsConnected()); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(bt->AccessWiiMote(0x0101)->IsConnected()); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Check(bt->AccessWiiMote(0x0102)->IsConnected()); - GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(bt->AccessWiiMote(0x0103)->IsConnected()); - GetMenuBar() - ->FindItem(IDM_CONNECT_BALANCEBOARD) - ->Check(bt->AccessWiiMote(0x0104)->IsConnected()); - Core::PauseAndLock(false, was_unpaused); + Core::RunAsCPUThread([&] { + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(bt->AccessWiiMote(0x0100)->IsConnected()); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(bt->AccessWiiMote(0x0101)->IsConnected()); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Check(bt->AccessWiiMote(0x0102)->IsConnected()); + GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(bt->AccessWiiMote(0x0103)->IsConnected()); + GetMenuBar() + ->FindItem(IDM_CONNECT_BALANCEBOARD) + ->Check(bt->AccessWiiMote(0x0104)->IsConnected()); + }); } GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Enable(Running || Paused); diff --git a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp index 15c213ac94..5d8bf9615e 100644 --- a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp @@ -915,25 +915,23 @@ void InputConfigDialog::UpdateDeviceComboBox() void InputConfigDialog::RefreshDevices(wxCommandEvent&) { - bool was_unpaused = Core::PauseAndLock(true); + Core::RunAsCPUThread([&] { + // refresh devices + g_controller_interface.RefreshDevices(); - // refresh devices - g_controller_interface.RefreshDevices(); + // update all control references + UpdateControlReferences(); - // update all control references - UpdateControlReferences(); + // update device cbox + UpdateDeviceComboBox(); - // update device cbox - UpdateDeviceComboBox(); + Wiimote::LoadConfig(); + Keyboard::LoadConfig(); + Pad::LoadConfig(); + HotkeyManagerEmu::LoadConfig(); - Wiimote::LoadConfig(); - Keyboard::LoadConfig(); - Pad::LoadConfig(); - HotkeyManagerEmu::LoadConfig(); - - UpdateGUI(); - - Core::PauseAndLock(false, was_unpaused); + UpdateGUI(); + }); } ControlGroupBox::~ControlGroupBox() From 5729ac0fc685d42035dfa1c850672822a247851c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 21 Jul 2017 16:04:02 +0800 Subject: [PATCH 2/2] Core: Replace recursive locking from PauseAndLock PauseAndLock cannot be called recursively anymore. --- Source/Core/Core/Core.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index fefe7d7888..31cb2d8b4c 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -102,7 +102,6 @@ static StoppedCallbackFunc s_on_stopped_callback; static std::thread s_cpu_thread; static bool s_request_refresh_info = false; -static int s_pause_and_lock_depth = 0; static bool s_is_throttler_temp_disabled = false; struct HostJob @@ -765,11 +764,6 @@ static bool PauseAndLock(bool do_lock, bool unpause_on_unlock) if (!IsRunning()) return true; - // let's support recursive locking to simplify things on the caller's side, - // and let's do it at this outer level in case the individual systems don't support it. - if (do_lock ? s_pause_and_lock_depth++ : --s_pause_and_lock_depth) - return true; - bool was_unpaused = true; if (do_lock) {