From 620997c1937ffc69ad1e9404ac5cd5b150dca8c4 Mon Sep 17 00:00:00 2001 From: Elad <18193363+knight4u32@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:43:08 +0300 Subject: [PATCH] SPU/LV2: Notify SPU events after mutex guards' unlocking --- rpcs3/Emu/Cell/SPUThread.cpp | 6 ++--- rpcs3/Emu/Cell/lv2/sys_event.cpp | 38 +++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index bd474d8122..dbf3b695f4 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -6851,7 +6851,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value) fmt::throw_exception("Unknown/illegal channel in WRCH (ch=%d [%s], value=0x%x)", ch, ch < 128 ? spu_ch_name[ch] : "???", value); } -extern void resume_spu_thread_group_from_waiting(spu_thread& spu) +extern void resume_spu_thread_group_from_waiting(spu_thread& spu, std::array>, 8>& notify_spus) { const auto group = spu.group; @@ -6865,7 +6865,7 @@ extern void resume_spu_thread_group_from_waiting(spu_thread& spu) { group->run_state = SPU_THREAD_GROUP_STATUS_SUSPENDED; spu.state += cpu_flag::signal; - spu.state.notify_one(); + ensure(spu.state & cpu_flag::suspend); return; } @@ -6883,7 +6883,7 @@ extern void resume_spu_thread_group_from_waiting(spu_thread& spu) thread->state -= cpu_flag::suspend; } - thread->state.notify_one(); + notify_spus[thread->index] = thread; } } } diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index db72972b91..8b3de14bf7 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -117,7 +117,7 @@ shared_ptr lv2_event_queue::find(u64 ipc_key) return g_fxo->get>().get(ipc_key); } -extern void resume_spu_thread_group_from_waiting(spu_thread& spu); +extern void resume_spu_thread_group_from_waiting(spu_thread& spu, std::array>, 8>& notify_spus); CellError lv2_event_queue::send(lv2_event event, bool* notified_thread, lv2_event_port* port) { @@ -126,6 +126,22 @@ CellError lv2_event_queue::send(lv2_event event, bool* notified_thread, lv2_even *notified_thread = false; } + struct notify_spus_t + { + std::array>, 8> spus; + + ~notify_spus_t() noexcept + { + for (auto& spu : spus) + { + if (spu && spu->state & cpu_flag::wait) + { + spu->state.notify_one(); + } + } + } + } notify_spus{}; + std::lock_guard lock(mutex); if (!exists) @@ -199,7 +215,7 @@ CellError lv2_event_queue::send(lv2_event event, bool* notified_thread, lv2_even const u32 data2 = static_cast(std::get<2>(event)); const u32 data3 = static_cast(std::get<3>(event)); spu.ch_in_mbox.set_values(4, CELL_OK, data1, data2, data3); - resume_spu_thread_group_from_waiting(spu); + resume_spu_thread_group_from_waiting(spu, notify_spus.spus); } return {}; @@ -260,6 +276,22 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return CELL_EINVAL; } + struct notify_spus_t + { + std::array>, 8> spus; + + ~notify_spus_t() noexcept + { + for (auto& spu : spus) + { + if (spu && spu->state & cpu_flag::wait) + { + spu->state.notify_one(); + } + } + } + } notify_spus{}; + std::vector events; std::unique_lock qlock; @@ -357,7 +389,7 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) for (auto cpu = +queue->sq; cpu; cpu = cpu->next_cpu) { cpu->ch_in_mbox.set_values(1, CELL_ECANCELED); - resume_spu_thread_group_from_waiting(*cpu); + resume_spu_thread_group_from_waiting(*cpu, notify_spus.spus); } atomic_storage::release(queue->sq, nullptr);