From b11e8f8b8d40e8c2b6fabbb40061d27f3490fec3 Mon Sep 17 00:00:00 2001 From: Eladash Date: Wed, 18 Mar 2020 21:44:58 +0200 Subject: [PATCH] Minor fix of sys_ppu_thread_yield return value Account for a special case where threads were rotated but no context switch was made. --- rpcs3/Emu/Cell/lv2/lv2.cpp | 32 +++++++++++++++++++++------ rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_sync.h | 2 +- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 2454d93074..519d94a687 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1162,16 +1162,34 @@ bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) if (const auto ppu = g_ppu[i]; ppu == cpu) { - if (g_ppu[i + 1]->prio != ppu->prio) + std::size_t j = i + 1; + + for (; j < g_ppu.size(); j++) { + if (g_ppu[j]->prio != ppu->prio) + { + break; + } + } + + if (j == i + 1) + { + // Empty 'same prio' threads list return false; } - else + + // Rotate current thread to the last position of the 'same prio' threads list + std::rotate(g_ppu.begin() + i, g_ppu.begin() + i + 1, g_ppu.begin() + j); + + if (j <= g_cfg.core.ppu_threads + 0u) { - g_ppu.erase(g_ppu.cbegin() + i); - ppu->start_time = get_guest_system_time(); - break; + // Threads were rotated, but no context switch was made + return false; } + + ppu->start_time = get_guest_system_time(); + cpu = nullptr; // Disable current thread enqueing, also enable threads list enqueing + break; } } } @@ -1227,9 +1245,9 @@ bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) } // Remove pending if necessary - if (!g_pending.empty() && cpu && cpu == get_current_cpu_thread()) + if (!g_pending.empty() && ((cpu && cpu == get_current_cpu_thread()) || prio == yield_cmd)) { - unqueue(g_pending, cpu); + unqueue(g_pending, get_current_cpu_thread()); } // Suspend threads if necessary diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index 5392decd44..d16863cb41 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -82,7 +82,7 @@ s32 sys_ppu_thread_yield(ppu_thread& ppu) { sys_ppu_thread.trace("sys_ppu_thread_yield()"); - // Return 1 on no-op, 0 on successful context switch + // Return 0 on successful context switch, 1 otherwise return +!lv2_obj::yield(ppu); } diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index af24552833..262a5d4fd6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -159,7 +159,7 @@ public: return awake_unlocked(thread, prio); } - // Returns true and success, false if did nothing + // Returns true on successful context switch, false otherwise static bool yield(cpu_thread& thread) { vm::temporary_unlock(thread);