Merge pull request #353 from Nekotekina/master

Tried to replace semaphore
This commit is contained in:
B1ackDaemon 2014-06-21 01:03:46 +03:00
commit dc8b0b09c6
10 changed files with 173 additions and 28 deletions

View file

@ -4,6 +4,8 @@ template<typename T, u32 SQSize = 666>
class SQueue class SQueue
{ {
std::mutex m_mutex; std::mutex m_mutex;
NamedThreadBase* push_waiter;
NamedThreadBase* pop_waiter;
u32 m_pos; u32 m_pos;
u32 m_count; u32 m_count;
T m_data[SQSize]; T m_data[SQSize];
@ -12,6 +14,8 @@ public:
SQueue() SQueue()
: m_pos(0) : m_pos(0)
, m_count(0) , m_count(0)
, push_waiter(nullptr)
, pop_waiter(nullptr)
{ {
} }
@ -22,6 +26,9 @@ public:
bool Push(const T& data) bool Push(const T& data)
{ {
NamedThreadBase* t = GetCurrentNamedThread();
push_waiter = t;
while (true) while (true)
{ {
if (m_count >= SQSize) if (m_count >= SQSize)
@ -30,7 +37,8 @@ public:
{ {
return false; return false;
} }
Sleep(1);
SM_Sleep();
continue; continue;
} }
@ -38,9 +46,11 @@ public:
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (m_count >= SQSize) continue; if (m_count >= SQSize) continue;
if (pop_waiter && !m_count) pop_waiter->Notify();
m_data[(m_pos + m_count++) % SQSize] = data; m_data[(m_pos + m_count++) % SQSize] = data;
push_waiter = nullptr;
return true; return true;
} }
} }
@ -48,6 +58,9 @@ public:
bool Pop(T& data) bool Pop(T& data)
{ {
NamedThreadBase* t = GetCurrentNamedThread();
pop_waiter = t;
while (true) while (true)
{ {
if (!m_count) if (!m_count)
@ -56,7 +69,8 @@ public:
{ {
return false; return false;
} }
Sleep(1);
SM_Sleep();
continue; continue;
} }
@ -64,22 +78,24 @@ public:
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (!m_count) continue; if (!m_count) continue;
if (push_waiter && m_count >= SQSize) push_waiter->Notify();
data = m_data[m_pos]; data = m_data[m_pos];
m_pos = (m_pos + 1) % SQSize; m_pos = (m_pos + 1) % SQSize;
m_count--; m_count--;
pop_waiter = nullptr;
return true; return true;
} }
} }
} }
volatile u32 GetCount() // may be not safe volatile u32 GetCount() // may be thread unsafe
{ {
return m_count; return m_count;
} }
volatile bool IsEmpty() // may be not safe volatile bool IsEmpty() // may be thread unsafe
{ {
return !m_count; return !m_count;
} }
@ -87,11 +103,15 @@ public:
void Clear() void Clear()
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (push_waiter && m_count >= SQSize) push_waiter->Notify();
m_count = 0; m_count = 0;
} }
T& Peek(u32 pos = 0) T& Peek(u32 pos = 0)
{ {
NamedThreadBase* t = GetCurrentNamedThread();
pop_waiter = t;
while (true) while (true)
{ {
if (!m_count) if (!m_count)
@ -100,13 +120,18 @@ public:
{ {
break; break;
} }
Sleep(1);
SM_Sleep();
continue; continue;
} }
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (m_count) break; if (m_count)
{
pop_waiter = nullptr;
break;
}
} }
} }
return m_data[(m_pos + pos) % SQSize]; return m_data[(m_pos + pos) % SQSize];

75
Utilities/SSemaphore.cpp Normal file
View file

@ -0,0 +1,75 @@
#include "stdafx.h"
#include "Utilities/SSemaphore.h"
bool SSemaphore::wait(u64 timeout)
{
std::unique_lock<std::mutex> 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<std::mutex> lock(m_mutex);
if (m_count)
{
m_count--;
return true;
}
}
}
bool SSemaphore::try_wait()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_count)
{
m_count--;
return true;
}
else
{
return false;
}
}
void SSemaphore::post(u32 value)
{
std::lock_guard<std::mutex> 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;
}

34
Utilities/SSemaphore.h Normal file
View file

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

View file

