rCriticalSection & rSemaphore removed

SC_Semaphore errors fixed
Room for interrupt threads
This commit is contained in:
Nekotekina 2014-06-22 14:59:28 +04:00
parent 2fad8039f5
commit 30b8e51234
15 changed files with 84 additions and 148 deletions

View file

@ -1,68 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
rSemaphore::rSemaphore()
{
handle = reinterpret_cast<void*>(new wxSemaphore());
}
rSemaphore::~rSemaphore()
{
delete reinterpret_cast<wxSemaphore*>(handle);
}
rSemaphore::rSemaphore(int initial_count, int max_count)
{
handle = reinterpret_cast<void*>(new wxSemaphore(initial_count,max_count));
}
void rSemaphore::Wait()
{
reinterpret_cast<wxSemaphore*>(handle)->Wait();
}
rSemaStatus rSemaphore::TryWait()
{
wxSemaError err = reinterpret_cast<wxSemaphore*>(handle)->TryWait();
if (err == wxSEMA_BUSY)
{
return rSEMA_BUSY;
}
else
{
return rSEMA_OTHER;
}
}
void rSemaphore::Post()
{
reinterpret_cast<wxSemaphore*>(handle)->Post();
}
void rSemaphore::WaitTimeout(u64 timeout)
{
reinterpret_cast<wxSemaphore*>(handle)->WaitTimeout(timeout);
}
rCriticalSection::rCriticalSection()
{
handle = reinterpret_cast<void*>(new wxCriticalSection());
}
rCriticalSection::~rCriticalSection()
{
delete reinterpret_cast<wxCriticalSection*>(handle);
}
void rCriticalSection::Enter()
{
reinterpret_cast<wxCriticalSection*>(handle)->Enter();
}
void rCriticalSection::Leave()
{
reinterpret_cast<wxCriticalSection*>(handle)->Leave();
}
rTimer::rTimer() rTimer::rTimer()
{ {
handle = reinterpret_cast<void*>(new wxTimer()); handle = reinterpret_cast<void*>(new wxTimer());
@ -93,17 +30,6 @@ void rMicroSleep(u64 time)
wxMicroSleep(time); wxMicroSleep(time);
} }
rCriticalSectionLocker::rCriticalSectionLocker(const rCriticalSection &sec)
{
handle = reinterpret_cast<void*>(new wxCriticalSectionLocker(*reinterpret_cast<wxCriticalSection*>(sec.handle)));
}
rCriticalSectionLocker::~rCriticalSectionLocker()
{
delete reinterpret_cast<wxCriticalSectionLocker*>(handle);
}
bool rThread::IsMain() bool rThread::IsMain()
{ {
return wxThread::IsMain(); return wxThread::IsMain();

View file

@ -1,34 +1,5 @@
#pragma once #pragma once
enum rSemaStatus
{
rSEMA_BUSY,
rSEMA_OTHER
};
struct rSemaphore
{
rSemaphore();
rSemaphore(const rSemaphore& other) = delete;
~rSemaphore();
rSemaphore(int initial_count, int max_count);
void Wait();
rSemaStatus TryWait();
void Post();
void WaitTimeout(u64 timeout);
private:
void *handle;
};
struct rCriticalSection
{
rCriticalSection();
rCriticalSection(const rCriticalSection& other) = delete;
~rCriticalSection();
void Enter();
void Leave();
void *handle;
};
struct rTimer struct rTimer
{ {
rTimer(); rTimer();
@ -43,14 +14,6 @@ private:
void rSleep(u32 time); void rSleep(u32 time);
void rMicroSleep(u64 time); void rMicroSleep(u64 time);
struct rCriticalSectionLocker
{
rCriticalSectionLocker(const rCriticalSection& other);
~rCriticalSectionLocker();
private:
void *handle;
};
struct rThread struct rThread
{ {
static bool IsMain(); static bool IsMain();

View file

@ -85,13 +85,13 @@ void CPUThread::SetName(const std::string& name)
void CPUThread::Wait(bool wait) void CPUThread::Wait(bool wait)
{ {
rCriticalSectionLocker lock(m_cs_sync); std::lock_guard<std::mutex> lock(m_cs_sync);
m_sync_wait = wait; m_sync_wait = wait;
} }
void CPUThread::Wait(const CPUThread& thr) void CPUThread::Wait(const CPUThread& thr)
{ {
rCriticalSectionLocker lock(m_cs_sync); std::lock_guard<std::mutex> lock(m_cs_sync);
m_wait_thread_id = thr.GetId(); m_wait_thread_id = thr.GetId();
m_sync_wait = true; m_sync_wait = true;
} }

View file

@ -138,7 +138,7 @@ public:
u32 m_wait_thread_id; u32 m_wait_thread_id;
rCriticalSection m_cs_sync; std::mutex m_cs_sync;
bool m_sync_wait; bool m_sync_wait;
void Wait(bool wait); void Wait(bool wait);
void Wait(const CPUThread& thr); void Wait(const CPUThread& thr);

View file

@ -6,7 +6,6 @@ class CPUThreadManager
{ {
std::vector<CPUThread*> m_threads; std::vector<CPUThread*> m_threads;
std::mutex m_mtx_thread; std::mutex m_mtx_thread;
rSemaphore m_sem_task;
u32 m_raw_spu_num; u32 m_raw_spu_num;
public: public:

View file

@ -900,6 +900,13 @@ public:
switch(ch) switch(ch)
{ {
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
if (!group) // if RawSPU
{
// TODO: run PPU interrupt thread
ConLog.Error("SPU_WrOutIntrMbox interrupt unimplemented");
Emu.Pause();
}
else
{ {
u8 code = v >> 24; u8 code = v >> 24;
if (code < 64) if (code < 64)
@ -933,7 +940,9 @@ public:
if (!port.eq) if (!port.eq)
{ {
SPU.In_MBox.PushUncond(CELL_ENOTCONN); // check error passing // spu_printf fails there
ConLog.Warning("sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, v & 0x00ffffff, data);
SPU.In_MBox.PushUncond(CELL_ENOTCONN); // TODO: check error passing
return; return;
} }

View file

@ -31,7 +31,7 @@ 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.lock(); 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;
} }
@ -41,7 +41,7 @@ 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.unlock(); 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

@ -1877,7 +1877,7 @@ void RSXThread::Task()
ConLog.Warning("RSX thread aborted"); ConLog.Warning("RSX thread aborted");
return; return;
} }
rCriticalSectionLocker lock(m_cs_main); std::lock_guard<std::mutex> lock(m_cs_main);
inc=1; inc=1;

View file

@ -148,7 +148,7 @@ public:
u32 m_draw_array_first; u32 m_draw_array_first;
public: public:
rCriticalSection m_cs_main; std::mutex m_cs_main;
SSemaphore m_sem_flush; SSemaphore m_sem_flush;
SSemaphore m_sem_flip; SSemaphore m_sem_flip;
Callback m_flip_handler; Callback m_flip_handler;

View file

@ -201,15 +201,15 @@ extern void sys_spinlock_unlock(mem_ptr_t<spinlock> lock);
//ppu_thread //ppu_thread
extern void sys_ppu_thread_exit(u64 errorcode); extern void sys_ppu_thread_exit(u64 errorcode);
extern int sys_ppu_thread_yield(); extern int sys_ppu_thread_yield();
extern int sys_ppu_thread_join(u32 thread_id, mem64_t vptr); extern int sys_ppu_thread_join(u64 thread_id, mem64_t vptr);
extern int sys_ppu_thread_detach(u32 thread_id); extern int sys_ppu_thread_detach(u64 thread_id);
extern void sys_ppu_thread_get_join_state(u32 isjoinable_addr); extern void sys_ppu_thread_get_join_state(u32 isjoinable_addr);
extern int sys_ppu_thread_set_priority(u32 thread_id, int prio); extern int sys_ppu_thread_set_priority(u64 thread_id, int prio);
extern int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr); extern int sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr);
extern int sys_ppu_thread_get_stack_information(u32 info_addr); extern int sys_ppu_thread_get_stack_information(u32 info_addr);
extern int sys_ppu_thread_stop(u32 thread_id); extern int sys_ppu_thread_stop(u64 thread_id);
extern int sys_ppu_thread_restart(u32 thread_id); extern int sys_ppu_thread_restart(u64 thread_id);
extern int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); extern int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry); extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry);
extern int sys_ppu_thread_get_id(const u32 id_addr); extern int sys_ppu_thread_get_id(const u32 id_addr);

View file

@ -194,7 +194,12 @@ u32 SleepQueue::count()
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
return list.size(); u32 result = 0;
for (u32 i = 0; i < list.size(); i++)
{
if (list[i]) result++;
}
return result;
} }
bool SleepQueue::finalize() bool SleepQueue::finalize()

View file

@ -10,12 +10,19 @@
extern Module *sysPrxForUser; extern Module *sysPrxForUser;
static const u32 PPU_THREAD_ID_INVALID = 0xFFFFFFFFU; static const u32 PPU_THREAD_ID_INVALID = 0xFFFFFFFFU;
enum enum
{ {
SYS_PPU_THREAD_ONCE_INIT, SYS_PPU_THREAD_ONCE_INIT,
SYS_PPU_THREAD_DONE_INIT, SYS_PPU_THREAD_DONE_INIT,
}; };
enum ppu_thread_flags : u64
{
SYS_PPU_THREAD_CREATE_JOINABLE = 0x1,
SYS_PPU_THREAD_CREATE_INTERRUPT = 0x2,
};
void sys_ppu_thread_exit(u64 errorcode) void sys_ppu_thread_exit(u64 errorcode)
{ {
sysPrxForUser->Log("sys_ppu_thread_exit(0x%llx)", errorcode); sysPrxForUser->Log("sys_ppu_thread_exit(0x%llx)", errorcode);
@ -40,7 +47,7 @@ int sys_ppu_thread_yield()
return CELL_OK; return CELL_OK;
} }
int sys_ppu_thread_join(u32 thread_id, mem64_t vptr) int sys_ppu_thread_join(u64 thread_id, mem64_t vptr)
{ {
sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr.GetAddr()); sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr.GetAddr());
@ -61,7 +68,7 @@ int sys_ppu_thread_join(u32 thread_id, mem64_t vptr)
return CELL_OK; return CELL_OK;
} }
int sys_ppu_thread_detach(u32 thread_id) int sys_ppu_thread_detach(u64 thread_id)
{ {
sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%d)", thread_id); sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%d)", thread_id);
@ -81,7 +88,7 @@ void sys_ppu_thread_get_join_state(u32 isjoinable_addr)
Memory.Write32(isjoinable_addr, GetCurrentPPUThread().IsJoinable()); Memory.Write32(isjoinable_addr, GetCurrentPPUThread().IsJoinable());
} }
int sys_ppu_thread_set_priority(u32 thread_id, int prio) int sys_ppu_thread_set_priority(u64 thread_id, int prio)
{ {
sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio); sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio);
@ -93,7 +100,7 @@ int sys_ppu_thread_set_priority(u32 thread_id, int prio)
return CELL_OK; return CELL_OK;
} }
int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr) int sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr)
{ {
sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr); sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr);
@ -120,7 +127,7 @@ int sys_ppu_thread_get_stack_information(u32 info_addr)
return CELL_OK; return CELL_OK;
} }
int sys_ppu_thread_stop(u32 thread_id) int sys_ppu_thread_stop(u64 thread_id)
{ {
sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id); sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id);
@ -132,7 +139,7 @@ int sys_ppu_thread_stop(u32 thread_id)
return CELL_OK; return CELL_OK;
} }
int sys_ppu_thread_restart(u32 thread_id) int sys_ppu_thread_restart(u64 thread_id)
{ {
sysPrxForUser->Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id); sysPrxForUser->Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id);
@ -145,30 +152,50 @@ int sys_ppu_thread_restart(u32 thread_id)
return CELL_OK; return CELL_OK;
} }
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(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr)
{ {
std::string threadname = ""; std::string threadname = "";
if (Memory.IsGoodAddr(threadname_addr)) if (Memory.IsGoodAddr(threadname_addr))
{ {
threadname = Memory.ReadString(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'))", 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()); thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr, threadname.c_str());
} }
else 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)", 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); thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr);
if (threadname_addr != 0) return CELL_EFAULT; if (threadname_addr != 0) return CELL_EFAULT;
} }
if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr)) if (!Memory.IsGoodAddr(entry) || !thread_id.IsGood())
{ {
return CELL_EFAULT; return CELL_EFAULT;
} }
bool is_joinable = false;
bool is_interrupt = false;
switch (flags)
{
case 0: break;
case SYS_PPU_THREAD_CREATE_JOINABLE:
{
is_joinable = true;
break;
}
case SYS_PPU_THREAD_CREATE_INTERRUPT:
{
sysPrxForUser->Error("sys_ppu_thread_create: unimplemented flag (SYS_PPU_THREAD_CREATE_INTERRUPT)");
is_interrupt = true;
break;
}
default: sysPrxForUser->Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM;
}
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);
Memory.Write64(thread_id_addr, new_thread.GetId()); thread_id = new_thread.GetId();
new_thread.SetEntry(entry); new_thread.SetEntry(entry);
new_thread.SetArg(0, arg); new_thread.SetArg(0, arg);
new_thread.SetPrio(prio); new_thread.SetPrio(prio);
@ -176,7 +203,7 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u64 arg, int prio, u32
//new_thread.flags = flags; //new_thread.flags = flags;
new_thread.SetName(threadname); 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] (flags=0x%llx, entry=0x%x): id = %d", new_thread.GetName().c_str(), flags, entry, new_thread.GetId());
new_thread.Run(); new_thread.Run();
new_thread.Exec(); new_thread.Exec();

