Merge pull request #5803 from leoetlino/pause-and-lock

Replace balanced Core::PauseAndLock calls with RunAsCPUThread
This commit is contained in:
JosJuice 2017-07-22 12:42:55 +02:00 committed by GitHub
commit 57affaff22
13 changed files with 300 additions and 323 deletions

View File

@ -102,7 +102,6 @@ static StoppedCallbackFunc s_on_stopped_callback;
static std::thread s_cpu_thread; static std::thread s_cpu_thread;
static bool s_request_refresh_info = false; static bool s_request_refresh_info = false;
static int s_pause_and_lock_depth = 0;
static bool s_is_throttler_temp_disabled = false; static bool s_is_throttler_temp_disabled = false;
struct HostJob struct HostJob
@ -759,17 +758,12 @@ void RequestRefreshInfo()
s_request_refresh_info = true; 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 // WARNING: PauseAndLock is not fully threadsafe so is only valid on the Host Thread
if (!IsRunning()) if (!IsRunning())
return true; 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; bool was_unpaused = true;
if (do_lock) if (do_lock)
{ {
@ -806,6 +800,19 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock)
return was_unpaused; return was_unpaused;
} }
void RunAsCPUThread(std::function<void()> 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 // Display FPS info
// This should only be called from VI // This should only be called from VI
void VideoThrottle() void VideoThrottle()
@ -955,22 +962,20 @@ void UpdateWantDeterminism(bool initial)
{ {
NOTICE_LOG(COMMON, "Want determinism <- %s", new_want_determinism ? "true" : "false"); 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; // Don't call InitializeWiiRoot during boot, because IOS already does it.
const auto ios = IOS::HLE::GetIOS(); if (!initial)
if (ios) Core::InitializeWiiRoot(s_wants_determinism);
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);
} }
} }

View File

@ -74,12 +74,14 @@ void RequestRefreshInfo();
void UpdateTitle(); void UpdateTitle();
// waits until all systems are paused and fully idle, and acquires a lock on that state. // Run a function as the CPU thread.
// 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. // If called from the Host thread, the CPU thread is paused and the current thread temporarily
// the return value of the first call should be passed in as the second argument of the second call. // becomes the CPU thread while running the function.
// [NOT THREADSAFE] Host only // If called from the CPU thread, the function will be run directly.
bool PauseAndLock(bool doLock, bool unpauseOnUnlock = true); //
// This should only be called from the CPU thread or the host thread.
void RunAsCPUThread(std::function<void()> function);
// for calling back into UI code without introducing a dependency on it in core // for calling back into UI code without introducing a dependency on it in core
using StoppedCallbackFunc = std::function<void()>; using StoppedCallbackFunc = std::function<void()>;

View File

@ -476,12 +476,7 @@ static void InsertDiscCallback(u64 userdata, s64 cyclesLate)
// Can only be called by the host thread // Can only be called by the host thread
void ChangeDiscAsHost(const std::string& new_path) void ChangeDiscAsHost(const std::string& new_path)
{ {
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] { ChangeDiscAsCPU(new_path); });
// The host thread is now temporarily the CPU thread
ChangeDiscAsCPU(new_path);
Core::PauseAndLock(false, was_unpaused);
} }
// Can only be called by the CPU thread // Can only be called by the CPU thread

View File

