diff --git a/Utilities/rConcurrency.cpp b/Utilities/rConcurrency.cpp index 10afc624e2..c36f70e486 100644 --- a/Utilities/rConcurrency.cpp +++ b/Utilities/rConcurrency.cpp @@ -1,68 +1,5 @@ #include "stdafx.h" -rSemaphore::rSemaphore() -{ - handle = reinterpret_cast(new wxSemaphore()); -} - -rSemaphore::~rSemaphore() -{ - delete reinterpret_cast(handle); -} - -rSemaphore::rSemaphore(int initial_count, int max_count) -{ - handle = reinterpret_cast(new wxSemaphore(initial_count,max_count)); -} - -void rSemaphore::Wait() -{ - reinterpret_cast(handle)->Wait(); -} - -rSemaStatus rSemaphore::TryWait() -{ - wxSemaError err = reinterpret_cast(handle)->TryWait(); - if (err == wxSEMA_BUSY) - { - return rSEMA_BUSY; - } - else - { - return rSEMA_OTHER; - } -} - -void rSemaphore::Post() -{ - reinterpret_cast(handle)->Post(); -} - -void rSemaphore::WaitTimeout(u64 timeout) -{ - reinterpret_cast(handle)->WaitTimeout(timeout); -} - -rCriticalSection::rCriticalSection() -{ - handle = reinterpret_cast(new wxCriticalSection()); -} - -rCriticalSection::~rCriticalSection() -{ - delete reinterpret_cast(handle); -} - -void rCriticalSection::Enter() -{ - reinterpret_cast(handle)->Enter(); -} - -void rCriticalSection::Leave() -{ - reinterpret_cast(handle)->Leave(); -} - rTimer::rTimer() { handle = reinterpret_cast(new wxTimer()); @@ -93,17 +30,6 @@ void rMicroSleep(u64 time) wxMicroSleep(time); } -rCriticalSectionLocker::rCriticalSectionLocker(const rCriticalSection &sec) -{ - handle = reinterpret_cast(new wxCriticalSectionLocker(*reinterpret_cast(sec.handle))); -} - - -rCriticalSectionLocker::~rCriticalSectionLocker() -{ - delete reinterpret_cast(handle); -} - bool rThread::IsMain() { return wxThread::IsMain(); diff --git a/Utilities/rConcurrency.h b/Utilities/rConcurrency.h index 506e3fecd3..8504daef1b 100644 --- a/Utilities/rConcurrency.h +++ b/Utilities/rConcurrency.h @@ -1,34 +1,5 @@ #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 { rTimer(); @@ -43,14 +14,6 @@ private: void rSleep(u32 time); void rMicroSleep(u64 time); -struct rCriticalSectionLocker -{ - rCriticalSectionLocker(const rCriticalSection& other); - ~rCriticalSectionLocker(); -private: - void *handle; -}; - struct rThread { static bool IsMain(); diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index e6c7a09cb0..10da0f8608 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -85,13 +85,13 @@ void CPUThread::SetName(const std::string& name) void CPUThread::Wait(bool wait) { - rCriticalSectionLocker lock(m_cs_sync); + std::lock_guard lock(m_cs_sync); m_sync_wait = wait; } void CPUThread::Wait(const CPUThread& thr) { - rCriticalSectionLocker lock(m_cs_sync); + std::lock_guard lock(m_cs_sync); m_wait_thread_id = thr.GetId(); m_sync_wait = true; } diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 5fd14c402b..e725e719d9 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -138,7 +138,7 @@ public: u32 m_wait_thread_id; - rCriticalSection m_cs_sync; + std::mutex m_cs_sync; bool m_sync_wait; void Wait(bool wait); void Wait(const CPUThread& thr); diff --git a/rpcs3/Emu/CPU/CPUThreadManager.h b/rpcs3/Emu/CPU/CPUThreadManager.h index f40a9e936d..6ccdf568e7 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.h +++ b/rpcs3/Emu/CPU/CPUThreadManager.h @@ -6,7 +6,6 @@ class CPUThreadManager { std::vector m_threads; std::mutex m_mtx_thread; - rSemaphore m_sem_task; u32 m_raw_spu_num; public: diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 664a1e24f0..270d92dde5 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -900,6 +900,13 @@ public: switch(ch) { 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; if (code < 64) @@ -933,7 +940,9 @@ public: 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; } diff --git a/rpcs3/Emu/GS/GSRender.h b/rpcs3/Emu/GS/GSRender.h index 556c889606..86d74748a2 100644 --- a/rpcs3/Emu/GS/GSRender.h +++ b/rpcs3/Emu/GS/GSRender.h @@ -31,7 +31,7 @@ public: { 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_FLIP: m_renderer.m_sem_flip.wait(); break; } @@ -41,7 +41,7 @@ public: { 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_FLIP: m_renderer.m_sem_flip.post(); break; } diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 7e4c1bfa2a..268eb8cf1d 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -1877,7 +1877,7 @@ void RSXThread::Task() ConLog.Warning("RSX thread aborted"); return; } - rCriticalSectionLocker lock(m_cs_main); + std::lock_guard lock(m_cs_main); inc=1; diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 310011e044..e1068c4c55 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -148,7 +148,7 @@ public: u32 m_draw_array_first; public: - rCriticalSection m_cs_main; + std::mutex m_cs_main; SSemaphore m_sem_flush; SSemaphore m_sem_flip; Callback m_flip_handler; diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index bb438c33f2..413df89e7b 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -201,15 +201,15 @@ extern void sys_spinlock_unlock(mem_ptr_t lock); //ppu_thread extern void sys_ppu_thread_exit(u64 errorcode); extern int sys_ppu_thread_yield(); -extern int sys_ppu_thread_join(u32 thread_id, mem64_t vptr); -extern int sys_ppu_thread_detach(u32 thread_id); +extern int sys_ppu_thread_join(u64 thread_id, mem64_t vptr); +extern int sys_ppu_thread_detach(u64 thread_id); 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_get_priority(u32 thread_id, u32 prio_addr); +extern int sys_ppu_thread_set_priority(u64 thread_id, int prio); +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_stop(u32 thread_id); -extern int sys_ppu_thread_restart(u32 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_stop(u64 thread_id); +extern int sys_ppu_thread_restart(u64 thread_id); +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 int sys_ppu_thread_get_id(const u32 id_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 4461ce9dfe..c1650a6efa 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -194,7 +194,12 @@ u32 SleepQueue::count() { std::lock_guard 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() diff --git a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp index 94b9f9f969..83316d7e45 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp @@ -10,12 +10,19 @@ extern Module *sysPrxForUser; static const u32 PPU_THREAD_ID_INVALID = 0xFFFFFFFFU; + enum { SYS_PPU_THREAD_ONCE_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) { sysPrxForUser->Log("sys_ppu_thread_exit(0x%llx)", errorcode); @@ -40,7 +47,7 @@ int sys_ppu_thread_yield() 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()); @@ -61,7 +68,7 @@ int sys_ppu_thread_join(u32 thread_id, mem64_t vptr) 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); @@ -81,7 +88,7 @@ void sys_ppu_thread_get_join_state(u32 isjoinable_addr) 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); @@ -93,7 +100,7 @@ int sys_ppu_thread_set_priority(u32 thread_id, int prio) 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); @@ -120,7 +127,7 @@ int sys_ppu_thread_get_stack_information(u32 info_addr) 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); @@ -132,7 +139,7 @@ int sys_ppu_thread_stop(u32 thread_id) 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); @@ -145,30 +152,50 @@ int sys_ppu_thread_restart(u32 thread_id) 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 = ""; 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()); + thread_id.GetAddr(), 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); + thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr); 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; } + 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); - Memory.Write64(thread_id_addr, new_thread.GetId()); + thread_id = new_thread.GetId(); new_thread.SetEntry(entry); new_thread.SetArg(0, arg); 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.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.Exec(); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp index 2ef88daefd..b256e1c380 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp @@ -17,14 +17,15 @@ int sys_semaphore_create(mem32_t sem, mem_ptr_t attr, i 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; } 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; } @@ -96,6 +97,7 @@ int sys_semaphore_wait(u32 sem_id, u64 timeout) if (timeout && get_system_time() - start_time > timeout) { + sem->m_queue.invalidate(tid); return CELL_ETIMEDOUT; } @@ -103,6 +105,10 @@ int sys_semaphore_wait(u32 sem_id, u64 timeout) { std::lock_guard lock(sem->m_mutex); + if (tid != sem->signal) + { + continue; + } sem->signal = 0; // TODO: notify signaler return CELL_OK; @@ -150,9 +156,9 @@ int sys_semaphore_post(u32 sem_id, int count) 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) @@ -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()); + if (!count.IsGood()) + { + return CELL_EFAULT; + } + Semaphore* sem; if (!Emu.GetIdManager().GetIDData(sem_id, sem)) { diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 031e1039df..61140cd079 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -246,7 +246,6 @@ - diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 5ddf7ac06e..7e3284658a 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -850,9 +850,6 @@ Emu\Cell - - Emu\Cell - Emu\Cell