diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 4db17d05ba..64e164e417 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2346,7 +2346,7 @@ bool spu_thread::process_mfc_cmd() ch_mfc_cmd.cmd, ch_mfc_cmd.lsa, ch_mfc_cmd.eal, ch_mfc_cmd.tag, ch_mfc_cmd.size); } -u32 spu_thread::get_events(u32 mask_hint) +u32 spu_thread::get_events(u32 mask_hint, bool waiting) { const u32 mask1 = ch_event_mask; @@ -2378,7 +2378,17 @@ u32 spu_thread::get_events(u32 mask_hint) } // Simple polling or polling with atomically set/removed SPU_EVENT_WAITING flag - return ch_event_stat & mask1; + return !waiting ? ch_event_stat & mask1 : ch_event_stat.atomic_op([&](u32& stat) -> u32 + { + if (u32 res = stat & mask1) + { + stat &= ~SPU_EVENT_WAITING; + return res; + } + + stat |= SPU_EVENT_WAITING; + return 0; + }); } void spu_thread::set_events(u32 mask) @@ -2608,7 +2618,7 @@ s64 spu_thread::get_ch_value(u32 ch) return res; } - while (res = get_events(mask1), !res) + while (res = get_events(mask1, true), !res) { state += cpu_flag::wait; diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 8d4b227ee1..2cbc11301c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -299,7 +299,7 @@ public: // Waiting for channel push state availability, actually pushing if specified bool push_wait(cpu_thread& spu, u32 value, bool push = true) { - while (true) + while (true) { u64 state; data.fetch_op([&](u64& data) @@ -716,7 +716,7 @@ public: atomic_t last_exit_status; // Value to be written in exit_status after checking group termination const u32 index; // SPU index - const std::add_pointer_t ls; // SPU LS pointer + const std::add_pointer_t ls; // SPU LS pointer const spu_type thread_type; private: const u32 offset; // SPU LS offset @@ -750,7 +750,7 @@ public: u32 get_mfc_completed(); bool process_mfc_cmd(); - u32 get_events(u32 mask_hint = -1); + u32 get_events(u32 mask_hint = -1, bool waiting = false); void set_events(u32 mask); void set_interrupt_status(bool enable); bool check_mfc_interrupts(u32 nex_pc);