Savestates Support For PS3 Emulation (#10478)

This commit is contained in:
Elad Ashkenazi 2022-07-04 16:02:17 +03:00 committed by GitHub
parent 969b9eb89d
commit fcd297ffb2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
154 changed files with 4948 additions and 635 deletions

View file

@ -1190,6 +1190,7 @@ DECLARE(lv2_obj::g_mutex);
DECLARE(lv2_obj::g_ppu);
DECLARE(lv2_obj::g_pending);
DECLARE(lv2_obj::g_waiting);
DECLARE(lv2_obj::g_to_sleep);
thread_local DECLARE(lv2_obj::g_to_awake);
@ -1256,6 +1257,32 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout)
// Find and remove the thread
if (!unqueue(g_ppu, ppu))
{
if (unqueue(g_to_sleep, ppu))
{
ppu->start_time = start_time;
std::string out = fmt::format("Threads (%d):", g_to_sleep.size());
for (auto thread : g_to_sleep)
{
fmt::append(out, " 0x%x,", thread->id);
}
ppu_log.warning("%s", out);
if (g_to_sleep.empty())
{
// All threads are ready, wake threads
Emu.CallFromMainThread([]
{
if (Emu.IsStarting())
{
// It uses lv2_obj::g_mutex, run it on main thread
Emu.FinalizeRunRequest();
}
});
}
}
// Already sleeping
ppu_log.trace("sleep(): called on already sleeping thread.");
return;
@ -1438,11 +1465,12 @@ void lv2_obj::cleanup()
g_ppu.clear();
g_pending.clear();
g_waiting.clear();
g_to_sleep.clear();
}
void lv2_obj::schedule_all()
{
if (g_pending.empty())
if (g_pending.empty() && g_to_sleep.empty())
{
// Wake up threads
for (usz i = 0, x = std::min<usz>(g_cfg.core.ppu_threads, g_ppu.size()); i < x; i++)
@ -1486,7 +1514,7 @@ ppu_thread_status lv2_obj::ppu_state(ppu_thread* ppu, bool lock_idm, bool lock_l
opt_lock[0].emplace(id_manager::g_mutex);
}
if (ppu->state & cpu_flag::stop)
if (!Emu.IsReady() ? ppu->state.all_of(cpu_flag::stop) : ppu->stop_flag_removal_protection)
{
return PPU_THREAD_STATUS_IDLE;
}
@ -1507,6 +1535,11 @@ ppu_thread_status lv2_obj::ppu_state(ppu_thread* ppu, bool lock_idm, bool lock_l
if (it == g_ppu.end())
{
if (!ppu->interrupt_thread_executing)
{
return PPU_THREAD_STATUS_STOP;
}
return PPU_THREAD_STATUS_SLEEP;
}
@ -1517,3 +1550,14 @@ ppu_thread_status lv2_obj::ppu_state(ppu_thread* ppu, bool lock_idm, bool lock_l
return PPU_THREAD_STATUS_ONPROC;
}
void lv2_obj::set_future_sleep(ppu_thread* ppu)
{
g_to_sleep.emplace_back(ppu);
}
bool lv2_obj::is_scheduler_ready()
{
reader_lock lock(g_mutex);
return g_to_sleep.empty();
}