@ -6,6 +6,7 @@
#include <mutex> #include <mutex>
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include <Utilities/SSemaphore.h>
class ThreadExec; class ThreadExec;
@ -138,16 +139,6 @@ public:
bool IsBusy() const { return m_busy; } 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 class StepThread : public ThreadBase
{ {

View file

@ -32,8 +32,8 @@ public:
switch(m_type) switch(m_type)
{ {
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Enter(); break; 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_FLUSH: m_renderer.m_sem_flush.wait(); break;
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Wait(); break; case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.wait(); break;
} }
} }
@ -42,8 +42,8 @@ public:
switch(m_type) switch(m_type)
{ {
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Leave(); break; 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_FLUSH: m_renderer.m_sem_flush.post(); break;
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Post(); break; case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.post(); break;
} }
} }
}; };

View file

@ -1891,9 +1891,9 @@ void RSXThread::Task()
if(put == get) if(put == get)
{ {
if(m_flip_status == 0) 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); Sleep(1);

View file

@ -7,6 +7,7 @@
#include <stack> #include <stack>
#include <set> // For tracking a list of used gcm commands #include <set> // For tracking a list of used gcm commands
#include "Utilities/SSemaphore.h"
enum Method enum Method
{ {
@ -146,8 +147,8 @@ public:
public: public:
rCriticalSection m_cs_main; rCriticalSection m_cs_main;
rSemaphore m_sem_flush; SSemaphore m_sem_flush;
rSemaphore m_sem_flip; SSemaphore m_sem_flip;
Callback m_flip_handler; Callback m_flip_handler;
public: public:

View file

@ -147,10 +147,21 @@ int sys_ppu_thread_restart(u32 thread_id)
int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr) int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr)
{ {
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", std::string threadname = "";
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr).c_str()); if (Memory.IsGoodAddr(threadname_addr))
{
threadname = Memory.ReadString(threadname_addr);
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, threadname.c_str());
}
else
{
sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)",
thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr);
if (threadname_addr != 0) return CELL_EFAULT;
}
if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr) || !Memory.IsGoodAddr(threadname_addr)) if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr))
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
@ -163,7 +174,7 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32
new_thread.SetPrio(prio); new_thread.SetPrio(prio);
new_thread.SetStackSize(stacksize); new_thread.SetStackSize(stacksize);
//new_thread.flags = flags; //new_thread.flags = flags;
new_thread.SetName(Memory.ReadString(threadname_addr)); new_thread.SetName(threadname);
ConLog.Write("*** New PPU Thread [%s] (): id = %d", new_thread.GetName().c_str(), new_thread.GetId()); ConLog.Write("*** New PPU Thread [%s] (): id = %d", new_thread.GetName().c_str(), new_thread.GetId());

View file

@ -28,6 +28,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\Utilities\SMutex.cpp" /> <ClCompile Include="..\Utilities\SMutex.cpp" />
<ClCompile Include="..\Utilities\SSemaphore.cpp" />
<ClCompile Include="..\Utilities\StrFmt.cpp" /> <ClCompile Include="..\Utilities\StrFmt.cpp" />
<ClCompile Include="..\Utilities\Thread.cpp" /> <ClCompile Include="..\Utilities\Thread.cpp" />
<ClCompile Include="Crypto\aes.cpp" /> <ClCompile Include="Crypto\aes.cpp" />
@ -220,6 +221,7 @@
<ClInclude Include="..\Utilities\simpleini\SimpleIni.h" /> <ClInclude Include="..\Utilities\simpleini\SimpleIni.h" />
<ClInclude Include="..\Utilities\SMutex.h" /> <ClInclude Include="..\Utilities\SMutex.h" />
<ClInclude Include="..\Utilities\SQueue.h" /> <ClInclude Include="..\Utilities\SQueue.h" />
<ClInclude Include="..\Utilities\SSemaphore.h" />
<ClInclude Include="..\Utilities\StrFmt.h" /> <ClInclude Include="..\Utilities\StrFmt.h" />
<ClInclude Include="..\Utilities\Thread.h" /> <ClInclude Include="..\Utilities\Thread.h" />
<ClInclude Include="..\Utilities\Timer.h" /> <ClInclude Include="..\Utilities\Timer.h" />

View file

@ -575,6 +575,9 @@
<ClCompile Include="Emu\Io\XInput\XInputPadHandler.cpp"> <ClCompile Include="Emu\Io\XInput\XInputPadHandler.cpp">
<Filter>Emu\Io\XInput</Filter> <Filter>Emu\Io\XInput</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Utilities\SSemaphore.cpp">
<Filter>Utilities</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Crypto\aes.h"> <ClInclude Include="Crypto\aes.h">
@ -1042,5 +1045,8 @@
<ClInclude Include="Emu\event.h"> <ClInclude Include="Emu\event.h">
<Filter>Emu\SysCalls</Filter> <Filter>Emu\SysCalls</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Utilities\SSemaphore.h">
<Filter>Utilities</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>