From d0126f0fa044f653bede0b66a25abc162aaff94e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 1 Feb 2021 14:46:10 +0300 Subject: [PATCH] Fix freezes in HLE Vdec and SPU LLVM precompilation. Freezes could accidentally occur on close or ingame. Deprecate range-for loop on lf_queue. This is a part of PR #9208 Co-authored-by: Eladash --- Utilities/lockless.h | 58 ----------------------------- rpcs3/Emu/Cell/Modules/cellVdec.cpp | 23 +++++++++++- rpcs3/Emu/Cell/SPURecompiler.cpp | 21 ++++++++++- 3 files changed, 41 insertions(+), 61 deletions(-) diff --git a/Utilities/lockless.h b/Utilities/lockless.h index 0254816887..350b6f4b59 100644 --- a/Utilities/lockless.h +++ b/Utilities/lockless.h @@ -365,64 +365,6 @@ public: return count; } - - // Iterator that enables direct endless range-for loop: for (auto* ptr : queue) ... - class iterator - { - lf_queue* _this = nullptr; - - lf_queue_slice m_data; - - public: - constexpr iterator() = default; - - explicit iterator(lf_queue* _this) - : _this(_this) - { - m_data = _this->pop_all(); - } - - bool operator !=(const iterator& rhs) const - { - return _this != rhs._this; - } - - T* operator *() const - { - return m_data ? m_data.get() : nullptr; - } - - iterator& operator ++() - { - if (m_data) - { - m_data.pop_front(); - } - - if (!m_data) - { - m_data = _this->pop_all(); - - if (!m_data) - { - _this->wait(); - m_data = _this->pop_all(); - } - } - - return *this; - } - }; - - iterator begin() - { - return iterator{this}; - } - - iterator end() - { - return iterator{}; - } }; // Concurrent linked list, elements remain until destroyed. diff --git a/rpcs3/Emu/Cell/Modules/cellVdec.cpp b/rpcs3/Emu/Cell/Modules/cellVdec.cpp index 17db2d3ce2..45f954b391 100644 --- a/rpcs3/Emu/Cell/Modules/cellVdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVdec.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Emu/IdManager.h" +#include "Emu/perf_meter.hpp" #include "Emu/Cell/PPUModule.h" #include "Emu/Cell/lv2/sys_sync.h" #include "Emu/Cell/lv2/sys_ppu_thread.h" @@ -205,11 +206,29 @@ struct vdec_context final void exec(ppu_thread& ppu, u32 vid) { + perf_meter<"VDEC"_u32> perf0; + ppu_tid.release(ppu.id); - // pcmd can be nullptr - for (auto* pcmd : in_cmd) + for (auto slice = in_cmd.pop_all();; [&] { + if (slice) + { + slice.pop_front(); + } + + if (slice || thread_ctrl::state() == thread_state::aborting) + { + return; + } + + thread_ctrl::wait_on(in_cmd, nullptr); + slice = in_cmd.pop_all(); // Pop new command list + }()) + { + // pcmd can be nullptr + auto* pcmd = slice.get(); + if (thread_ctrl::state() == thread_state::aborting) { break; diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index a9d4163208..0f46e7126e 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -4,6 +4,7 @@ #include "Emu/System.h" #include "Emu/system_config.h" #include "Emu/IdManager.h" +#include "Emu/perf_meter.hpp" #include "Crypto/sha1.h" #include "Utilities/StrUtil.h" #include "Utilities/JIT.h" @@ -8894,6 +8895,8 @@ struct spu_llvm_worker void operator()() { + perf_meter<"SPUW"_u32> perf0; + // SPU LLVM Recompiler instance const auto compiler = spu_recompiler_base::make_llvm_recompiler(); compiler->init(); @@ -8901,8 +8904,24 @@ struct spu_llvm_worker // Fake LS std::vector> ls(0x10000); - for (auto* prog : registered) + for (auto slice = registered.pop_all();; [&] { + if (slice) + { + slice.pop_front(); + } + + if (slice || thread_ctrl::state() == thread_state::aborting) + { + return; + } + + thread_ctrl::wait_on(registered, nullptr); + slice = registered.pop_all(); + }()) + { + auto* prog = slice.get(); + if (thread_ctrl::state() == thread_state::aborting) { break;