GS: Use semaphores with a fast userspace path

This commit is contained in:
TellowKrinkle 2022-11-27 15:06:41 -06:00 committed by lightningterror
parent ab7105ffa0
commit faf750a544
3 changed files with 35 additions and 4 deletions

View File

@ -230,4 +230,35 @@ namespace Threading
/// Should be called by the worker thread if it restarts after dying
void Reset();
};
/// A semaphore that definitely has a fast userspace path
class UserspaceSemaphore
{
KernelSemaphore m_sema;
std::atomic<uint32_t> m_counter{0};
public:
UserspaceSemaphore() = default;
~UserspaceSemaphore() = default;
void Post()
{
if (m_counter.fetch_add(1, std::memory_order_release) < 0)
m_sema.Post();
}
void Wait()
{
if (m_counter.fetch_sub(1, std::memory_order_acquire) <= 0)
m_sema.Wait();
}
bool TryWait()
{
int32_t counter = m_counter.load(std::memory_order_relaxed);
while (counter > 0 && !m_counter.compare_exchange_weak(counter, counter - 1, std::memory_order_acquire, std::memory_order_relaxed))
;
return counter > 0;
}
};
} // namespace Threading

View File

@ -342,8 +342,8 @@ public:
std::mutex m_mtx_RingBufferBusy2; // Gets released on semaXGkick waiting...
std::mutex m_mtx_WaitGS;
Threading::WorkSema m_sem_event;
Threading::KernelSemaphore m_sem_OnRingReset;
Threading::KernelSemaphore m_sem_Vsync;
Threading::UserspaceSemaphore m_sem_OnRingReset;
Threading::UserspaceSemaphore 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)
@ -369,7 +369,7 @@ public:
std::atomic_bool m_open_flag{false};
std::atomic_bool m_shutdown_flag{false};
std::atomic_bool m_run_idle_flag{false};
Threading::KernelSemaphore m_open_or_close_done;
Threading::UserspaceSemaphore m_open_or_close_done;
public:
SysMtgsThread();

View File

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