From f5c575961fe9f7ba3ab3e3f87cb2b66ef27bfdbb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 17 Oct 2020 14:30:24 +0300 Subject: [PATCH] Implement priorities for cpu_thread::suspend_all tasks Give PUTLLUC increased priority. --- rpcs3/Emu/CPU/CPUThread.cpp | 19 +++++++++++++++++-- rpcs3/Emu/CPU/CPUThread.h | 9 ++++++--- rpcs3/Emu/Cell/SPUThread.cpp | 3 ++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 4d12fd1f5b..5e3f11415f 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -811,6 +811,9 @@ void cpu_thread::suspend_work::push(cpu_thread* _this) noexcept // Extract queue and reverse element order (FILO to FIFO) (TODO: maybe leave order as is?) auto* head = queue.exchange(nullptr); + s8 min_prio = head->prio; + s8 max_prio = head->prio; + if (auto* prev = head->next) { head->next = nullptr; @@ -821,14 +824,26 @@ void cpu_thread::suspend_work::push(cpu_thread* _this) noexcept prev->next = head; head = std::exchange(prev, pre2); + + // Fill priority range + min_prio = std::min(min_prio, head->prio); + max_prio = std::max(max_prio, head->prio); } while (prev); } // Execute all stored workload - for (; head; head = head->next) + for (s32 prio = max_prio; prio >= min_prio; prio--) { - head->exec(head->func_ptr, head->res_buf); + // ... according to priorities + for (auto work = head; work; work = work->next) + { + // Properly sorting single-linked list may require to optimize the loop + if (work->prio == prio) + { + work->exec(work->func_ptr, work->res_buf); + } + } } // Finalization diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 600c88ebd6..04cf307c9c 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -123,6 +123,9 @@ public: // For internal use struct suspend_work { + // Task priority + s8 prio; + void* func_ptr; void* res_buf; @@ -137,12 +140,12 @@ public: }; // Suspend all threads and execute op (may be executed by other thread than caller!) - template + template static auto suspend_all(cpu_thread* _this, F op) { if constexpr (std::is_void_v>) { - suspend_work work{&op, nullptr, [](void* func, void*) + suspend_work work{Prio, &op, nullptr, [](void* func, void*) { std::invoke(*static_cast(func)); }}; @@ -154,7 +157,7 @@ public: { std::invoke_result_t result; - suspend_work work{&op, &result, [](void* func, void* res_buf) + suspend_work work{Prio, &op, &result, [](void* func, void* res_buf) { *static_cast*>(res_buf) = std::invoke(*static_cast(func)); }}; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index d65c5cebc2..b6e8db1a19 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2200,7 +2200,8 @@ void do_cell_atomic_128_store(u32 addr, const void* to_write) if (result == 0) { - cpu_thread::suspend_all(cpu, [&] + // Execute with increased priority + cpu_thread::suspend_all<+1>(cpu, [&] { mov_rdata(vm::_ref(addr), *static_cast(to_write)); vm::reservation_acquire(addr, 128) += 127;