From faf750a5449a3497891d6fdacb1534ead455d3a6 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Sun, 27 Nov 2022 15:06:41 -0600 Subject: [PATCH] GS: Use semaphores with a fast userspace path --- common/Threading.h | 31 +++++++++++++++++++++++++++++++ pcsx2/GS.h | 6 +++--- pcsx2/MTVU.h | 2 +- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/common/Threading.h b/common/Threading.h index 83bdc55621..908e41d023 100644 --- a/common/Threading.h +++ b/common/Threading.h @@ -230,4 +230,35 @@ namespace Threading /// Should be called by the worker thread if it restarts after dying void Reset(); }; + + /// A semaphore that definitely has a fast userspace path + class UserspaceSemaphore + { + KernelSemaphore m_sema; + std::atomic m_counter{0}; + + public: + UserspaceSemaphore() = default; + ~UserspaceSemaphore() = default; + + void Post() + { + if (m_counter.fetch_add(1, std::memory_order_release) < 0) + m_sema.Post(); + } + + void Wait() + { + if (m_counter.fetch_sub(1, std::memory_order_acquire) <= 0) + m_sema.Wait(); + } + + bool TryWait() + { + int32_t counter = m_counter.load(std::memory_order_relaxed); + while (counter > 0 && !m_counter.compare_exchange_weak(counter, counter - 1, std::memory_order_acquire, std::memory_order_relaxed)) + ; + return counter > 0; + } + }; } // namespace Threading diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 8b3d2da28d..68d589483e 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -342,8 +342,8 @@ public: std::mutex m_mtx_RingBufferBusy2; // Gets released on semaXGkick waiting... std::mutex m_mtx_WaitGS; Threading::WorkSema m_sem_event; - Threading::KernelSemaphore m_sem_OnRingReset; - Threading::KernelSemaphore m_sem_Vsync; + Threading::UserspaceSemaphore m_sem_OnRingReset; + Threading::UserspaceSemaphore m_sem_Vsync; // used to keep multiple threads from sending packets to the ringbuffer concurrently. // (currently not used or implemented -- is a planned feature for a future threaded VU1) @@ -369,7 +369,7 @@ public: std::atomic_bool m_open_flag{false}; std::atomic_bool m_shutdown_flag{false}; std::atomic_bool m_run_idle_flag{false}; - Threading::KernelSemaphore m_open_or_close_done; + Threading::UserspaceSemaphore m_open_or_close_done; public: SysMtgsThread(); diff --git a/pcsx2/MTVU.h b/pcsx2/MTVU.h index f48e33c131..b77d9af709 100644 --- a/pcsx2/MTVU.h +++ b/pcsx2/MTVU.h @@ -45,7 +45,7 @@ class VU_Thread final { public: alignas(16) vifStruct vif; alignas(16) VIFregisters vifRegs; - Threading::KernelSemaphore semaXGkick; + Threading::UserspaceSemaphore semaXGkick; std::atomic vuCycles[4]; // Used for VU cycle stealing hack u32 vuCycleIdx; // Used for VU cycle stealing hack u32 vuFBRST;