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() void Threading::KernelSemaphore::Wait()
{ {
pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Use WaitWithYield.");
MACH_CHECK(semaphore_wait(m_sema)); 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 /// Wait up to the given time
/// Returns true if successful, false if timed out /// Returns true if successful, false if timed out
static bool WaitUpTo(semaphore_t sema, wxTimeSpan wxtime) static bool WaitUpTo(semaphore_t sema, wxTimeSpan wxtime)
@ -92,25 +101,6 @@ static bool WaitUpTo(semaphore_t sema, wxTimeSpan wxtime)
return true; 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() Threading::Semaphore::Semaphore()
{ {
// other platforms explicitly make a thread-private (unshared) semaphore // other platforms explicitly make a thread-private (unshared) semaphore

View File

@ -84,7 +84,7 @@ bool Threading::WorkSema::WaitForEmpty()
break; break;
} }
pxAssertDev(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)"); 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)); 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); value = m_state.load(std::memory_order_acquire);
} }
pxAssertDev(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)"); 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)); return !IsDead(m_state.load(std::memory_order_relaxed));
} }
@ -149,40 +149,19 @@ void Threading::KernelSemaphore::Post()
void Threading::KernelSemaphore::Wait() void Threading::KernelSemaphore::Wait()
{ {
pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Use WaitWithYield.");
#ifdef _WIN32 #ifdef _WIN32
pthreadCancelableWait(m_sema); WaitForSingleObject(m_sema, INFINITE);
#else #else
sem_wait(&m_sema); sem_wait(&m_sema);
#endif #endif
} }
void Threading::KernelSemaphore::WaitWithYield() bool Threading::KernelSemaphore::TryWait()
{ {
#if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL))
{
Wait();
}
else
{
#ifdef _WIN32 #ifdef _WIN32
u64 millis = def_yieldgui_interval.GetMilliseconds().GetValue(); return WaitForSingleObject(m_sema, 0) == WAIT_OBJECT_0;
while (pthreadCancelableTimedWait(m_sema, millis) == ETIMEDOUT)
YieldToMain();
#else #else
while (true) return sem_trywait(&m_sema) == 0;
{
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();
#endif #endif
} }

View File

@ -295,7 +295,7 @@ namespace Threading
~KernelSemaphore(); ~KernelSemaphore();
void Post(); void Post();
void Wait(); void Wait();
void WaitWithYield(); bool TryWait();
}; };
/// A semaphore for notifying a work-processing thread of new work in a (separate) queue /// 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_RingBufferBusy2; // Gets released on semaXGkick waiting...
Threading::Mutex m_mtx_WaitGS; Threading::Mutex m_mtx_WaitGS;
Threading::WorkSema m_sem_event; Threading::WorkSema m_sem_event;
Threading::Semaphore m_sem_OnRingReset; Threading::KernelSemaphore m_sem_OnRingReset;
Threading::Semaphore m_sem_Vsync; Threading::KernelSemaphore m_sem_Vsync;
// used to keep multiple threads from sending packets to the ringbuffer concurrently. // 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) // (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); 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() ); //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) void SysMtgsThread::InitAndReadFIFO(u8* mem, u32 qwc)
@ -415,7 +415,7 @@ void SysMtgsThread::MainLoop()
{ {
mtvu_lock.Release(); mtvu_lock.Release();
// Wait for MTVU to complete vu1 program // Wait for MTVU to complete vu1 program
vu1Thread.semaXGkick.WaitWithoutYield(); vu1Thread.semaXGkick.Wait();
mtvu_lock.Acquire(); mtvu_lock.Acquire();
} }
Gif_Path& path = gifUnit.gifPath[GIF_PATH_1]; 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); m_SignalRingEnable.store(true, std::memory_order_release);
SetEvent(); SetEvent();
m_sem_OnRingReset.WaitWithoutYield(); m_sem_OnRingReset.Wait();
readpos = m_ReadPos.load(std::memory_order_acquire); readpos = m_ReadPos.load(std::memory_order_acquire);
//Console.WriteLn( Color_Blue, "(EEcore Awake) Report!\tringpos=0x%06x", readpos ); //Console.WriteLn( Color_Blue, "(EEcore Awake) Report!\tringpos=0x%06x", readpos );

View File

@ -46,7 +46,7 @@ class VU_Thread final {
public: public:
alignas(16) vifStruct vif; alignas(16) vifStruct vif;
alignas(16) VIFregisters vifRegs; alignas(16) VIFregisters vifRegs;
Threading::Semaphore semaXGkick; Threading::KernelSemaphore semaXGkick;
std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
u32 vuCycleIdx; // Used for VU cycle stealing hack u32 vuCycleIdx; // Used for VU cycle stealing hack
u32 vuFBRST; u32 vuFBRST;

View File

@ -54,7 +54,7 @@ extern DECI2_DBGP_BRK ebrk[32], ibrk[32];
extern s32 ebrk_count, ibrk_count; extern s32 ebrk_count, ibrk_count;
extern s32 runCode, runCount; extern s32 runCode, runCount;
extern Threading::Semaphore* runEvent; extern Threading::KernelSemaphore* runEvent;
extern s32 connected; extern s32 connected;
//when add linux code this might change //when add linux code this might change