diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index 2a816d9839..4df615ff18 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -138,7 +138,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia } } - bool result = false; + atomic_t result = false; osk->on_osk_close = [maxLength, wptr = std::weak_ptr(osk)](s32 status) { @@ -192,7 +192,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia }); // wait for check callback - while (!done) + while (!done && !Emu.IsStopped()) { std::this_thread::yield(); } @@ -249,13 +249,14 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia { osk->Create(get_localized_string(localized_string_id::CELL_OSK_DIALOG_TITLE), message, osk->osk_text, maxLength, prohibitFlgs, allowOskPanelFlg, firstViewPanel); result = true; + result.notify_one(); }); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0); - while (!result) + while (!result && !Emu.IsStopped()) { - thread_ctrl::wait_for(1000); + thread_ctrl::wait_on(result, false); } return CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_process.cpp b/rpcs3/Emu/Cell/lv2/sys_process.cpp index 41234b0a13..5f10589207 100644 --- a/rpcs3/Emu/Cell/lv2/sys_process.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_process.cpp @@ -336,15 +336,8 @@ void _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3) sys_process.warning("_sys_process_exit(status=%d, arg2=0x%x, arg3=0x%x)", status, arg2, arg3); - // Get shared ptr to current PPU - Emu.CallAfter([s_ppu = idm::get>(ppu.id)]() + Emu.CallAfter([]() { - if (s_ppu->is_stopped()) - { - // Stop() was already executed from a signal before - return; - } - sys_process.success("Process finished"); Emu.Stop(); }); @@ -408,14 +401,8 @@ void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr ar if (disc.empty() && !Emu.GetTitleID().empty()) disc = vfs::get(Emu.GetDir()); - Emu.CallAfter([s_ppu = idm::get>(ppu.id), path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data), disc = std::move(disc), hdd1 = std::move(hdd1), klic = g_fxo->get()->devKlic.load()]() mutable + Emu.CallAfter([path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data), disc = std::move(disc), hdd1 = std::move(hdd1), klic = g_fxo->get()->devKlic.load()]() mutable { - if (s_ppu->is_stopped()) - { - // Stop() was already executed from a signal before - return; - } - sys_process.success("Process finished -> %s", argv[0]); Emu.SetForceBoot(true); Emu.Stop(); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index cb753a4ece..18a3352e63 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1873,6 +1873,9 @@ void Emulator::Stop(bool restart) sys_log.notice("Stopping emulator..."); + m_stop_ctr++; + m_stop_ctr.notify_all(); + GetCallbacks().on_stop(); if (auto rsx = g_fxo->get()) diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index f18a79f4fa..a0c650d33a 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -69,6 +69,7 @@ class Emulator final atomic_t m_pause_start_time{0}; // set when paused atomic_t m_pause_amend_time{0}; // increased when resumed + atomic_t m_stop_ctr{0}; // Increments when emulation is stopped video_renderer m_default_renderer; std::string m_default_graphics_adapter; @@ -109,9 +110,22 @@ public: } // Call from the GUI thread - void CallAfter(std::function&& func) const + void CallAfter(std::function&& func, bool track_emu_state = true) const { - return m_cb.call_after(std::move(func)); + if (!track_emu_state) + { + return m_cb.call_after(std::move(func)); + } + + std::function final_func = [this, before = IsStopped(), count = +m_stop_ctr, func = std::move(func)] + { + if (count == m_stop_ctr && before == IsStopped()) + { + func(); + } + }; + + return m_cb.call_after(std::move(final_func)); } /** Set emulator mode to running unconditionnaly. @@ -245,6 +259,17 @@ public: std::set GetGameDirs() const; + u64 GetEmulationCounter() const + { + return m_stop_ctr; + } + + void WaitEmulationCounter(u64 old = -1) const + { + if (old == umax) old = m_stop_ctr; // Use current if not specified + if (m_stop_ctr == old) m_stop_ctr.wait(old); + } + private: void LimitCacheSize(); }; diff --git a/rpcs3/rpcs3qt/save_data_dialog.cpp b/rpcs3/rpcs3qt/save_data_dialog.cpp index 88557bff4c..4ede1197c2 100644 --- a/rpcs3/rpcs3qt/save_data_dialog.cpp +++ b/rpcs3/rpcs3qt/save_data_dialog.cpp @@ -35,11 +35,12 @@ s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, sdid.exec(); selection = sdid.GetSelection(); dlg_result = true; + dlg_result.notify_one(); }); - while (!dlg_result) + while (!dlg_result && !Emu.IsStopped()) { - thread_ctrl::wait_for(1000); + thread_ctrl::wait_on(dlg_result, false); } input::SetIntercepted(false);