@ -544,68 +544,66 @@ bool BeginRecordingInput(int controllers)
if (s_playMode != MODE_NONE || controllers == 0) if (s_playMode != MODE_NONE || controllers == 0)
return false; 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_rerecords = 0;
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; 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 (Core::IsRunningAndStarted())
{ {
if (SConfig::GetInstance().m_SIDevice[i] == SerialInterface::SIDEVICE_GC_TARUKONGA) const std::string save_path = File::GetUserPath(D_STATESAVES_IDX) + "dtm.sav";
s_bongos |= (1 << i); if (File::Exists(save_path))
} File::Delete(save_path);
if (Core::IsRunningAndStarted()) State::SaveAs(save_path);
{ s_bRecordingFromSaveState = true;
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); std::thread md5thread(GetMD5);
s_bRecordingFromSaveState = true; md5thread.detach();
GetSettings();
}
std::thread md5thread(GetMD5); // Wiimotes cause desync issues if they're not reset before launching the game
md5thread.detach(); if (!Core::IsRunningAndStarted())
GetSettings(); {
} // 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 s_playMode = MODE_RECORDING;
if (!Core::IsRunningAndStarted()) s_author = SConfig::GetInstance().m_strMovieAuthor;
{ s_temp_input.clear();
// This will also reset the wiimotes for gamecube games, but that shouldn't do anything
Wiimote::ResetAllWiimotes();
}
s_playMode = MODE_RECORDING; s_currentByte = 0;
s_author = SConfig::GetInstance().m_strMovieAuthor;
s_temp_input.clear();
s_currentByte = 0; if (Core::IsRunning())
Core::UpdateWantDeterminism();
if (Core::IsRunning()) });
Core::UpdateWantDeterminism();
Core::PauseAndLock(false, was_unpaused);
Core::DisplayMessage("Starting movie recording", 2000); Core::DisplayMessage("Starting movie recording", 2000);
return true; return true;

View File

@ -174,14 +174,14 @@ void MemChecks::Add(const TMemCheck& memory_check)
if (GetMemCheck(memory_check.start_address) == nullptr) if (GetMemCheck(memory_check.start_address) == nullptr)
{ {
bool had_any = HasAny(); bool had_any = HasAny();
bool lock = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
m_mem_checks.push_back(memory_check); m_mem_checks.push_back(memory_check);
// If this is the first one, clear the JIT cache so it can switch to // If this is the first one, clear the JIT cache so it can switch to
// watchpoint-compatible code. // watchpoint-compatible code.
if (!had_any && g_jit) if (!had_any && g_jit)
g_jit->ClearCache(); g_jit->ClearCache();
PowerPC::DBATUpdated(); PowerPC::DBATUpdated();
Core::PauseAndLock(false, lock); });
} }
} }
@ -191,12 +191,12 @@ void MemChecks::Remove(u32 address)
{ {
if (i->start_address == address) if (i->start_address == address)
{ {
bool lock = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
m_mem_checks.erase(i); m_mem_checks.erase(i);
if (!HasAny() && g_jit) if (!HasAny() && g_jit)
g_jit->ClearCache(); g_jit->ClearCache();
PowerPC::DBATUpdated(); PowerPC::DBATUpdated();
Core::PauseAndLock(false, lock); });
return; return;
} }
} }

View File

