From 9266507e4cbed7bfbf56fdbc107d46f54497bc79 Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 12 May 2020 19:17:50 +0300 Subject: [PATCH] SPU: Implement spu_channel_(4_)t::try_read --- rpcs3/Emu/Cell/SPUThread.cpp | 12 ++++++------ rpcs3/Emu/Cell/SPUThread.h | 34 +++++++++++++++++++++++++++++++++- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 6 +++--- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index f6c3e122cc..6a223535c1 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -995,8 +995,8 @@ void spu_thread::cpu_stop() if (thread && thread.get() != this && thread->status_npc.load().status >> 16 == SYS_SPU_THREAD_STOP_THREAD_EXIT) { // Wait for all threads to have error codes if exited by sys_spu_thread_exit - for (u64 status; ((status = thread->exit_status.data) & spu_channel::bit_count) == 0 - || static_cast(status) != thread->last_exit_status;) + for (u32 status; !thread->exit_status.try_read(status) + || status != thread->last_exit_status;) { _mm_pause(); } @@ -3288,11 +3288,11 @@ void fmt_class_string::format(std::string& out, u64 arg) { const auto& ch = get_object(arg); - const u64 raw = ch.data.load(); + u32 data = 0; - if (raw & spu_channel::bit_count) + if (ch.try_read(data)) { - fmt::append(out, "0x%08x", static_cast(raw)); + fmt::append(out, "0x%08x", data); } else { @@ -3305,7 +3305,7 @@ void fmt_class_string::format(std::string& out, u64 arg) { const auto& ch = get_object(arg); - // TODO + // TODO (use try_read) fmt::append(out, "count = %d", ch.get_count()); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 34767fde85..8de43c215d 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -233,6 +233,20 @@ public: return (old & bit_count) != 0; } + // Reading without modification + bool try_read(u32& out) const + { + const u64 old = data.load(); + + if (old & bit_count) [[likely]] + { + out = static_cast(old); + return true; + } + + return false; + } + // Pop unconditionally (loading last value), may require notification u32 pop(cpu_thread& spu) { @@ -269,6 +283,7 @@ struct spu_channel_4_t { u8 waiting; u8 count; + u8 _pad[2]; u32 value0; u32 value1; u32 value2; @@ -338,6 +353,23 @@ public: }); } + // returns current queue size without modification + uint try_read(u32 (&out)[4]) const + { + const sync_var_t data = values.load(); + const uint result = data.count; + + if (result != 0) + { + out[0] = data.value0; + out[1] = data.value1; + out[2] = data.value2; + out[3] = value3; + } + + return result; + } + u32 get_count() const { return std::as_const(values).raw().count; @@ -345,7 +377,7 @@ public: void set_values(u32 count, u32 value0, u32 value1 = 0, u32 value2 = 0, u32 value3 = 0) { - this->values.raw() = { 0, static_cast(count), value0, value1, value2 }; + this->values.raw() = { 0, static_cast(count), {}, value0, value1, value2 }; this->value3 = value3; } }; diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index 3aabe5012c..a9a24a0745 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -482,11 +482,11 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr return CELL_ESRCH; } - const u64 exit_status = thread->exit_status.data.load(); + u32 data; - if (exit_status & spu_channel::bit_count) + if (thread->exit_status.try_read(data)) { - *status = static_cast(exit_status); + *status = static_cast(data); return CELL_OK; }