diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 6e2d85e6fe..fd2cc4b631 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -1330,7 +1330,6 @@ static u32 spu_rdch(spu_thread* _spu, u32 ch) if (result < 0 || _spu->state & cpu_flag::again) { - _spu->state += cpu_flag::again; spu_runtime::g_escape(_spu); } @@ -2269,7 +2268,6 @@ static void spu_wrch_mfc(spu_thread* _spu) { if (!_spu->process_mfc_cmd() || _spu->state & cpu_flag::again) { - _spu->state += cpu_flag::again; spu_runtime::g_escape(_spu); } diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 5e7f614405..0dc71757c4 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -5588,7 +5588,6 @@ public: if (result < 0 || _spu->state & cpu_flag::again) { - _spu->state += cpu_flag::again; spu_runtime::g_escape(_spu); } @@ -5882,7 +5881,6 @@ public: { if (!_spu->set_ch_value(ch, value) || _spu->state & cpu_flag::again) { - _spu->state += cpu_flag::again; spu_runtime::g_escape(_spu); } @@ -5906,7 +5904,6 @@ public: { if (!_spu->process_mfc_cmd() || _spu->state & cpu_flag::again) { - _spu->state += cpu_flag::again; spu_runtime::g_escape(_spu); } diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 45839b032d..d9d6619b56 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -235,21 +235,17 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) std::vector events; + std::unique_lock qlock; + const auto queue = idm::withdraw(equeue_id, [&](lv2_event_queue& queue) -> CellError { - std::lock_guard lock(queue.mutex); + qlock.lock(queue.mutex); if (!mode && !queue.sq.empty()) { return CELL_EBUSY; } - if (queue.sq.empty()) - { - // Optimization - mode = 0; - } - if (!queue.events.empty()) { // Copy events for logging, does not empty @@ -257,6 +253,23 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) } lv2_obj::on_id_destroy(queue, queue.key); + + if (queue.sq.empty()) + { + qlock.unlock(); + } + else + { + for (auto cpu : queue.sq) + { + if (cpu->state & cpu_flag::again) + { + ppu.state += cpu_flag::again; + return CELL_EAGAIN; + } + } + } + return {}; }); @@ -265,6 +278,11 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return CELL_ESRCH; } + if (ppu.state & cpu_flag::again) + { + return {}; + } + if (queue.ret) { return queue.ret; @@ -272,12 +290,10 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) std::string lost_data; - if (mode == SYS_EVENT_QUEUE_DESTROY_FORCE) + if (qlock.owns_lock()) { std::deque sq; - std::lock_guard lock(queue->mutex); - sq = std::move(queue->sq); if (sys_event.warning) @@ -309,6 +325,8 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) resume_spu_thread_group_from_waiting(static_cast(*cpu)); } } + + qlock.unlock(); } if (sys_event.warning)