@ -207,42 +207,36 @@ void LoadFromBuffer(std::vector<u8>& buffer)
return; return;
} }
bool wasUnpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
u8* ptr = &buffer[0];
u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_READ);
PointerWrap p(&ptr, PointerWrap::MODE_READ); DoState(p);
DoState(p); });
Core::PauseAndLock(false, wasUnpaused);
} }
void SaveToBuffer(std::vector<u8>& buffer) void SaveToBuffer(std::vector<u8>& buffer)
{ {
bool wasUnpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
u8* ptr = nullptr;
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
u8* ptr = nullptr; DoState(p);
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); const size_t buffer_size = reinterpret_cast<size_t>(ptr);
buffer.resize(buffer_size);
DoState(p); ptr = &buffer[0];
const size_t buffer_size = reinterpret_cast<size_t>(ptr); p.SetMode(PointerWrap::MODE_WRITE);
buffer.resize(buffer_size); DoState(p);
});
ptr = &buffer[0];
p.SetMode(PointerWrap::MODE_WRITE);
DoState(p);
Core::PauseAndLock(false, wasUnpaused);
} }
void VerifyBuffer(std::vector<u8>& buffer) void VerifyBuffer(std::vector<u8>& buffer)
{ {
bool wasUnpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
u8* ptr = &buffer[0];
u8* ptr = &buffer[0]; PointerWrap p(&ptr, PointerWrap::MODE_VERIFY);
PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); DoState(p);
DoState(p); });
Core::PauseAndLock(false, wasUnpaused);
} }
// return state number not in map // 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) void SaveAs(const std::string& filename, bool wait)
{ {
// Pause the core while we save the state Core::RunAsCPUThread([&] {
bool wasUnpaused = Core::PauseAndLock(true); // Measure the size of the buffer.
u8* ptr = nullptr;
// Measure the size of the buffer. PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
u8* ptr = nullptr;
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
DoState(p);
const size_t buffer_size = reinterpret_cast<size_t>(ptr);
// Then actually do the write.
{
std::lock_guard<std::mutex> lk(g_cs_current_buffer);
g_current_buffer.resize(buffer_size);
ptr = &g_current_buffer[0];
p.SetMode(PointerWrap::MODE_WRITE);
DoState(p); DoState(p);
} const size_t buffer_size = reinterpret_cast<size_t>(ptr);
if (p.GetMode() == PointerWrap::MODE_WRITE) // Then actually do the write.
{ {
Core::DisplayMessage("Saving State...", 1000); std::lock_guard<std::mutex> 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; if (p.GetMode() == PointerWrap::MODE_WRITE)
save_args.buffer_vector = &g_current_buffer; {
save_args.buffer_mutex = &g_cs_current_buffer; Core::DisplayMessage("Saving State...", 1000);
save_args.filename = filename;
save_args.wait = wait;
Flush(); CompressAndDumpState_args save_args;
g_save_thread = std::thread(CompressAndDumpState, save_args); save_args.buffer_vector = &g_current_buffer;
g_compressAndDumpStateSyncEvent.Wait(); save_args.buffer_mutex = &g_cs_current_buffer;
save_args.filename = filename;
save_args.wait = wait;
g_last_filename = filename; Flush();
} g_save_thread = std::thread(CompressAndDumpState, save_args);
else g_compressAndDumpStateSyncEvent.Wait();
{
// someone aborted the save by changing the mode?
Core::DisplayMessage("Unable to save: Internal DoState Error", 4000);
}
// Resume the core and disable stepping g_last_filename = filename;
Core::PauseAndLock(false, wasUnpaused); }
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) bool ReadHeader(const std::string& filename, StateHeader& header)
@ -549,72 +539,68 @@ void LoadAs(const std::string& filename)
return; return;
} }
// Stop the core while we load the state Core::RunAsCPUThread([&] {
bool wasUnpaused = Core::PauseAndLock(true); g_loadDepth++;
g_loadDepth++; // Save temp buffer for undo load state
if (!Movie::IsJustStartingRecordingInputFromSaveState())
// Save temp buffer for undo load state
if (!Movie::IsJustStartingRecordingInputFromSaveState())
{
std::lock_guard<std::mutex> 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<u8> buffer;
LoadFileStateData(filename, buffer);
if (!buffer.empty())
{ {
u8* ptr = &buffer[0]; std::lock_guard<std::mutex> lk(g_cs_undo_load_buffer);
PointerWrap p(&ptr, PointerWrap::MODE_READ); SaveToBuffer(g_undo_load_buffer);
version_created_by = DoState(p); if (Movie::IsMovieActive())
loaded = true; Movie::SaveRecording(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm");
loadedSuccessfully = (p.GetMode() == PointerWrap::MODE_READ); else if (File::Exists(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm"))
File::Delete(File::GetUserPath(D_STATESAVES_IDX) + "undo.dtm");
} }
}
if (loaded) bool loaded = false;
{ bool loadedSuccessfully = false;
if (loadedSuccessfully) std::string version_created_by;
// brackets here are so buffer gets freed ASAP
{ {
Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000); std::vector<u8> buffer;
if (File::Exists(filename + ".dtm")) LoadFileStateData(filename, buffer);
Movie::LoadInput(filename + ".dtm");
else if (!Movie::IsJustStartingRecordingInputFromSaveState() && if (!buffer.empty())
!Movie::IsJustStartingPlayingInputFromSaveState()) {
Movie::EndPlayInput(false); 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 if (loadedSuccessfully)
Core::DisplayMessage("Unable to load: Can't load state from other versions!", 4000); {
if (!version_created_by.empty()) Core::DisplayMessage(StringFromFormat("Loaded state from %s", filename.c_str()), 2000);
Core::DisplayMessage("The savestate was created using " + version_created_by, 4000); 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. // since we could be in an inconsistent state now (and might crash or whatever), undo.
if (g_loadDepth < 2) if (g_loadDepth < 2)
UndoLoadState(); UndoLoadState();
}
} }
}
if (s_on_after_load_callback) if (s_on_after_load_callback)
s_on_after_load_callback(); s_on_after_load_callback();
g_loadDepth--; g_loadDepth--;
});
// resume dat core
Core::PauseAndLock(false, wasUnpaused);
} }
void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback) void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback)
@ -624,24 +610,22 @@ void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback)
void VerifyAt(const std::string& filename) void VerifyAt(const std::string& filename)
{ {
bool wasUnpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
std::vector<u8> buffer;
LoadFileStateData(filename, buffer);
std::vector<u8> buffer; if (!buffer.empty())
LoadFileStateData(filename, buffer); {
u8* ptr = &buffer[0];
PointerWrap p(&ptr, PointerWrap::MODE_VERIFY);
DoState(p);
if (!buffer.empty()) if (p.GetMode() == PointerWrap::MODE_VERIFY)
{ Core::DisplayMessage(StringFromFormat("Verified state at %s", filename.c_str()), 2000);
u8* ptr = &buffer[0]; else
PointerWrap p(&ptr, PointerWrap::MODE_VERIFY); Core::DisplayMessage("Unable to Verify : Can't verify state from other revisions !", 4000);
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);
} }
void Init() void Init()

View File

@ -137,13 +137,13 @@ void Host_ConnectWiimote(int wm_idx, bool connect)
const auto ios = IOS::HLE::GetIOS(); const auto ios = IOS::HLE::GetIOS();
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
return; return;
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>( const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")); ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt) if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
Host_UpdateMainFrame(); Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused); });
}); });
} }

