Utilities: Add TryWait and spin waits to semaphore and mutex

This commit is contained in:
TellowKrinkle 2021-03-28 03:09:52 -05:00 committed by Kojin
parent 5ff89dd695
commit 881b017606
4 changed files with 47 additions and 0 deletions

View File

@ -226,6 +226,14 @@ bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
#endif #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 // 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 // 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 // the stack and passed to another thread via GUI message or such, avoiding complications where

View File

@ -262,6 +262,24 @@ void Threading::Mutex::Wait()
Release(); 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() void Threading::Mutex::WaitWithoutYield()
{ {
AcquireWithoutYield(); AcquireWithoutYield();

View File

@ -165,6 +165,11 @@ void Threading::Semaphore::WaitNoCancel(const wxTimeSpan& timeout)
pthread_setcancelstate(oldstate, NULL); pthread_setcancelstate(oldstate, NULL);
} }
bool Threading::Semaphore::TryWait()
{
return sem_trywait(&m_sema) == 0;
}
int Threading::Semaphore::Count() int Threading::Semaphore::Count()
{ {
int retval; int retval;

View File

@ -28,6 +28,7 @@
#endif #endif
#include "common/Pcsx2Defs.h" #include "common/Pcsx2Defs.h"
#include "common/TraceLog.h" #include "common/TraceLog.h"
#include "common/General.h"
#undef Yield // release the burden of windows.h global namespace spam. #undef Yield // release the burden of windows.h global namespace spam.
@ -256,6 +257,20 @@ namespace Threading
bool WaitWithoutYield(const wxTimeSpan& timeout); bool WaitWithoutYield(const wxTimeSpan& timeout);
void WaitNoCancel(); void WaitNoCancel();
void WaitNoCancel(const wxTimeSpan& timeout); 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(); int Count();
void Wait(); void Wait();
@ -285,6 +300,7 @@ namespace Threading
bool AcquireWithoutYield(const wxTimeSpan& timeout); bool AcquireWithoutYield(const wxTimeSpan& timeout);
void Wait(); void Wait();
void WaitWithSpin();
bool Wait(const wxTimeSpan& timeout); bool Wait(const wxTimeSpan& timeout);
void WaitWithoutYield(); void WaitWithoutYield();
bool WaitWithoutYield(const wxTimeSpan& timeout); bool WaitWithoutYield(const wxTimeSpan& timeout);