From 67a144df2a7b7f3018aefd49c123b1f8601e763a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 30 Jan 2014 00:31:09 +0400 Subject: [PATCH 1/5] SC_Rwlock implementation, SC_Lwcond draft Other small changes --- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 16 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 7 + rpcs3/Emu/SysCalls/SysCalls.h | 9 ++ rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp | 81 ++++++++++ rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h | 24 +++ rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 43 ++++-- rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp | 141 +++++++++++++++-- rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h | 154 ++++++++++++++++++- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 6 +- rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 3 + 11 files changed, 451 insertions(+), 34 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp create mode 100644 rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index 1e33d4d572..ee7f8d2973 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -365,6 +365,8 @@ int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t pSelf) { + cellPamf.Log("cellPamfReaderGetStreamIndex(pSelf=0x%x)", pSelf.GetAddr()); + return pSelf->stream; } @@ -506,7 +508,7 @@ int cellPamfReaderGetNumberOfEp(mem_ptr_t pSelf) int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t pSelf, u32 epIndex, mem_ptr_t pIt) { - cellPamf.Warning("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)", + cellPamf.Error("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)", pSelf.GetAddr(), pSelf->stream, epIndex, pIt.GetAddr()); const mem_ptr_t pAddr(pSelf->pAddr); @@ -516,19 +518,25 @@ int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t pSelf, u32 ep int cellPamfReaderGetEpIteratorWithTimeStamp(mem_ptr_t pSelf, mem_ptr_t pTimeStamp, mem_ptr_t pIt) { - UNIMPLEMENTED_FUNC(cellPamf); + cellPamf.Error("cellPamfReaderGetEpIteratorWithTimeStamp(pSelf=0x%x, pTimeStamp_addr=0x%x, pIt_addr=0x%x)", + pSelf.GetAddr(), pTimeStamp.GetAddr(), pIt.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + //TODO: return CELL_OK; } int cellPamfEpIteratorGetEp(mem_ptr_t pIt, mem_ptr_t pEp) { - UNIMPLEMENTED_FUNC(cellPamf); + cellPamf.Error("cellPamfEpIteratorGetEp(pIt_addr=0x%x, pEp_addr=0x%x)", pIt.GetAddr(), pEp.GetAddr()); + //TODO: return CELL_OK; } int cellPamfEpIteratorMove(mem_ptr_t pIt, int steps, mem_ptr_t pEp) { - UNIMPLEMENTED_FUNC(cellPamf); + cellPamf.Error("cellPamfEpIteratorMove(pIt_addr=0x%x, steps=%d, pEp_addr=0x%x)", pIt.GetAddr(), steps, pEp.GetAddr()); + //TODO: return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index e08e90cae4..dd43be259e 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -175,4 +175,11 @@ void sysPrxForUser_init() sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_load); sysPrxForUser.AddFunc(0xb995662e, sys_raw_spu_image_load); + + sysPrxForUser.AddFunc(0xda0eb71a, sys_lwcond_create); + sysPrxForUser.AddFunc(0x1c9a942c, sys_lwcond_destroy); + sysPrxForUser.AddFunc(0xef87a695, sys_lwcond_signal); + sysPrxForUser.AddFunc(0xe9a1bd84, sys_lwcond_signal_all); + sysPrxForUser.AddFunc(0x52aadadf, sys_lwcond_signal_to); + sysPrxForUser.AddFunc(0x2a6d9d51, sys_lwcond_wait); } diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 6158e81a1f..7c18cb6df0 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -6,6 +6,7 @@ #include "lv2/SC_Rwlock.h" #include "lv2/SC_SPU_Thread.h" #include "lv2/SC_Lwmutex.h" +#include "lv2/SC_Lwcond.h" #include "Emu/event.h" //#define SYSCALLS_DEBUG @@ -147,6 +148,14 @@ extern int sys_semaphore_trywait(u32 sem); extern int sys_semaphore_post(u32 sem, int count); extern int sys_semaphore_get_value(u32 sem, u32 count_addr); +//sys_lwcond +extern int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t lwmutex, mem_ptr_t attr); +extern int sys_lwcond_destroy(mem_ptr_t lwcond); +extern int sys_lwcond_signal(mem_ptr_t lwcond); +extern int sys_lwcond_signal_all(mem_ptr_t lwcond); +extern int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id); +extern int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout); + //sys_lwmutex extern int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_t attr); extern int sys_lwmutex_destroy(mem_ptr_t lwmutex); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp new file mode 100644 index 0000000000..da208a6495 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp @@ -0,0 +1,81 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "SC_Lwmutex.h" +#include "SC_Lwcond.h" + +SysCallBase sys_lwcond("sys_lwcond"); + +int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t lwmutex, mem_ptr_t attr) +{ + sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)", + lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr()); + + if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; + + lwcond->lwmutex_addr = lwmutex.GetAddr(); + lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(*(u64*)&attr->name)); + + sys_lwcond.Warning("*** lwcond created [%s]", attr->name); + return CELL_OK; +} + +int sys_lwcond_destroy(mem_ptr_t lwcond) +{ + sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.GetAddr()); + + if (!lwcond.IsGood()) return CELL_EFAULT; + LWCond* lwc; + u32 id = (u32)lwcond->lwcond_queue; + if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + + Emu.GetIdManager().RemoveID(id); + return CELL_OK; +} + +int sys_lwcond_signal(mem_ptr_t lwcond) +{ + sys_lwcond.Warning("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.GetAddr()); + + if (!lwcond.IsGood()) return CELL_EFAULT; + LWCond* lwc; + u32 id = (u32)lwcond->lwcond_queue; + if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + + return CELL_OK; +} + +int sys_lwcond_signal_all(mem_ptr_t lwcond) +{ + sys_lwcond.Warning("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.GetAddr()); + + if (!lwcond.IsGood()) return CELL_EFAULT; + LWCond* lwc; + u32 id = (u32)lwcond->lwcond_queue; + if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + + return CELL_OK; +} + +int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) +{ + sys_lwcond.Warning("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.GetAddr(), ppu_thread_id); + + if (!lwcond.IsGood()) return CELL_EFAULT; + LWCond* lwc; + u32 id = (u32)lwcond->lwcond_queue; + if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + + return CELL_OK; +} + +int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) +{ + sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%llu)", lwcond.GetAddr(), timeout); + + if (!lwcond.IsGood()) return CELL_EFAULT; + LWCond* lwc; + u32 id = (u32)lwcond->lwcond_queue; + if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h new file mode 100644 index 0000000000..30eab02f61 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h @@ -0,0 +1,24 @@ +#pragma once + +struct sys_lwcond_attribute_t +{ + char name[8]; +}; + +struct sys_lwcond_t +{ + be_t lwmutex_addr; + be_t lwcond_queue; +}; + +#pragma pack() + +struct LWCond +{ + u64 m_name; + + LWCond(u64 name) + : m_name(name) + { + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index c1e2779df4..ad313f9334 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -23,10 +23,10 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_tattr_protocol) { - case SYS_SYNC_PRIORITY: break; - case SYS_SYNC_RETRY: sc_lwmutex.Error("TODO: SYS_SYNC_RETRY attr"); break; - case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Error("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; - case SYS_SYNC_FIFO: sc_lwmutex.Error("TODO: SYS_SYNC_FIFO attr"); break; + case SYS_SYNC_PRIORITY: sc_lwmutex.Log("TODO: SYS_SYNC_PRIORITY attr"); break; + case SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break; + case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; + case SYS_SYNC_FIFO: sc_lwmutex.Log("TODO: SYS_SYNC_FIFO attr"); break; default: return CELL_EINVAL; } @@ -36,15 +36,31 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_trecursive_count = 0; lwmutex->sleep_queue = 0; - sc_lwmutex.Log("*** lwmutex created [%s] (protocol=0x%x, recursive=0x%x)", - attr->name, (u32)attr->attr_protocol, (u32)attr->attr_recursive); + sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute); return CELL_OK; } int sys_lwmutex_destroy(mem_ptr_t lwmutex) { - sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + + if (!lwmutex.IsGood()) return CELL_EFAULT; + + if (!lwmutex->attribute) return CELL_EINVAL; + + { // global lock + std::lock_guard lock(g_lwmutex); + + if (!lwmutex->owner) + { + lwmutex->attribute = 0; + } + else + { + return CELL_EBUSY; + } + } return CELL_OK; } @@ -55,6 +71,8 @@ int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) if (!lwmutex.IsGood()) return CELL_EFAULT; + if (!lwmutex->attribute) return CELL_EINVAL; + PPCThread& thr = GetCurrentPPUThread(); const u32 id = thr.GetId(); @@ -80,7 +98,7 @@ int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) if (!lwmutex->owner) // lock { - lwmutex->owner = id; + lwmutex->owner = id; lwmutex->recursive_count = 1; return CELL_OK; } @@ -91,6 +109,7 @@ int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) const u32 max_counter = timeout ? (timeout / 1000) : 20000; do // waiting { + if (Emu.IsStopped()) return CELL_ETIMEDOUT; Sleep(1); { // global lock @@ -108,9 +127,9 @@ int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) if (counter++ > max_counter) { if (!timeout) - { // endless waiter - sc_lwmutex.Error("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr()); - return CELL_OK; + { + sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr()); + counter = 0; } else { @@ -126,6 +145,8 @@ int sys_lwmutex_trylock(mem_ptr_t lwmutex) if (!lwmutex.IsGood()) return CELL_EFAULT; + if (!lwmutex->attribute) return CELL_EINVAL; + PPCThread& thr = GetCurrentPPUThread(); const u32 id = thr.GetId(); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp index c17c90cf58..1cadd83e07 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp @@ -6,48 +6,169 @@ SysCallBase sys_rwlock("sys_rwlock"); int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr()); + sys_rwlock.Warning("sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr()); + + if (!rw_lock_id.IsGood() || !attr.IsGood()) return CELL_EFAULT; + + switch ((u32)attr->attr_protocol) + { + case SYS_SYNC_PRIORITY: sys_rwlock.Log("TODO: SYS_SYNC_PRIORITY attr"); break; + case SYS_SYNC_RETRY: sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break; + case SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; + case SYS_SYNC_FIFO: break; + default: return CELL_EINVAL; + } + + if ((u32)attr->attr_pshared != 0x200) + { + sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared); + return CELL_EINVAL; + } + + rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared, + (u64)attr->key, (s32)attr->flags, *(u64*)&attr->name)); + + sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x)", attr->name, (u32)attr->attr_protocol); + return CELL_OK; } int sys_rwlock_destroy(u32 rw_lock_id) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id); + sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + + std::lock_guard lock(rw->m_lock); + + if (rw->wlock_queue.GetCount() || rw->rlock_list.GetCount() || rw->wlock_thread) return CELL_EBUSY; + + Emu.GetIdManager().RemoveID(rw_lock_id); + return CELL_OK; } int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); - return CELL_OK; + sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); + + if (rw->rlock_trylock(id)) return CELL_OK; + + u32 counter = 0; + const u32 max_counter = timeout ? (timeout / 1000) : 20000; + do + { + if (Emu.IsStopped()) return CELL_ETIMEDOUT; + Sleep(1); + + if (rw->rlock_trylock(id)) return CELL_OK; + + if (counter++ > max_counter) + { + if (!timeout) + { + sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d): TIMEOUT", rw_lock_id); + counter = 0; + } + else + { + return CELL_ETIMEDOUT; + } + } + } while (true); } int sys_rwlock_tryrlock(u32 rw_lock_id) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id); + sys_rwlock.Warning("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + + if (!rw->rlock_trylock(GetCurrentPPUThread().GetId())) return CELL_EBUSY; + return CELL_OK; } int sys_rwlock_runlock(u32 rw_lock_id) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id); + sys_rwlock.Warning("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + + if (!rw->rlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM; + return CELL_OK; } int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); - return CELL_OK; + sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); + + if (!rw->wlock_check(id)) return CELL_EDEADLK; + + if (rw->wlock_trylock(id, true)) return CELL_OK; + + u32 counter = 0; + const u32 max_counter = timeout ? (timeout / 1000) : 20000; + do + { + if (Emu.IsStopped()) return CELL_ETIMEDOUT; + Sleep(1); + + if (rw->wlock_trylock(id, true)) return CELL_OK; + + if (counter++ > max_counter) + { + if (!timeout) + { + sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d): TIMEOUT", rw_lock_id); + counter = 0; + } + else + { + return CELL_ETIMEDOUT; + } + } + } while (true); } int sys_rwlock_trywlock(u32 rw_lock_id) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id); + sys_rwlock.Warning("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); + + if (!rw->wlock_check(id)) return CELL_EDEADLK; + + if (!rw->wlock_trylock(id, false)) return CELL_EBUSY; + return CELL_OK; } int sys_rwlock_wunlock(u32 rw_lock_id) { - sys_rwlock.Warning("Unimplemented function: sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id); + sys_rwlock.Warning("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id); + + RWLock* rw; + if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; + + if (!rw->wlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM; + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h index d986b59a98..c63782ef09 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h @@ -2,11 +2,153 @@ struct sys_rwlock_attribute_t { - u32 attr_protocol; //sys_protocol_t - u32 attr_pshared; //sys_process_shared_t - u64 key; //sys_ipc_key_t - s32 flags; - u8 name[8]; + be_t attr_protocol; + be_t attr_pshared; // == 0x200 (NOT SHARED) + be_t key; // process-shared key (not used) + be_t flags; // process-shared flags (not used) + be_t pad; + char name[8]; }; -#pragma pack() \ No newline at end of file +#pragma pack() + +struct RWLock +{ + std::mutex m_lock; // internal lock + u32 wlock_thread; // write lock owner + Array wlock_queue; // write lock queue + Array rlock_list; // read lock list + u32 m_protocol; // TODO + + u32 m_pshared; // not used + u64 m_key; // not used + s32 m_flags; // not used + union + { + u64 m_name_data; // not used + char m_name[8]; + }; + + RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name) + : m_protocol(protocol) + , m_pshared(pshared) + , m_key(key) + , m_flags(flags) + , m_name_data(name) + , wlock_thread(0) + { + } + + bool rlock_trylock(u32 id) + { + std::lock_guard lock(m_lock); + + if (!wlock_thread && !wlock_queue.GetCount()) + { + rlock_list.AddCpy(id); + return true; + } + return false; + } + + bool rlock_unlock(u32 id) + { + std::lock_guard lock(m_lock); + + for (u32 i = rlock_list.GetCount() - 1; ~i; i--) + { + if (rlock_list[i] == id) + { + rlock_list.RemoveAt(i); + return true; + } + } + return false; + } + + bool wlock_check(u32 id) + { + std::lock_guard lock(m_lock); + + if (wlock_thread == id) + { + return false; // deadlock + } + for (u32 i = rlock_list.GetCount() - 1; ~i; i--) + { + if (rlock_list[i] == id) + { + return false; // deadlock + } + } + return true; + } + + bool wlock_trylock(u32 id, bool enqueue) + { + std::lock_guard lock(m_lock); + + if (wlock_thread || rlock_list.GetCount()) // already locked + { + if (!enqueue) + { + return false; // do not enqueue + } + for (u32 i = wlock_queue.GetCount() - 1; ~i; i--) + { + if (wlock_queue[i] == id) + { + return false; // already enqueued + } + } + wlock_queue.AddCpy(id); // enqueue new thread + return false; + } + else + { + if (wlock_queue.GetCount()) + { + // SYNC_FIFO only yet + if (wlock_queue[0] == id) + { + wlock_thread = id; + wlock_queue.RemoveAt(0); + return true; + } + else + { + if (!enqueue) + { + return false; // do not enqueue + } + for (u32 i = wlock_queue.GetCount() - 1; ~i; i--) + { + if (wlock_queue[i] == id) + { + return false; // already enqueued + } + } + wlock_queue.AddCpy(id); // enqueue new thread + return false; + } + } + else + { + wlock_thread = id; // easy way + return true; + } + } + } + + bool wlock_unlock(u32 id) + { + std::lock_guard lock(m_lock); + + if (wlock_thread == id) + { + wlock_thread = 0; + return true; + } + return false; + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index f79ce5cf7b..341e36fcaa 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -15,7 +15,7 @@ struct SpuGroupInfo { CPUThread* threads[g_spu_group_thr_count]; sys_spu_thread_group_attribute& attr; - volatile long lock; + std::atomic lock; SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr), lock(0) { @@ -259,7 +259,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) return CELL_ESRCH; } - if (_InterlockedCompareExchange(&group_info->lock, 1, 0)) //get lock + if (group_info->lock.exchange(1)) //get lock { return CELL_EBUSY; } @@ -275,7 +275,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) } } - _InterlockedExchange(&group_info->lock, 0); //release lock + group_info->lock = 0; //release lock return CELL_OK; } diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 5f76f44462..e8e50cafc2 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -249,6 +249,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 65591d896f..45dd7d3051 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -370,6 +370,9 @@ Emu\SysCalls\Modules + + Emu\SysCalls\lv2 + From 6efe751d4c186675cca019794d256de56a17e835 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 31 Jan 2014 03:40:05 +0400 Subject: [PATCH 2/5] Bugs fixed, lwcond implementation Modules: mutex added --- rpcs3/Emu/SysCalls/Modules.cpp | 30 ++++-- rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp | 58 +++++++++++- rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h | 98 +++++++++++++++++++- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 126 ++++---------------------- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h | 86 +++++++++++++++++- rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp | 25 +++-- rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h | 34 +++---- 7 files changed, 301 insertions(+), 156 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index b31c396a9a..4d02cd0dc9 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -1,11 +1,13 @@ #include "stdafx.h" #include "SysCalls.h" #include "SC_FUNC.h" +#include Module* g_modules[3][0xff] = {0}; uint g_max_module_id = 0; uint g_module_2_count = 0; ArrayF g_modules_funcs_list; +std::mutex g_funcs_lock; struct ModuleInfo { @@ -142,20 +144,31 @@ bool IsLoadedFunc(u32 id) bool CallFunc(u32 num) { - for(u32 i=0; i lock(g_funcs_lock); + + for(u32 i=0; i lock(g_funcs_lock); + for(u32 i=0; i lock(g_funcs_lock); g_modules_funcs_list.Clear(); } @@ -318,8 +332,10 @@ void Module::Load() for(u32 i=0; i lock(g_funcs_lock); + if(IsLoadedFunc(m_funcs_list[i].id)) continue; + g_modules_funcs_list.Add(m_funcs_list[i]); } @@ -343,6 +359,8 @@ void Module::UnLoad() bool Module::Load(u32 id) { + std::lock_guard lock(g_funcs_lock); + if(IsLoadedFunc(id)) return false; for(u32 i=0; i lwcond, mem_ptr_t l if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; - lwcond->lwmutex_addr = lwmutex.GetAddr(); - lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(*(u64*)&attr->name)); + u32 protocol = (u32)lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK; + switch (protocol) + { + case SYS_SYNC_PRIORITY: break; + case SYS_SYNC_RETRY: sys_lwcond.Error("Invalid SYS_SYNC_RETRY attr"); break; + case SYS_SYNC_PRIORITY_INHERIT: sys_lwcond.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; + case SYS_SYNC_FIFO: break; + default: sys_lwcond.Error("Invalid lwmutex protocol(%d)", protocol); break; + } - sys_lwcond.Warning("*** lwcond created [%s]", attr->name); + lwcond->lwmutex_addr = lwmutex.GetAddr(); + lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(protocol, *(u64*)&attr->name)); + + sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x)", attr->name, protocol); return CELL_OK; } @@ -41,6 +51,8 @@ int sys_lwcond_signal(mem_ptr_t lwcond) u32 id = (u32)lwcond->lwcond_queue; if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + lwc->signal(); + return CELL_OK; } @@ -53,6 +65,8 @@ int sys_lwcond_signal_all(mem_ptr_t lwcond) u32 id = (u32)lwcond->lwcond_queue; if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + lwc->signal_all(); + return CELL_OK; } @@ -65,6 +79,8 @@ int sys_lwcond_signal_to(mem_ptr_t lwcond, u32 ppu_thread_id) u32 id = (u32)lwcond->lwcond_queue; if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + if (!lwc->signal_to(ppu_thread_id)) return CELL_EPERM; + return CELL_OK; } @@ -76,6 +92,40 @@ int sys_lwcond_wait(mem_ptr_t lwcond, u64 timeout) LWCond* lwc; u32 id = (u32)lwcond->lwcond_queue; if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH; + const u32 tid = GetCurrentPPUThread().GetId(); + mem_ptr_t lwmutex((u32)lwcond->lwmutex_addr); - return CELL_OK; + if ((u32)lwmutex->owner != tid) return CELL_EPERM; // caller must own this lwmutex + lwc->begin_waiting(tid); + + u32 counter = 0; + const u32 max_counter = timeout ? (timeout / 1000) : 20000; + bool was_locked = true; + do + { + if (Emu.IsStopped()) return CELL_ETIMEDOUT; + if (was_locked) lwmutex->unlock(tid); + Sleep(1); + if (was_locked = (lwmutex->trylock(tid) == CELL_OK)) + { + if (lwc->check(tid)) + { + return CELL_OK; + } + } + + if (counter++ > max_counter) + { + if (!timeout) + { + sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x): TIMEOUT", lwcond.GetAddr()); + counter = 0; + } + else + { + lwc->stop_waiting(tid); + return CELL_ETIMEDOUT; + } + } + } while (true); } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h index 30eab02f61..c72347e3b3 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h @@ -15,10 +15,104 @@ struct sys_lwcond_t struct LWCond { - u64 m_name; + std::mutex m_lock; + Array waiters; // list of waiting threads + Array signaled; // list of signaled threads + u32 m_protocol; // protocol + u64 m_name; // not used - LWCond(u64 name) + LWCond(u32 prot, u64 name) : m_name(name) + , m_protocol(prot) { } + + void signal() + { + std::lock_guard lock(m_lock); + + if (waiters.GetCount()) + { + if (m_protocol == SYS_SYNC_PRIORITY) + { + u64 max_prio = 0; + u32 sel = 0; + for (u32 i = 0; i < waiters.GetCount(); i++) + { + CPUThread* t = Emu.GetCPU().GetThread(waiters[i]); + if (!t) continue; + + u64 prio = t->GetPrio(); + if (prio > max_prio) + { + max_prio = prio; + sel = i; + } + } + signaled.AddCpy(waiters[sel]); + waiters.RemoveAt(sel); + } + else // SYS_SYNC_FIFO + { + signaled.AddCpy(waiters[0]); + waiters.RemoveAt(0); + } + } + } + + void signal_all() + { + std::lock_guard lock(m_lock); + + signaled.AppendFrom(waiters); // "nobody cares" protocol (!) + waiters.Clear(); + } + + bool signal_to(u32 id) // returns false if not found + { + std::lock_guard lock(m_lock); + for (u32 i = waiters.GetCount() - 1; ~i; i--) + { + if (waiters[i] == id) + { + waiters.RemoveAt(i); + signaled.AddCpy(id); + return true; + } + } + return false; + } + + void begin_waiting(u32 id) + { + std::lock_guard lock(m_lock); + waiters.AddCpy(id); + } + + void stop_waiting(u32 id) + { + std::lock_guard lock(m_lock); + for (u32 i = waiters.GetCount() - 1; ~i; i--) + { + if (waiters[i] == id) + { + waiters.RemoveAt(i); + break; + } + } + } + + bool check(u32 id) // returns true if signaled + { + std::lock_guard lock(m_lock); + for (u32 i = signaled.GetCount() - 1; ~i; i--) + { + if (signaled[i] == id) + { + signaled.RemoveAt(i); + return true; + } + } + return false; + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index ad313f9334..5b2dc5794c 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -9,7 +9,7 @@ std::mutex g_lwmutex; int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_t attr) { - sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)", + sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)", lwmutex.GetAddr(), attr.GetAddr()); if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; @@ -23,10 +23,10 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_tattr_protocol) { - case SYS_SYNC_PRIORITY: sc_lwmutex.Log("TODO: SYS_SYNC_PRIORITY attr"); break; + case SYS_SYNC_PRIORITY: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY attr"); break; case SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break; case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; - case SYS_SYNC_FIFO: sc_lwmutex.Log("TODO: SYS_SYNC_FIFO attr"); break; + case SYS_SYNC_FIFO: sc_lwmutex.Warning("TODO: SYS_SYNC_FIFO attr"); break; default: return CELL_EINVAL; } @@ -36,14 +36,14 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_trecursive_count = 0; lwmutex->sleep_queue = 0; - sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute); + sc_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute); return CELL_OK; } int sys_lwmutex_destroy(mem_ptr_t lwmutex) { - sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); if (!lwmutex.IsGood()) return CELL_EFAULT; @@ -54,6 +54,7 @@ int sys_lwmutex_destroy(mem_ptr_t lwmutex) if (!lwmutex->owner) { + lwmutex->owner = ~0; // make it unable to lock lwmutex->attribute = 0; } else @@ -67,43 +68,16 @@ int sys_lwmutex_destroy(mem_ptr_t lwmutex) int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) { - sc_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout); + sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout); if (!lwmutex.IsGood()) return CELL_EFAULT; if (!lwmutex->attribute) return CELL_EINVAL; - PPCThread& thr = GetCurrentPPUThread(); - const u32 id = thr.GetId(); + const u32 tid = GetCurrentPPUThread().GetId(); - { // global lock - std::lock_guard lock(g_lwmutex); - - if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE) - { - if (id == (u32)lwmutex->owner) - { - lwmutex->recursive_count = lwmutex->recursive_count + 1; - if (lwmutex->recursive_count == 0xffffffff) return CELL_EKRESOURCE; - return CELL_OK; - } - } - else // recursive not allowed - { - if (id == (u32)lwmutex->owner) - { - return CELL_EDEADLK; - } - } - - if (!lwmutex->owner) // lock - { - lwmutex->owner = id; - lwmutex->recursive_count = 1; - return CELL_OK; - } - lwmutex->waiter = id; // not used yet - } + int res = lwmutex->trylock(tid); + if (res != CELL_EBUSY) return res; u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : 20000; @@ -112,17 +86,9 @@ int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) if (Emu.IsStopped()) return CELL_ETIMEDOUT; Sleep(1); - { // global lock - std::lock_guard lock(g_lwmutex); - - if (!lwmutex->owner) // lock - { - lwmutex->owner = id; - lwmutex->recursive_count = 1; - return CELL_OK; - } - lwmutex->waiter = id; // not used yet - } + res = lwmutex->trylock(tid); + if (res != CELL_EBUSY) return res; + if (!lwmutex->attribute) return CELL_EINVAL; if (counter++ > max_counter) { @@ -141,79 +107,23 @@ int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) int sys_lwmutex_trylock(mem_ptr_t lwmutex) { - sc_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); if (!lwmutex.IsGood()) return CELL_EFAULT; if (!lwmutex->attribute) return CELL_EINVAL; - PPCThread& thr = GetCurrentPPUThread(); - const u32 id = thr.GetId(); - - { // global lock - std::lock_guard lock(g_lwmutex); - - if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE) - { - if (id == (u32)lwmutex->owner) - { - lwmutex->recursive_count = lwmutex->recursive_count + 1; - if (lwmutex->recursive_count == 0xffffffff) return CELL_EKRESOURCE; - return CELL_OK; - } - } - else // recursive not allowed - { - if (id == (u32)lwmutex->owner) - { - return CELL_EDEADLK; - } - } - - if (!lwmutex->owner) // try lock - { - lwmutex->owner = id; - lwmutex->recursive_count = 1; - return CELL_OK; - } - else - { - return CELL_EBUSY; - } - } + return lwmutex->trylock(GetCurrentPPUThread().GetId()); } int sys_lwmutex_unlock(mem_ptr_t lwmutex) { - sc_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); if (!lwmutex.IsGood()) return CELL_EFAULT; - PPCThread& thr = GetCurrentPPUThread(); - const u32 id = thr.GetId(); + if (!lwmutex->unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM; - { // global lock - std::lock_guard lock(g_lwmutex); - - if (id != (u32)lwmutex->owner) - { - return CELL_EPERM; - } - else - { - lwmutex->recursive_count = (u32)lwmutex->recursive_count - 1; - if (!lwmutex->recursive_count) - { - lwmutex->waiter = 0; // not used yet - lwmutex->owner = 0; // release - /* CPUThread* thr = Emu.GetCPU().GetThread(lwmutex->owner); - if(thr) - { - thr->Wait(false); - } */ - } - return CELL_OK; - } - } + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h index 85f0f01fe8..1072d7eca5 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -5,7 +5,7 @@ enum { // First In, First Out SYS_SYNC_FIFO = 1, - // Priority Order (doesn't care?) + // Priority Order SYS_SYNC_PRIORITY = 2, // Basic Priority Inheritance Protocol SYS_SYNC_PRIORITY_INHERIT = 3, @@ -26,6 +26,15 @@ enum SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //??? }; +struct sys_lwmutex_attribute_t +{ + be_t attr_protocol; + be_t attr_recursive; + char name[8]; +}; + +extern std::mutex g_lwmutex; + struct sys_lwmutex_t { union // sys_lwmutex_variable_t @@ -44,11 +53,78 @@ struct sys_lwmutex_t be_t recursive_count; be_t sleep_queue; be_t pad; + + int trylock(u32 tid) + { + std::lock_guard lock(g_lwmutex); // global lock + + if ((u32)attribute & SYS_SYNC_RECURSIVE) + { + if (tid == (u32)owner) + { + recursive_count = (u32)recursive_count + 1; + if ((u32)recursive_count == 0xffffffff) return CELL_EKRESOURCE; + return CELL_OK; + } + } + else // recursive not allowed + { + if (tid == (u32)owner) + { + return CELL_EDEADLK; + } + } + + if (!(u32)owner) // try lock + { + owner = tid; + recursive_count = 1; + return CELL_OK; + } + else + { + return CELL_EBUSY; + } + } + + bool unlock(u32 tid) + { + std::lock_guard lock(g_lwmutex); // global lock + + if (tid != (u32)owner) + { + return false; + } + else + { + recursive_count = (u32)recursive_count - 1; + if (!(u32)recursive_count) + { + waiter = 0; // not used yet + owner = 0; // release + } + return true; + } + } }; -struct sys_lwmutex_attribute_t +struct lwmutex_locker { - be_t attr_protocol; - be_t attr_recursive; - char name[8]; +private: + mem_ptr_t m_mutex; + u32 m_id; +public: + const int res; + + lwmutex_locker(u32 lwmutex_addr, u32 tid) + : m_id(tid) + , m_mutex(lwmutex_addr) + , res(m_mutex->trylock(m_id)) + { + } + + ~lwmutex_locker() + { + if (res == CELL_OK) m_mutex->unlock(m_id); + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp index 1cadd83e07..5c9b963923 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp @@ -12,7 +12,7 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr switch ((u32)attr->attr_protocol) { - case SYS_SYNC_PRIORITY: sys_rwlock.Log("TODO: SYS_SYNC_PRIORITY attr"); break; + case SYS_SYNC_PRIORITY: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY attr"); break; case SYS_SYNC_RETRY: sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break; case SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; case SYS_SYNC_FIFO: break; @@ -55,10 +55,9 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) RWLock* rw; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; - PPCThread& thr = GetCurrentPPUThread(); - const u32 id = thr.GetId(); + const u32 tid = GetCurrentPPUThread().GetId(); - if (rw->rlock_trylock(id)) return CELL_OK; + if (rw->rlock_trylock(tid)) return CELL_OK; u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : 20000; @@ -67,7 +66,7 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) if (Emu.IsStopped()) return CELL_ETIMEDOUT; Sleep(1); - if (rw->rlock_trylock(id)) return CELL_OK; + if (rw->rlock_trylock(tid)) return CELL_OK; if (counter++ > max_counter) { @@ -114,12 +113,11 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) RWLock* rw; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; - PPCThread& thr = GetCurrentPPUThread(); - const u32 id = thr.GetId(); + const u32 tid = GetCurrentPPUThread().GetId(); - if (!rw->wlock_check(id)) return CELL_EDEADLK; + if (!rw->wlock_check(tid)) return CELL_EDEADLK; - if (rw->wlock_trylock(id, true)) return CELL_OK; + if (rw->wlock_trylock(tid, true)) return CELL_OK; u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : 20000; @@ -128,7 +126,7 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout) if (Emu.IsStopped()) return CELL_ETIMEDOUT; Sleep(1); - if (rw->wlock_trylock(id, true)) return CELL_OK; + if (rw->wlock_trylock(tid, true)) return CELL_OK; if (counter++ > max_counter) { @@ -151,12 +149,11 @@ int sys_rwlock_trywlock(u32 rw_lock_id) RWLock* rw; if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH; - PPCThread& thr = GetCurrentPPUThread(); - const u32 id = thr.GetId(); + const u32 tid = GetCurrentPPUThread().GetId(); - if (!rw->wlock_check(id)) return CELL_EDEADLK; + if (!rw->wlock_check(tid)) return CELL_EDEADLK; - if (!rw->wlock_trylock(id, false)) return CELL_EBUSY; + if (!rw->wlock_trylock(tid, false)) return CELL_EBUSY; return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h index c63782ef09..720f137db7 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.h @@ -39,25 +39,25 @@ struct RWLock { } - bool rlock_trylock(u32 id) + bool rlock_trylock(u32 tid) { std::lock_guard lock(m_lock); if (!wlock_thread && !wlock_queue.GetCount()) { - rlock_list.AddCpy(id); + rlock_list.AddCpy(tid); return true; } return false; } - bool rlock_unlock(u32 id) + bool rlock_unlock(u32 tid) { std::lock_guard lock(m_lock); for (u32 i = rlock_list.GetCount() - 1; ~i; i--) { - if (rlock_list[i] == id) + if (rlock_list[i] == tid) { rlock_list.RemoveAt(i); return true; @@ -66,17 +66,17 @@ struct RWLock return false; } - bool wlock_check(u32 id) + bool wlock_check(u32 tid) { std::lock_guard lock(m_lock); - if (wlock_thread == id) + if (wlock_thread == tid) { return false; // deadlock } for (u32 i = rlock_list.GetCount() - 1; ~i; i--) { - if (rlock_list[i] == id) + if (rlock_list[i] == tid) { return false; // deadlock } @@ -84,7 +84,7 @@ struct RWLock return true; } - bool wlock_trylock(u32 id, bool enqueue) + bool wlock_trylock(u32 tid, bool enqueue) { std::lock_guard lock(m_lock); @@ -96,12 +96,12 @@ struct RWLock } for (u32 i = wlock_queue.GetCount() - 1; ~i; i--) { - if (wlock_queue[i] == id) + if (wlock_queue[i] == tid) { return false; // already enqueued } } - wlock_queue.AddCpy(id); // enqueue new thread + wlock_queue.AddCpy(tid); // enqueue new thread return false; } else @@ -109,9 +109,9 @@ struct RWLock if (wlock_queue.GetCount()) { // SYNC_FIFO only yet - if (wlock_queue[0] == id) + if (wlock_queue[0] == tid) { - wlock_thread = id; + wlock_thread = tid; wlock_queue.RemoveAt(0); return true; } @@ -123,28 +123,28 @@ struct RWLock } for (u32 i = wlock_queue.GetCount() - 1; ~i; i--) { - if (wlock_queue[i] == id) + if (wlock_queue[i] == tid) { return false; // already enqueued } } - wlock_queue.AddCpy(id); // enqueue new thread + wlock_queue.AddCpy(tid); // enqueue new thread return false; } } else { - wlock_thread = id; // easy way + wlock_thread = tid; // easy way return true; } } } - bool wlock_unlock(u32 id) + bool wlock_unlock(u32 tid) { std::lock_guard lock(m_lock); - if (wlock_thread == id) + if (wlock_thread == tid) { wlock_thread = 0; return true; From 432c6cf206f9acfda01fd0660dad480e4a526876 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 31 Jan 2014 16:46:49 +0400 Subject: [PATCH 3/5] Small changes SC_FUNC changes (done by DH) PPUInterpreter changes (copied from main, done by elisha464) Log() using fixed --- rpcs3/Emu/Cell/PPUInterpreter.h | 18 +++++++----- rpcs3/Emu/SysCalls/SC_FUNC.h | 37 +++++++++++++++++++----- rpcs3/Emu/SysCalls/SysCalls.h | 4 +++ rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp | 1 + rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 1 + 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 0aa510981c..5bda4613de 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -1209,11 +1209,15 @@ private: } void VPERM(u32 vd, u32 va, u32 vb, u32 vc) { + u8 tmpSRC[32]; + memcpy(tmpSRC, CPU.VPR[vb]._u8, 16); + memcpy(tmpSRC + 16, CPU.VPR[va]._u8, 16); + for (uint b = 0; b < 16; b++) { u8 index = CPU.VPR[vc]._u8[b] & 0x1f; - CPU.VPR[vd]._u8[b] = index < 0x10 ? CPU.VPR[va]._u8[0xf - index] : CPU.VPR[vb]._u8[0xf - (index - 0x10)]; + CPU.VPR[vd]._u8[b] = tmpSRC[0x1f - index]; } } void VPKPX(u32 vd, u32 va, u32 vb) @@ -1552,13 +1556,13 @@ private: } void VSLDOI(u32 vd, u32 va, u32 vb, u32 sh) { - for (uint b = 0; b < 16 - sh; b++) + u8 tmpSRC[32]; + memcpy(tmpSRC, CPU.VPR[vb]._u8, 16); + memcpy(tmpSRC + 16, CPU.VPR[va]._u8, 16); + + for(uint b=0; b<16; b++) { - CPU.VPR[vd]._u8[15 - b] = CPU.VPR[va]._u8[15 - (b + sh)]; - } - for (uint b = 16 - sh; b < 16; b++) - { - CPU.VPR[vd]._u8[15 - b] = CPU.VPR[vb]._u8[15 - (b - (16 - sh))]; + CPU.VPR[vd]._u8[15 - b] = tmpSRC[31 - (b + sh)]; } } void VSLH(u32 vd, u32 va, u32 vb) diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index 832e0bf2b4..0157a8bf2f 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -2,19 +2,40 @@ #define RESULT(x) SC_ARGS_1 = (x) -template +template struct get_arg; -template -struct get_arg { static __forceinline T func(PPUThread& CPU, int i) { return (T&)CPU.GPR[i + 2]; } }; +template +struct get_arg // not fp, not ptr, 1..8 +{ + static __forceinline T func(PPUThread& CPU) { return (T&)CPU.GPR[i + 2]; } +}; -template -struct get_arg { static __forceinline T func(PPUThread& CPU, int i) { return CPU.GPR[i + 2] ? (T)&Memory[CPU.GPR[i + 2]] : nullptr; } }; +template +struct get_arg // ptr, 1..8 +{ + static __forceinline T func(PPUThread& CPU) { return CPU.GPR[i + 2] ? (T)&Memory[CPU.GPR[i + 2]] : nullptr; } +}; -template -struct get_arg { static __forceinline T func(PPUThread& CPU, int i) { return CPU.FPR[i]; } }; +template +struct get_arg // fp, 1..12 +{ + static __forceinline T func(PPUThread& CPU) { return CPU.FPR[i]; } +}; -#define ARG(n) get_arg::value, std::is_pointer::value, T##n>::func(CPU, n) +template +struct get_arg // not fp, not ptr, 9..12 +{ + static __forceinline T func(PPUThread& CPU) { u64 res = Memory.Read64(CPU.GPR[1] + 0x70 + 0x8 * (i - 9)); return (T&)res; } +}; + +template +struct get_arg // ptr, 9..12 +{ + static __forceinline T func(PPUThread& CPU) { u64 addr = Memory.Read64(CPU.GPR[1] + 0x70 + 0x8 * (i - 9)); return addr ? (T)&Memory[addr] : nullptr; } +}; + +#define ARG(n) get_arg<((n) > 8), std::is_floating_point::value, std::is_pointer::value, T##n, n>::func(CPU) template class binder_func_0 : public func_caller diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 7c18cb6df0..56acf61882 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -376,10 +376,12 @@ extern int sys_rsx_attribute(); #define SC_ARG_5 CPU.GPR[8] #define SC_ARG_6 CPU.GPR[9] #define SC_ARG_7 CPU.GPR[10] +/* // these definitions are wrong: #define SC_ARG_8 CPU.GPR[11] #define SC_ARG_9 CPU.GPR[12] #define SC_ARG_10 CPU.GPR[13] #define SC_ARG_11 CPU.GPR[14] +*/ #define SC_ARGS_1 SC_ARG_0 #define SC_ARGS_2 SC_ARGS_1,SC_ARG_1 @@ -389,10 +391,12 @@ extern int sys_rsx_attribute(); #define SC_ARGS_6 SC_ARGS_5,SC_ARG_5 #define SC_ARGS_7 SC_ARGS_6,SC_ARG_6 #define SC_ARGS_8 SC_ARGS_7,SC_ARG_7 +/* #define SC_ARGS_9 SC_ARGS_8,SC_ARG_8 #define SC_ARGS_10 SC_ARGS_9,SC_ARG_9 #define SC_ARGS_11 SC_ARGS_10,SC_ARG_10 #define SC_ARGS_12 SC_ARGS_11,SC_ARG_11 +*/ extern bool dump_enable; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index f1674f6ab4..86f24d65dd 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -162,6 +162,7 @@ int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) int sys_memory_get_user_memory_size(u32 mem_info_addr) { + sc_mem.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info_addr); sys_memory_info info; info.total_user_memory = re(Memory.GetUserMemTotalSize()); info.available_user_memory = re(Memory.GetUserMemAvailSize()); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index 4ef5ffa01b..c70d43838d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -74,7 +74,7 @@ int cellPadClearBuf(u32 port_no) int cellPadGetData(u32 port_no, u32 data_addr) { - //ConLog.Warning("cellPadGetData[port_no: %d, data_addr: 0x%x]", port_no, data_addr); + sys_io.Log("cellPadGetData[port_no: %d, data_addr: 0x%x]", port_no, data_addr); const Array& pads = Emu.GetPadManager().GetPads(); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if(port_no >= pads.GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 341e36fcaa..52e6c7cc38 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -458,6 +458,7 @@ int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value) //184 int sys_spu_thread_write_snr(u32 id, u32 number, u32 value) { + sc_spu.Log("sys_spu_thread_write_snr(id=0x%x, number=%d, value=0x%x)", id, number, value); CPUThread* thr = Emu.GetCPU().GetThread(id); if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) From 67601bd639eba8e75db9b85da31fd357008dacdd Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 1 Feb 2014 01:35:48 +0400 Subject: [PATCH 4/5] Small changes --- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 9 +- rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp | 3 +- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 104 +++++++++++++---------- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h | 3 +- 6 files changed, 69 insertions(+), 54 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index e76e9069de..452f6b1724 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -81,6 +81,10 @@ int cellSyncMutexLock(mem_ptr_t mutex) std::lock_guard lock(g_SyncMutex); old_order = mutex->m_order; mutex->m_order = mutex->m_order + 1; + if (old_order == mutex->m_freed) + { + return CELL_OK; + } } int counter = 0; @@ -89,10 +93,9 @@ int cellSyncMutexLock(mem_ptr_t mutex) Sleep(1); if (++counter >= 5000) { - Emu.Pause(); - cellSync.Error("cellSyncMutexLock(mutex=0x%x, old_order=%d, order=%d, freed=%d): TIMEOUT", + counter = 0; + cellSync.Warning("cellSyncMutexLock(mutex=0x%x, old_order=%d, order=%d, freed=%d): TIMEOUT", mutex.GetAddr(), (u16)old_order, (u16)mutex->m_order, (u16)mutex->m_freed); - break; } } //while (_InterlockedExchange((volatile long*)&mutex->m_data, 1)) Sleep(1); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp index 7c17f368ab..2c2cb84322 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp @@ -25,7 +25,7 @@ int sys_lwcond_create(mem_ptr_t lwcond, mem_ptr_t l lwcond->lwmutex_addr = lwmutex.GetAddr(); lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(protocol, *(u64*)&attr->name)); - sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x)", attr->name, protocol); + sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x): id=%d", attr->name, protocol, (u32)lwcond->lwcond_queue); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 5b2dc5794c..77a4e93d99 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -36,7 +36,7 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_trecursive_count = 0; lwmutex->sleep_queue = 0; - sc_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute); + sc_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): id=???", attr->name, (u32)lwmutex->attribute); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp index 5c9b963923..d4f6ecae7a 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Rwlock.cpp @@ -28,7 +28,8 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t attr rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared, (u64)attr->key, (s32)attr->flags, *(u64*)&attr->name)); - sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x)", attr->name, (u32)attr->attr_protocol); + sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d", + attr->name, (u32)attr->attr_protocol, rw_lock_id.GetValue()); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 52e6c7cc38..c45680cb8c 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -9,17 +9,29 @@ static SysCallBase sc_spu("sys_spu"); extern SysCallBase sys_event; -static const u32 g_spu_group_thr_count = 255; +static const u32 g_spu_group_thr_max = 255; struct SpuGroupInfo { - CPUThread* threads[g_spu_group_thr_count]; - sys_spu_thread_group_attribute& attr; + Array list; std::atomic lock; + wxString m_name; + int m_prio; + int m_type; + int m_ct; - SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr), lock(0) + SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct) + : m_name(name) + , m_prio(prio) + , m_type(type) + , m_ct(ct) + , lock(0) { - memset(threads, 0, sizeof(CPUThread*) * g_spu_group_thr_count); + list.SetCount(num); + for (u32 i = 0; i < num; i++) + { + list[i] = 0; + } } }; @@ -102,12 +114,12 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< return CELL_EFAULT; } - if(spu_num >= g_spu_group_thr_count) + if(spu_num >= g_spu_group_thr_max) { return CELL_EINVAL; } - if(group_info->threads[spu_num]) + if(group_info->list[spu_num]) { return CELL_EBUSY; } @@ -133,20 +145,10 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< new_thread.SetArg(3, a4); new_thread.Run(); - thread = new_thread.GetId(); + thread = group_info->list[spu_num] = new_thread.GetId(); - group_info->threads[spu_num] = &new_thread; - - /*ConLog.Write("New SPU Thread:"); - ConLog.Write("SPU img offset = 0x%x", (u32)img->segs_addr); - ConLog.Write("entry_point = 0x%x", spu_ep); - ConLog.Write("name = %s", name.c_str()); - ConLog.Write("a1 = 0x%x", a1); - ConLog.Write("a2 = 0x%x", a2); - ConLog.Write("a3 = 0x%x", a3); - ConLog.Write("a4 = 0x%x", a4); - ConLog.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset); - ConLog.SkipLn();*/ + sc_spu.Warning("*** New SPU Thread [%s] (img_offset=0x%x, ls_offset=0x%x, ep=0x%x, a1=0x%llx, a2=0x%llx, a3=0x%llx, a4=0x%llx): id=%d", + name.c_str(), (u32)img->segs_addr, ((SPUThread&)new_thread).dmac.ls_offset, spu_ep, a1, a2, a3, a4, thread.GetValue()); return CELL_OK; } @@ -192,11 +194,12 @@ int sys_spu_thread_group_start(u32 id) } //Emu.Pause(); - for(int i=0; ilist.GetCount(); i++) { - if(group_info->threads[i]) + CPUThread* t; + if (t = Emu.GetCPU().GetThread(group_info->list[i])) { - group_info->threads[i]->Exec(); + t->Exec(); } } @@ -215,11 +218,12 @@ int sys_spu_thread_group_suspend(u32 id) } //Emu.Pause(); - for(int i=0; ilist.GetCount(); i++) { - if(group_info->threads[i]) + CPUThread* t; + if (t = Emu.GetCPU().GetThread(group_info->list[i])) { - group_info->threads[i]->Pause(); + t->Pause(); } } @@ -229,21 +233,23 @@ int sys_spu_thread_group_suspend(u32 id) //170 int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t attr) { - ConLog.Write("sys_spu_thread_group_create:"); - ConLog.Write("*** id_addr=0x%x", id.GetAddr()); - ConLog.Write("*** num=%d", num); - ConLog.Write("*** prio=%d", prio); - ConLog.Write("*** attr_addr=0x%x", attr.GetAddr()); + sc_spu.Warning("sys_spu_thread_group_create(id_addr=0x%x, num=%d, prio=%d, attr_addr=0x%x)", + id.GetAddr(), num, prio, attr.GetAddr()); - ConLog.Write("*** attr.name_len=%d", attr->name_len.ToLE()); - ConLog.Write("*** attr.name_addr=0x%x", attr->name_addr.ToLE()); - ConLog.Write("*** attr.type=%d", attr->type.ToLE()); - ConLog.Write("*** attr.option.ct=%d", attr->option.ct.ToLE()); + if (!id.IsGood() || !attr.IsGood()) return CELL_EFAULT; - const wxString name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); - ConLog.Write("*** name='%s'", name.c_str()); + if (!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) return CELL_EFAULT; - id = Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group '%s'", name), new SpuGroupInfo(*attr)); + if (num > g_spu_group_thr_max) return CELL_EINVAL; + + if (prio < 16 || prio > 255) return CELL_EINVAL; + + const wxString name = Memory.ReadString(attr->name_addr, attr->name_len); + + id = sc_spu.GetNewId(new SpuGroupInfo(name, num, prio, attr->type, attr->ct)); + + sc_spu.Warning("*** SPU Thread Group created [%s] (type=%d, option.ct=%d): id=%d", + name.c_str(), (int)attr->type, (u32)attr->ct, id.GetValue()); return CELL_OK; } @@ -259,7 +265,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) return CELL_ESRCH; } - if (group_info->lock.exchange(1)) //get lock + if (group_info->lock.exchange(1)) // acquire lock { return CELL_EBUSY; } @@ -267,21 +273,24 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT; status = 0; //unspecified because of ALL_THREADS_EXIT - for(int i=0; ilist.GetCount(); i++) { - if(group_info->threads[i]) + while (Emu.GetCPU().GetThread(group_info->list[i])) { - while (!group_info->threads[i]->IsStopped()) Sleep(1); + Sleep(1); + if (Emu.IsStopped()) return CELL_OK; } + group_info->list[i] = 0; } - group_info->lock = 0; //release lock + group_info->lock = 0; // release lock return CELL_OK; } int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr) { - UNIMPLEMENTED_FUNC(sc_spu); + sc_spu.Error("sys_spu_thread_create(thread_id_addr=0x%x, entry_addr=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x", + thread_id.GetAddr(), entry.GetAddr(), arg, prio, stacksize, flags, threadname_addr); return CELL_OK; } @@ -505,9 +514,10 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 return CELL_ESRCH; } - for(int i=0; ilist.GetCount(); ++i) { - if(group->threads[i]) + CPUThread* t; + if(t = Emu.GetCPU().GetThread(group->list[i])) { bool finded_port = false; for(int j=0; jpos; ++j) @@ -515,7 +525,7 @@ int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 if(!equeue->ports[j]->thread) { finded_port = true; - equeue->ports[j]->thread = group->threads[i]; + equeue->ports[j]->thread = t; } } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h index acac792dc8..7d674155e4 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h @@ -21,7 +21,8 @@ struct sys_spu_thread_group_attribute be_t name_len; be_t name_addr; be_t type; - struct{be_t ct;} option; + /* struct {} option; */ + be_t ct; // memory container id }; struct sys_spu_thread_attribute From 9919154d666952688846e9d5ea73d2e9c0f89cf2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 1 Feb 2014 02:07:37 +0400 Subject: [PATCH 5/5] Afterfix --- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 1f48bbe323..7b1b65c290 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -457,7 +457,7 @@ int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 as int cellSysutilCheckCallback() { - cellSysutil.Warning("cellSysutilCheckCallback()"); + cellSysutil.Log("cellSysutilCheckCallback()"); Emu.GetCallbackManager().m_exit_callback.Check(); return CELL_OK; @@ -667,7 +667,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option) switch(audioOut) { - case CELL_AUDIO_OUT_PRIMARY: return 1; + case CELL_AUDIO_OUT_PRIMARY: return 2; case CELL_AUDIO_OUT_SECONDARY: return 0; }