View File

@ -237,25 +237,24 @@ void IOWindow::UpdateDeviceList()
m_block.Set(true); m_block.Set(true);
m_devices_combo->clear(); 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(); // Adding default device regardless if it's currently connected or not
m_controller->UpdateReferences(g_controller_interface); const auto default_device = m_controller->default_device.ToString();
m_controller->UpdateDefaultDevice();
// Adding default device regardless if it's currently connected or not m_devices_combo->addItem(QString::fromStdString(default_device));
const auto default_device = m_controller->default_device.ToString();
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()) m_devices_combo->setCurrentIndex(0);
{ });
if (name != default_device)
m_devices_combo->addItem(QString::fromStdString(name));
}
m_devices_combo->setCurrentIndex(0);
Core::PauseAndLock(false, paused);
m_block.Set(false); m_block.Set(false);
} }

View File

@ -229,25 +229,23 @@ void MappingWindow::RefreshDevices()
{ {
m_devices_combo->clear(); 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(); const auto default_device = m_controller->default_device.ToString();
m_controller->UpdateReferences(g_controller_interface);
m_controller->UpdateDefaultDevice();
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()) m_devices_combo->setCurrentIndex(0);
{ });
if (name != default_device)
m_devices_combo->addItem(QString::fromStdString(name));
}
m_devices_combo->setCurrentIndex(0);
Core::PauseAndLock(false, paused);
} }
void MappingWindow::ChangeMappingType(MappingWindow::Type type) void MappingWindow::ChangeMappingType(MappingWindow::Type type)

View File

@ -71,12 +71,12 @@ void GCAdapterConfigDiag::ScheduleAdapterUpdate()
void GCAdapterConfigDiag::OnUpdateAdapter(wxCommandEvent& WXUNUSED(event)) void GCAdapterConfigDiag::OnUpdateAdapter(wxCommandEvent& WXUNUSED(event))
{ {
bool unpause = Core::PauseAndLock(true); Core::RunAsCPUThread([this] {
if (GCAdapter::IsDetected()) if (GCAdapter::IsDetected())
m_adapter_status->SetLabelText(_("Adapter Detected")); m_adapter_status->SetLabelText(_("Adapter Detected"));
else else
m_adapter_status->SetLabelText(_("Adapter Not Detected")); m_adapter_status->SetLabelText(_("Adapter Not Detected"));
Core::PauseAndLock(false, unpause); });
} }
void GCAdapterConfigDiag::OnAdapterRumble(wxCommandEvent& event) void GCAdapterConfigDiag::OnAdapterRumble(wxCommandEvent& event)

View File

