From 664d606123b79d0553fb046a02ce83c12382b7ca Mon Sep 17 00:00:00 2001 From: Eladash Date: Mon, 16 Mar 2020 16:55:08 +0200 Subject: [PATCH] Add return value of sys_ppu_thread_yield --- rpcs3/Emu/Cell/lv2/lv2.cpp | 44 +++++++++++++++------------ rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp | 5 +-- rpcs3/Emu/Cell/lv2/sys_ppu_thread.h | 2 +- rpcs3/Emu/Cell/lv2/sys_sync.h | 11 ++++--- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 0f2612e9a6..2454d93074 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1133,7 +1133,7 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout) } } -void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) +bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) { // Check thread type AUDIT(!cpu || cpu->id_type() == 1); @@ -1145,7 +1145,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) // Priority set if (static_cast(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, cpu)) { - return; + return true; } break; @@ -1153,25 +1153,27 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) case yield_cmd: { // Yield command - const u64 start_time = get_guest_system_time(); - - for (std::size_t i = 0, pos = -1; i < g_ppu.size(); i++) + for (std::size_t i = 0;; i++) { - if (g_ppu[i] == cpu) + if (i + 1 >= g_ppu.size()) { - pos = i; - prio = g_ppu[i]->prio; + return false; } - else if (i == pos + 1 && prio != -4 && g_ppu[i]->prio != prio) + + if (const auto ppu = g_ppu[i]; ppu == cpu) { - return; + if (g_ppu[i + 1]->prio != ppu->prio) + { + return false; + } + else + { + g_ppu.erase(g_ppu.cbegin() + i); + ppu->start_time = get_guest_system_time(); + break; + } } } - - unqueue(g_ppu, cpu); - unqueue(g_pending, cpu); - - static_cast(cpu)->start_time = start_time; } case enqueue_cmd: { @@ -1186,7 +1188,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) if (it != end && *it == cpu) { ppu_log.trace("sleep() - suspended (p=%zu)", g_pending.size()); - return; + return false; } // Use priority, also preserve FIFO order @@ -1208,17 +1210,20 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) } ppu_log.trace("awake(): %s", cpu->id); + return true; }; + bool changed_queue = false; + if (cpu) { // Emplace current thread - emplace_thread(cpu); + changed_queue = emplace_thread(cpu); } else for (const auto _cpu : g_to_awake) { // Emplace threads from list - emplace_thread(_cpu); + changed_queue |= emplace_thread(_cpu); } // Remove pending if necessary @@ -1228,7 +1233,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) } // Suspend threads if necessary - for (std::size_t i = g_cfg.core.ppu_threads; i < g_ppu.size(); i++) + for (std::size_t i = g_cfg.core.ppu_threads; changed_queue && i < g_ppu.size(); i++) { const auto target = g_ppu[i]; @@ -1240,6 +1245,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio) } schedule_all(); + return changed_queue; } void lv2_obj::cleanup() diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index a0f88420a0..5392decd44 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -78,11 +78,12 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode) } } -void sys_ppu_thread_yield(ppu_thread& ppu) +s32 sys_ppu_thread_yield(ppu_thread& ppu) { sys_ppu_thread.trace("sys_ppu_thread_yield()"); - lv2_obj::yield(ppu); + // Return 1 on no-op, 0 on successful context switch + return +!lv2_obj::yield(ppu); } error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr vptr) diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.h b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.h index 4ab89b0ef6..63ee0c69b3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.h @@ -56,7 +56,7 @@ enum : u32 // Syscalls void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode); -void sys_ppu_thread_yield(ppu_thread& ppu); +s32 sys_ppu_thread_yield(ppu_thread& ppu); // Return value is ignored by the library error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr vptr); error_code sys_ppu_thread_detach(u32 thread_id); error_code sys_ppu_thread_get_join_state(ppu_thread& ppu, vm::ptr isjoinable); // Error code is ignored by the library diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index 75f73927ce..2ce6a83a6e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -130,7 +130,7 @@ private: static void sleep_unlocked(cpu_thread&, u64 timeout); // Schedule the thread - static void awake_unlocked(cpu_thread*, s32 prio = enqueue_cmd); + static bool awake_unlocked(cpu_thread*, s32 prio = enqueue_cmd); public: static void sleep(cpu_thread& cpu, const u64 timeout = 0) @@ -140,16 +140,17 @@ public: g_to_awake.clear(); } - static inline void awake(cpu_thread* const thread, s32 prio = enqueue_cmd) + static inline bool awake(cpu_thread* const thread, s32 prio = enqueue_cmd) { std::lock_guard lock(g_mutex); - awake_unlocked(thread, prio); + return awake_unlocked(thread, prio); } - static void yield(cpu_thread& thread) + // Returns true and success, false if did nothing + static bool yield(cpu_thread& thread) { vm::temporary_unlock(thread); - awake(&thread, yield_cmd); + return awake(&thread, yield_cmd); } static void set_priority(cpu_thread& thread, s32 prio)