From 5fa2043e069638b0de908703475ad05840d489f8 Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Mon, 30 Dec 2024 17:05:07 +0200 Subject: [PATCH] LV2: Usleep loop pattern recognition --- rpcs3/Emu/Cell/PPUThread.h | 5 +++++ rpcs3/Emu/Cell/lv2/lv2.cpp | 23 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 9f94ad50f6..df95875200 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -300,6 +300,11 @@ public: const char* last_function{}; // Sticky copy of current_function, is not cleared on function return const char* current_module{}; // Current module name, for savestates. + // Sycall pattern recognition variables + u64 last_lv2_deschedule_cia = umax; // Position of syscall that puts the PPU to sleep + u64 last_lv2_deschedule_r3 = umax; // R3 argument of syscall that puts the PPU to sleep + u64 last_lv2_deschedule_match_count = 0; // Arguments matching count when PPU puts to sleep + const bool is_interrupt_thread; // True for interrupts-handler threads // Thread name diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index c6d69d8827..73ea2adc45 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1339,11 +1339,13 @@ bool lv2_obj::sleep(cpu_thread& cpu, const u64 timeout) if (cpu.get_class() == thread_class::ppu) { - if (u32 addr = static_cast(cpu).res_notify) - { - static_cast(cpu).res_notify = 0; + ppu_thread& ppu = static_cast(cpu); - if (static_cast(cpu).res_notify_time != vm::reservation_notifier_count_index(addr).second) + if (u32 addr = ppu.res_notify) + { + ppu.res_notify = 0; + + if (ppu.res_notify_time != vm::reservation_notifier_count_index(addr).second) { // Ignore outdated notification request } @@ -1362,6 +1364,17 @@ bool lv2_obj::sleep(cpu_thread& cpu, const u64 timeout) vm::reservation_notifier_notify(addr); } } + + if (ppu.last_lv2_deschedule_cia == ppu.cia && ppu.last_lv2_deschedule_r3 == ppu.gpr[3]) + { + ppu.last_lv2_deschedule_match_count++; + } + else + { + ppu.last_lv2_deschedule_cia = ppu.cia; + ppu.last_lv2_deschedule_r3 = ppu.gpr[3]; + ppu.last_lv2_deschedule_match_count = 0; + } } bool result = false; @@ -2178,7 +2191,7 @@ bool lv2_obj::wait_timeout(u64 usec, ppu_thread* cpu, bool scale, bool is_usleep static atomic_t g_success = 0; static atomic_t g_fails = 0; - if (accuracy_type == sleep_timers_accuracy_level::_dynamic && avg_delay < 30 && avg_delay < (remaining + 15) / 2) + if ((accuracy_type == sleep_timers_accuracy_level::_dynamic && avg_delay < 30) && ((avg_delay < (remaining + 15) / 2) || (cpu && cpu->last_lv2_deschedule_match_count > 3))) { wait_for(remaining);