From 096696bed7a654f6f746ff57ae8155e73364d2be Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 5 May 2022 23:01:12 +1000 Subject: [PATCH] Misc: Replace core usage of Semaphore with KernelSemaphore i.e. decouple it from the UI. --- common/Darwin/DarwinSemaphore.cpp | 30 ++++++++++------------------ common/Semaphore.cpp | 33 ++++++------------------------- common/Threading.h | 2 +- pcsx2/GS.h | 4 ++-- pcsx2/MTGS.cpp | 6 +++--- pcsx2/MTVU.h | 2 +- pcsx2/RDebug/deci2.h | 2 +- 7 files changed, 24 insertions(+), 55 deletions(-) diff --git a/common/Darwin/DarwinSemaphore.cpp b/common/Darwin/DarwinSemaphore.cpp index 8b65bd8193..dd5d5d203f 100644 --- a/common/Darwin/DarwinSemaphore.cpp +++ b/common/Darwin/DarwinSemaphore.cpp @@ -73,10 +73,19 @@ void Threading::KernelSemaphore::Post() void Threading::KernelSemaphore::Wait() { - pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Use WaitWithYield."); MACH_CHECK(semaphore_wait(m_sema)); } +bool Threading::KernelSemaphore::TryWait() +{ + mach_timespec_t time = {}; + kern_return_t res = semaphore_timedwait(m_sema, time); + if (res == KERN_OPERATION_TIMED_OUT) + return false; + MACH_CHECK(res); + return true; +} + /// Wait up to the given time /// Returns true if successful, false if timed out static bool WaitUpTo(semaphore_t sema, wxTimeSpan wxtime) @@ -92,25 +101,6 @@ static bool WaitUpTo(semaphore_t sema, wxTimeSpan wxtime) return true; } -void Threading::KernelSemaphore::WaitWithYield() -{ -#if wxUSE_GUI - if (!wxThread::IsMain() || (wxTheApp == NULL)) - { - Wait(); - } - else - { - while (!WaitUpTo(m_sema, def_yieldgui_interval)) - { - YieldToMain(); - } - } -#else - WaitWithoutYield(); -#endif -} - Threading::Semaphore::Semaphore() { // other platforms explicitly make a thread-private (unshared) semaphore diff --git a/common/Semaphore.cpp b/common/Semaphore.cpp index 6246d696d1..a7bbfb7e22 100644 --- a/common/Semaphore.cpp +++ b/common/Semaphore.cpp @@ -84,7 +84,7 @@ bool Threading::WorkSema::WaitForEmpty() break; } pxAssertDev(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)"); - m_empty_sema.WaitWithYield(); + m_empty_sema.Wait(); return !IsDead(m_state.load(std::memory_order_relaxed)); } @@ -102,7 +102,7 @@ bool Threading::WorkSema::WaitForEmptyWithSpin() value = m_state.load(std::memory_order_acquire); } pxAssertDev(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)"); - m_empty_sema.WaitWithYield(); + m_empty_sema.Wait(); return !IsDead(m_state.load(std::memory_order_relaxed)); } @@ -149,40 +149,19 @@ void Threading::KernelSemaphore::Post() void Threading::KernelSemaphore::Wait() { - pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Use WaitWithYield."); #ifdef _WIN32 - pthreadCancelableWait(m_sema); + WaitForSingleObject(m_sema, INFINITE); #else sem_wait(&m_sema); #endif } -void Threading::KernelSemaphore::WaitWithYield() +bool Threading::KernelSemaphore::TryWait() { -#if wxUSE_GUI - if (!wxThread::IsMain() || (wxTheApp == NULL)) - { - Wait(); - } - else - { #ifdef _WIN32 - u64 millis = def_yieldgui_interval.GetMilliseconds().GetValue(); - while (pthreadCancelableTimedWait(m_sema, millis) == ETIMEDOUT) - YieldToMain(); + return WaitForSingleObject(m_sema, 0) == WAIT_OBJECT_0; #else - while (true) - { - wxDateTime megafail(wxDateTime::UNow() + def_yieldgui_interval); - const timespec fail = {megafail.GetTicks(), megafail.GetMillisecond() * 1000000}; - if (sem_timedwait(&m_sema, &fail) == 0) - break; - YieldToMain(); - } -#endif - } -#else - Wait(); + return sem_trywait(&m_sema) == 0; #endif } diff --git a/common/Threading.h b/common/Threading.h index 9c3b90b23c..3df9b4db21 100644 --- a/common/Threading.h +++ b/common/Threading.h @@ -295,7 +295,7 @@ namespace Threading ~KernelSemaphore(); void Post(); void Wait(); - void WaitWithYield(); + bool TryWait(); }; /// A semaphore for notifying a work-processing thread of new work in a (separate) queue diff --git a/pcsx2/GS.h b/pcsx2/GS.h index caecb7143b..8413789038 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -336,8 +336,8 @@ public: Threading::Mutex m_mtx_RingBufferBusy2; // Gets released on semaXGkick waiting... Threading::Mutex m_mtx_WaitGS; Threading::WorkSema m_sem_event; - Threading::Semaphore m_sem_OnRingReset; - Threading::Semaphore m_sem_Vsync; + Threading::KernelSemaphore m_sem_OnRingReset; + Threading::KernelSemaphore 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) diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 1675d9ac63..8b2832336a 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -229,7 +229,7 @@ void SysMtgsThread::PostVsyncStart(bool registers_written) m_VsyncSignalListener.store(true, std::memory_order_release); //Console.WriteLn( Color_Blue, "(EEcore Sleep) Vsync\t\tringpos=0x%06x, writepos=0x%06x", m_ReadPos.load(), m_WritePos.load() ); - m_sem_Vsync.WaitNoCancel(); + m_sem_Vsync.Wait(); } void SysMtgsThread::InitAndReadFIFO(u8* mem, u32 qwc) @@ -415,7 +415,7 @@ void SysMtgsThread::MainLoop() { mtvu_lock.Release(); // Wait for MTVU to complete vu1 program - vu1Thread.semaXGkick.WaitWithoutYield(); + vu1Thread.semaXGkick.Wait(); mtvu_lock.Acquire(); } Gif_Path& path = gifUnit.gifPath[GIF_PATH_1]; @@ -722,7 +722,7 @@ void SysMtgsThread::GenericStall(uint size) { m_SignalRingEnable.store(true, std::memory_order_release); SetEvent(); - m_sem_OnRingReset.WaitWithoutYield(); + m_sem_OnRingReset.Wait(); readpos = m_ReadPos.load(std::memory_order_acquire); //Console.WriteLn( Color_Blue, "(EEcore Awake) Report!\tringpos=0x%06x", readpos ); diff --git a/pcsx2/MTVU.h b/pcsx2/MTVU.h index 45f25961f5..7ac23bd58f 100644 --- a/pcsx2/MTVU.h +++ b/pcsx2/MTVU.h @@ -46,7 +46,7 @@ class VU_Thread final { public: alignas(16) vifStruct vif; alignas(16) VIFregisters vifRegs; - Threading::Semaphore semaXGkick; + Threading::KernelSemaphore semaXGkick; std::atomic vuCycles[4]; // Used for VU cycle stealing hack u32 vuCycleIdx; // Used for VU cycle stealing hack u32 vuFBRST; diff --git a/pcsx2/RDebug/deci2.h b/pcsx2/RDebug/deci2.h index dfcef220bd..7adbfdb776 100644 --- a/pcsx2/RDebug/deci2.h +++ b/pcsx2/RDebug/deci2.h @@ -54,7 +54,7 @@ extern DECI2_DBGP_BRK ebrk[32], ibrk[32]; extern s32 ebrk_count, ibrk_count; extern s32 runCode, runCount; -extern Threading::Semaphore* runEvent; +extern Threading::KernelSemaphore* runEvent; extern s32 connected; //when add linux code this might change