@ -1249,9 +1249,7 @@ void CFrame::DoExclusiveFullscreen(bool enable_fullscreen)
if (!g_renderer || g_renderer->IsFullscreen() == enable_fullscreen) if (!g_renderer || g_renderer->IsFullscreen() == enable_fullscreen)
return; return;
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([enable_fullscreen] { g_renderer->SetFullscreen(enable_fullscreen); });
g_renderer->SetFullscreen(enable_fullscreen);
Core::PauseAndLock(false, was_unpaused);
} }
void CFrame::PollHotkeys(wxTimerEvent& event) void CFrame::PollHotkeys(wxTimerEvent& event)

View File

@ -1411,19 +1411,19 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
if (Core::IsRunning() && SConfig::GetInstance().bWii && if (Core::IsRunning() && SConfig::GetInstance().bWii &&
!SConfig::GetInstance().m_bt_passthrough_enabled) !SConfig::GetInstance().m_bt_passthrough_enabled)
{ {
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
const auto ios = IOS::HLE::GetIOS(); const auto ios = IOS::HLE::GetIOS();
if (!ios) if (!ios)
return; return;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>( const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")); ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt) if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected"; const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected";
Core::DisplayMessage(StringFromFormat(message, wm_idx + 1), 3000); Core::DisplayMessage(StringFromFormat(message, wm_idx + 1), 3000);
Host_UpdateMainFrame(); Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused); });
} }
} }
@ -1432,13 +1432,13 @@ void CFrame::OnConnectWiimote(wxCommandEvent& event)
const auto ios = IOS::HLE::GetIOS(); const auto ios = IOS::HLE::GetIOS();
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
return; return;
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>( const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")); ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
const bool is_connected = const bool is_connected =
bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected(); bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected();
ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected); ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected);
Core::PauseAndLock(false, was_unpaused); });
} }
// Toggle fullscreen. In Windows the fullscreen mode is accomplished by expanding the m_panel to // 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); GetMenuBar()->FindItem(IDM_CONNECT_BALANCEBOARD)->Enable(ShouldEnableWiimotes);
if (ShouldEnableWiimotes) if (ShouldEnableWiimotes)
{ {
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(bt->AccessWiiMote(0x0100)->IsConnected()); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(bt->AccessWiiMote(0x0100)->IsConnected());
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(bt->AccessWiiMote(0x0101)->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_WIIMOTE3)->Check(bt->AccessWiiMote(0x0102)->IsConnected());
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(bt->AccessWiiMote(0x0103)->IsConnected()); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(bt->AccessWiiMote(0x0103)->IsConnected());
GetMenuBar() GetMenuBar()
->FindItem(IDM_CONNECT_BALANCEBOARD) ->FindItem(IDM_CONNECT_BALANCEBOARD)
->Check(bt->AccessWiiMote(0x0104)->IsConnected()); ->Check(bt->AccessWiiMote(0x0104)->IsConnected());
Core::PauseAndLock(false, was_unpaused); });
} }
GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Enable(Running || Paused); GetMenuBar()->FindItem(IDM_RECORD_READ_ONLY)->Enable(Running || Paused);

View File

@ -915,25 +915,23 @@ void InputConfigDialog::UpdateDeviceComboBox()
void InputConfigDialog::RefreshDevices(wxCommandEvent&) void InputConfigDialog::RefreshDevices(wxCommandEvent&)
{ {
bool was_unpaused = Core::PauseAndLock(true); Core::RunAsCPUThread([&] {
// refresh devices
g_controller_interface.RefreshDevices();
// refresh devices // update all control references
g_controller_interface.RefreshDevices(); UpdateControlReferences();
// update all control references // update device cbox
UpdateControlReferences(); UpdateDeviceComboBox();
// update device cbox Wiimote::LoadConfig();
UpdateDeviceComboBox(); Keyboard::LoadConfig();
Pad::LoadConfig();
HotkeyManagerEmu::LoadConfig();
Wiimote::LoadConfig(); UpdateGUI();
Keyboard::LoadConfig(); });
Pad::LoadConfig();
HotkeyManagerEmu::LoadConfig();
UpdateGUI();
Core::PauseAndLock(false, was_unpaused);
} }
ControlGroupBox::~ControlGroupBox() ControlGroupBox::~ControlGroupBox()