From 56471f4ad407a1d5d508ffe7fb5a3e3f56b52c8a Mon Sep 17 00:00:00 2001 From: Eladash Date: Fri, 14 May 2021 14:21:10 +0300 Subject: [PATCH] SPU: Optimize SPU ports/queues --- rpcs3/Emu/Cell/SPUThread.cpp | 28 ++++++++++++---------------- rpcs3/Emu/Cell/SPUThread.h | 4 ++-- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 17 +++++++---------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 1ca194e657..21f8b1ac7f 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -3969,7 +3969,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value) std::lock_guard lock(group->mutex); - const auto queue = this->spup[spup].lock(); + const auto queue = this->spup[spup].get(); const auto res = ch_in_mbox.get_count() ? CELL_EBUSY : !queue ? CELL_ENOTCONN : @@ -4001,7 +4001,7 @@ bool spu_thread::set_ch_value(u32 ch, u32 value) spu_log.trace("sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data); - const auto queue = (std::lock_guard{group->mutex}, this->spup[spup].lock()); + const auto queue = (std::lock_guard{group->mutex}, this->spup[spup]); // TODO: check passing spup value if (auto res = queue ? queue->send(SYS_SPU_THREAD_EVENT_USER_KEY, lv2_id, (u64{spup} << 32) | (value & 0x00ffffff), data) : CELL_ENOTCONN) @@ -4339,16 +4339,12 @@ bool spu_thread::stop_and_signal(u32 code) return ch_in_mbox.set_values(1, CELL_EINVAL), true; } - std::shared_ptr queue; - state += cpu_flag::wait; spu_function_logger logger(*this, "sys_spu_thread_receive_event"); while (true) { - queue.reset(); - // Check group status, wait if necessary for (auto _state = +group->run_state; _state >= SPU_THREAD_GROUP_STATUS_WAITING && _state <= SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED; @@ -4364,8 +4360,6 @@ bool spu_thread::stop_and_signal(u32 code) thread_ctrl::wait_on(state, old);; } - reader_lock rlock(id_manager::g_mutex); - std::lock_guard lock(group->mutex); if (is_stopped()) @@ -4379,20 +4373,21 @@ bool spu_thread::stop_and_signal(u32 code) continue; } + lv2_event_queue* queue = nullptr; + for (auto& v : this->spuq) { if (spuq == v.first) { - queue = v.second.lock(); - - if (lv2_event_queue::check(queue)) + if (lv2_event_queue::check(v.second)) { + queue = v.second.get(); break; } } } - if (!lv2_event_queue::check(queue)) + if (!queue) { return ch_in_mbox.set_values(1, CELL_EINVAL), true; } @@ -4447,7 +4442,7 @@ bool spu_thread::stop_and_signal(u32 code) break; } - thread_ctrl::wait_on(state, old);; + thread_ctrl::wait_on(state, old); } std::lock_guard lock(group->mutex); @@ -4498,20 +4493,21 @@ bool spu_thread::stop_and_signal(u32 code) std::lock_guard lock(group->mutex); - std::shared_ptr queue; + lv2_event_queue* queue = nullptr; for (auto& v : this->spuq) { if (spuq == v.first) { - if (queue = v.second.lock(); lv2_event_queue::check(queue)) + if (lv2_event_queue::check(v.second)) { + queue = v.second.get(); break; } } } - if (!lv2_event_queue::check(queue)) + if (!queue) { return ch_in_mbox.set_values(1, CELL_EINVAL), true; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 982619baae..d8924207fa 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -736,8 +736,8 @@ public: atomic_t status_npc; std::array int_ctrl; // SPU Class 0, 1, 2 Interrupt Management - std::array>, 32> spuq; // Event Queue Keys for SPU Thread - std::weak_ptr spup[64]; // SPU Ports + std::array>, 32> spuq; // Event Queue Keys for SPU Thread + std::shared_ptr spup[64]; // SPU Ports spu_channel exit_status{}; // Threaded SPU exit status (not a channel, but the interface fits) atomic_t last_exit_status; // Value to be written in exit_status after checking group termination diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index 11f7e45cc9..b604ded9c9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -1490,7 +1490,7 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et, sys_spu.warning("sys_spu_thread_connect_event(id=0x%x, eq=0x%x, et=%d, spup=%d)", id, eq, et, spup); const auto [thread, group] = lv2_spu_group::get_thread(id); - const auto queue = idm::get(eq); + auto queue = idm::get(eq); if (!queue || !thread) [[unlikely]] { @@ -1512,7 +1512,7 @@ error_code sys_spu_thread_connect_event(ppu_thread& ppu, u32 id, u32 eq, u32 et, return CELL_EISCONN; } - port = queue; + port = std::move(queue); return CELL_OK; } @@ -1557,7 +1557,7 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq sys_spu.warning("sys_spu_thread_bind_queue(id=0x%x, spuq=0x%x, spuq_num=0x%x)", id, spuq, spuq_num); const auto [thread, group] = lv2_spu_group::get_thread(id); - const auto queue = idm::get(spuq); + auto queue = idm::get(spuq); if (!queue || !thread) [[unlikely]] { @@ -1576,8 +1576,7 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq for (auto& v : thread->spuq) { // Check if the entry is assigned at all - if (const decltype(v.second) test{}; - !v.second.owner_before(test) && !test.owner_before(v.second)) + if (!v.second) { if (!q) { @@ -1587,8 +1586,7 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq continue; } - if (v.first == spuq_num || - (!v.second.owner_before(queue) && !queue.owner_before(v.second))) + if (v.first == spuq_num || v.second == queue) { return CELL_EBUSY; } @@ -1600,7 +1598,7 @@ error_code sys_spu_thread_bind_queue(ppu_thread& ppu, u32 id, u32 spuq, u32 spuq } q->first = spuq_num; - q->second = queue; + q->second = std::move(queue); return CELL_OK; } @@ -1626,8 +1624,7 @@ error_code sys_spu_thread_unbind_queue(ppu_thread& ppu, u32 id, u32 spuq_num) continue; } - if (const decltype(v.second) test{}; - !v.second.owner_before(test) && !test.owner_before(v.second)) + if (!v.second) { continue; }