mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
Fix Emulation::CallAfter
Most CallAfter usages were extremely wrong when ordered after Emu.Stop(). could result in anywhere from emulation stopping hangs to even segfaults. track_emu_state = true is now the default, I haven't found cases which need need it disabled.
This commit is contained in:
parent
68a878264c
commit
112b7f6571
5 changed files with 40 additions and 23 deletions
|
@ -138,7 +138,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
|
|||
}
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
atomic_t<bool> result = false;
|
||||
|
||||
osk->on_osk_close = [maxLength, wptr = std::weak_ptr<OskDialogBase>(osk)](s32 status)
|
||||
{
|
||||
|
@ -192,7 +192,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> 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<CellOskDialogParam> 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;
|
||||
|
|
|
@ -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<named_thread<ppu_thread>>(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<sys_exit2_param> ar
|
|||
if (disc.empty() && !Emu.GetTitleID().empty())
|
||||
disc = vfs::get(Emu.GetDir());
|
||||
|
||||
Emu.CallAfter([s_ppu = idm::get<named_thread<ppu_thread>>(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<loaded_npdrm_keys>()->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<loaded_npdrm_keys>()->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();
|
||||
|
|
|
@ -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<rsx::thread>())
|
||||
|
|
|
@ -69,6 +69,7 @@ class Emulator final
|
|||
|
||||
atomic_t<u64> m_pause_start_time{0}; // set when paused
|
||||
atomic_t<u64> m_pause_amend_time{0}; // increased when resumed
|
||||
atomic_t<u64> 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<void()>&& func) const
|
||||
void CallAfter(std::function<void()>&& 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<void()> 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<std::string> 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();
|
||||
};
|
||||
|
|
|
@ -35,11 +35,12 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& 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);
|
||||
|
|
Loading…
Add table
Reference in a new issue