diff --git a/common/Darwin/DarwinSemaphore.cpp b/common/Darwin/DarwinSemaphore.cpp index 4040690d6d..092debd229 100644 --- a/common/Darwin/DarwinSemaphore.cpp +++ b/common/Darwin/DarwinSemaphore.cpp @@ -226,6 +226,14 @@ bool Threading::Semaphore::Wait(const wxTimeSpan& timeout) #endif } +bool Threading::Semaphore::TryWait() +{ + int counter = __atomic_load_n(&m_counter, __ATOMIC_RELAXED); + while (counter > 0 && !__atomic_compare_exchange_n(&m_counter, &counter, counter - 1, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) + ; + return counter > 0; +} + // Performs an uncancellable wait on a semaphore; restoring the thread's previous cancel state // after the wait has completed. Useful for situations where the semaphore itself is stored on // the stack and passed to another thread via GUI message or such, avoiding complications where diff --git a/common/Mutex.cpp b/common/Mutex.cpp index b6e3c62cc0..76af8e3fd4 100644 --- a/common/Mutex.cpp +++ b/common/Mutex.cpp @@ -262,6 +262,24 @@ void Threading::Mutex::Wait() Release(); } +// Like wait but spins for a while before sleeping the thread +void Threading::Mutex::WaitWithSpin() +{ + u32 waited = 0; + while (true) + { + if (TryAcquire()) + { + Release(); + return; + } + if (waited >= SPIN_TIME_NS) + break; + waited += ShortSpin(); + } + Wait(); +} + void Threading::Mutex::WaitWithoutYield() { AcquireWithoutYield(); diff --git a/common/Semaphore.cpp b/common/Semaphore.cpp index 2e1a5d3bf0..929204076e 100644 --- a/common/Semaphore.cpp +++ b/common/Semaphore.cpp @@ -165,6 +165,11 @@ void Threading::Semaphore::WaitNoCancel(const wxTimeSpan& timeout) pthread_setcancelstate(oldstate, NULL); } +bool Threading::Semaphore::TryWait() +{ + return sem_trywait(&m_sema) == 0; +} + int Threading::Semaphore::Count() { int retval; diff --git a/common/Threading.h b/common/Threading.h index 1f188bb8a2..52ebf22eac 100644 --- a/common/Threading.h +++ b/common/Threading.h @@ -28,6 +28,7 @@ #endif #include "common/Pcsx2Defs.h" #include "common/TraceLog.h" +#include "common/General.h" #undef Yield // release the burden of windows.h global namespace spam. @@ -256,6 +257,20 @@ namespace Threading bool WaitWithoutYield(const wxTimeSpan& timeout); void WaitNoCancel(); void WaitNoCancel(const wxTimeSpan& timeout); + void WaitWithoutYieldWithSpin() + { + u32 waited = 0; + while (true) + { + if (TryWait()) + return; + if (waited >= SPIN_TIME_NS) + break; + waited += ShortSpin(); + } + WaitWithoutYield(); + } + bool TryWait(); int Count(); void Wait(); @@ -285,6 +300,7 @@ namespace Threading bool AcquireWithoutYield(const wxTimeSpan& timeout); void Wait(); + void WaitWithSpin(); bool Wait(const wxTimeSpan& timeout); void WaitWithoutYield(); bool WaitWithoutYield(const wxTimeSpan& timeout);