diff --git a/Utilities/SSemaphore.cpp b/Utilities/SSemaphore.cpp new file mode 100644 index 0000000000..91754b764f --- /dev/null +++ b/Utilities/SSemaphore.cpp @@ -0,0 +1,75 @@ +#include "stdafx.h" +#include "Utilities/SSemaphore.h" + +bool SSemaphore::wait(u64 timeout) +{ + std::unique_lock lock(m_cv_mutex); + + u64 counter = 0; + while (true) + { + if (Emu.IsStopped()) + { + return false; + } + if (timeout && counter >= timeout) + { + return false; + } + m_cond.wait_for(lock, std::chrono::milliseconds(1)); + counter++; + + std::lock_guard lock(m_mutex); + if (m_count) + { + m_count--; + return true; + } + } +} + +bool SSemaphore::try_wait() +{ + std::lock_guard lock(m_mutex); + + if (m_count) + { + m_count--; + return true; + } + else + { + return false; + } +} + +void SSemaphore::post(u32 value) +{ + std::lock_guard lock(m_mutex); + + if (m_count >= m_max) + { + value = 0; + } + else if (value > (m_max - m_count)) + { + value = m_max - m_count; + } + + while (value) + { + m_count++; + value--; + m_cond.notify_one(); + } +} + +bool SSemaphore::post_and_wait() +{ + if (try_wait()) return false; + + post(); + wait(); + + return true; +} \ No newline at end of file diff --git a/Utilities/SSemaphore.h b/Utilities/SSemaphore.h new file mode 100644 index 0000000000..af46997bbf --- /dev/null +++ b/Utilities/SSemaphore.h @@ -0,0 +1,34 @@ +#pragma once + +class SSemaphore +{ + const u32 m_max; + u32 m_count; + std::mutex m_mutex, m_cv_mutex; + std::condition_variable m_cond; + +public: + SSemaphore(u32 value, u32 max = 1) + : m_max(max > 0 ? max : 0xffffffff) + , m_count(value > m_max ? m_max : value) + { + } + + SSemaphore() + : m_max(0xffffffff) + , m_count(0) + { + } + + ~SSemaphore() + { + } + + bool wait(u64 timeout = 0); + + bool try_wait(); + + void post(u32 value = 1); + + bool post_and_wait(); +}; \ No newline at end of file diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 7a4065015b..4485227e2d 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -6,6 +6,7 @@ #include #include #include +#include class ThreadExec; @@ -138,16 +139,6 @@ public: bool IsBusy() const { return m_busy; } }; -static __forceinline bool SemaphorePostAndWait(rSemaphore& sem) -{ - if(sem.TryWait() != rSEMA_BUSY) return false; - - sem.Post(); - sem.Wait(); - - return true; -} - /* class StepThread : public ThreadBase { diff --git a/rpcs3/Emu/GS/GSRender.h b/rpcs3/Emu/GS/GSRender.h index 5f55543327..556c889606 100644 --- a/rpcs3/Emu/GS/GSRender.h +++ b/rpcs3/Emu/GS/GSRender.h @@ -32,8 +32,8 @@ public: switch(m_type) { case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Enter(); break; - case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.Wait(); break; - case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Wait(); break; + case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.wait(); break; + case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.wait(); break; } } @@ -42,8 +42,8 @@ public: switch(m_type) { case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Leave(); break; - case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.Post(); break; - case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Post(); break; + case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.post(); break; + case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.post(); break; } } }; diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 5c76ab3792..8f5b9f2d1a 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -1891,9 +1891,9 @@ void RSXThread::Task() if(put == get) { if(m_flip_status == 0) - SemaphorePostAndWait(m_sem_flip); + m_sem_flip.post_and_wait(); - SemaphorePostAndWait(m_sem_flush); + m_sem_flush.post_and_wait(); } Sleep(1); diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 2a5020c12e..96166d4c0f 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -7,6 +7,7 @@ #include #include // For tracking a list of used gcm commands +#include "Utilities/SSemaphore.h" enum Method { @@ -146,8 +147,8 @@ public: public: rCriticalSection m_cs_main; - rSemaphore m_sem_flush; - rSemaphore m_sem_flip; + SSemaphore m_sem_flush; + SSemaphore m_sem_flip; Callback m_flip_handler; public: diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 4e8b8bd3ab..25be8d5571 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -28,6 +28,7 @@ + @@ -220,6 +221,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index a5db320871..4f530fafa5 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -575,6 +575,9 @@ Emu\Io\XInput + + Utilities + @@ -1042,5 +1045,8 @@ Emu\SysCalls + + Utilities + \ No newline at end of file