diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 941115f777..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 @@ -759,17 +758,12 @@ 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()) 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) { @@ -806,6 +800,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 +962,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()