View file

@ -17,14 +17,15 @@ int sys_semaphore_create(mem32_t sem, mem_ptr_t<sys_semaphore_attribute> attr, i
return CELL_EFAULT; return CELL_EFAULT;
} }
if (max_count <= 0) if (max_count <= 0 || initial_count > max_count || initial_count < 0)
{ {
sys_sem.Error("sys_semaphore_create(): invalid parameters (initial_count=%d, max_count=%d)", initial_count, max_count);
return CELL_EINVAL; return CELL_EINVAL;
} }
if (attr->pshared.ToBE() != se32(0x200)) if (attr->pshared.ToBE() != se32(0x200))
{ {
sys_sem.Error("Invalid pshared attribute(0x%x)", (u32)attr->pshared); sys_sem.Error("sys_semaphore_create(): invalid pshared value(0x%x)", (u32)attr->pshared);
return CELL_EINVAL; return CELL_EINVAL;
} }
@ -96,6 +97,7 @@ int sys_semaphore_wait(u32 sem_id, u64 timeout)
if (timeout && get_system_time() - start_time > timeout) if (timeout && get_system_time() - start_time > timeout)
{ {
sem->m_queue.invalidate(tid);
return CELL_ETIMEDOUT; return CELL_ETIMEDOUT;
} }
@ -103,6 +105,10 @@ int sys_semaphore_wait(u32 sem_id, u64 timeout)
{ {
std::lock_guard<std::mutex> lock(sem->m_mutex); std::lock_guard<std::mutex> lock(sem->m_mutex);
if (tid != sem->signal)
{
continue;
}
sem->signal = 0; sem->signal = 0;
// TODO: notify signaler // TODO: notify signaler
return CELL_OK; return CELL_OK;
@ -150,9 +156,9 @@ int sys_semaphore_post(u32 sem_id, int count)
return CELL_EINVAL; return CELL_EINVAL;
} }
if (count + sem->m_value - sem->m_queue.count() > sem->max) if (count + sem->m_value - (int)sem->m_queue.count() > sem->max)
{ {
return CELL_EINVAL; return CELL_EBUSY;
} }
while (count > 0) while (count > 0)
@ -191,6 +197,11 @@ int sys_semaphore_get_value(u32 sem_id, mem32_t count)
{ {
sys_sem.Log("sys_semaphore_get_value(sem_id=%d, count_addr=0x%x)", sem_id, count.GetAddr()); sys_sem.Log("sys_semaphore_get_value(sem_id=%d, count_addr=0x%x)", sem_id, count.GetAddr());
if (!count.IsGood())
{
return CELL_EFAULT;
}
Semaphore* sem; Semaphore* sem;
if (!Emu.GetIdManager().GetIDData(sem_id, sem)) if (!Emu.GetIdManager().GetIDData(sem_id, sem))
{ {

View file

@ -246,7 +246,6 @@
<ClInclude Include="Emu\Cell\PPCDisAsm.h" /> <ClInclude Include="Emu\Cell\PPCDisAsm.h" />
<ClInclude Include="Emu\Cell\PPCInstrTable.h" /> <ClInclude Include="Emu\Cell\PPCInstrTable.h" />
<ClInclude Include="Emu\Cell\PPCThread.h" /> <ClInclude Include="Emu\Cell\PPCThread.h" />
<ClInclude Include="Emu\Cell\PPCThreadManager.h" />
<ClInclude Include="Emu\Cell\PPUDecoder.h" /> <ClInclude Include="Emu\Cell\PPUDecoder.h" />
<ClInclude Include="Emu\Cell\PPUDisAsm.h" /> <ClInclude Include="Emu\Cell\PPUDisAsm.h" />
<ClInclude Include="Emu\Cell\PPUInstrTable.h" /> <ClInclude Include="Emu\Cell\PPUInstrTable.h" />

View file

@ -850,9 +850,6 @@
<ClInclude Include="Emu\Cell\PPCThread.h"> <ClInclude Include="Emu\Cell\PPCThread.h">
<Filter>Emu\Cell</Filter> <Filter>Emu\Cell</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\Cell\PPCThreadManager.h">
<Filter>Emu\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUDecoder.h"> <ClInclude Include="Emu\Cell\PPUDecoder.h">
<Filter>Emu\Cell</Filter> <Filter>Emu\Cell</Filter>
</ClInclude> </ClInclude>