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
}
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

View File

@ -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();

View File

@ -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;

View File

@ -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);