Misc: Replace core usage of Semaphore with KernelSemaphore

i.e. decouple it from the UI.
This commit is contained in:
Connor McLaughlin 2022-05-05 23:01:12 +10:00 committed by refractionpcsx2
parent 756cd1ee47
commit 096696bed7
7 changed files with 24 additions and 55 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
u32 vuCycleIdx; // Used for VU cycle stealing hack
u32 vuFBRST;

View File

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