diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 1326c33770..149076149d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -35,11 +35,11 @@ int cellDmuxOpenEx(mem_ptr_t demuxerType, mem_ptr_t demuxerType2, u32 demuxerResource2_addr, +int cellDmuxOpen2(mem_ptr_t demuxerType2, mem_ptr_t demuxerResource2, mem_ptr_t demuxerCb, u32 demuxerHandle_addr) { cellDmux.Error("cellDmuxOpen2(demuxerType2_addr=0x%x, demuxerResource2_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", - demuxerType2.GetAddr(), demuxerResource2_addr, demuxerCb.GetAddr(), demuxerHandle_addr); + demuxerType2.GetAddr(), demuxerResource2.GetAddr(), demuxerCb.GetAddr(), demuxerHandle_addr); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index a42bfbdcc2..7560980382 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -75,6 +75,7 @@ struct CellDmuxResourceEx be_t maxContention; }; +/* struct CellDmuxResource2Ex { bool isResourceEx; //true @@ -86,18 +87,42 @@ struct CellDmuxResource2NoEx bool isResourceEx; //false CellDmuxResource resource; }; +*/ + +struct CellDmuxResource2 +{ + bool isResourceEx; + be_t memAddr; + be_t memSize; + be_t ppuThreadPriority; + be_t ppuThreadStackSize; + union + { + struct + { + be_t spuThreadPriority; + be_t numOfSpus; + }; + struct + { + be_t ex_spurs_addr; + u8 ex_priority[8]; + be_t ex_maxContention; + }; + }; +}; struct CellDmuxCb { // CellDmuxCbMsg callback - mem_func_ptr_t demuxerMsg, u32 cbArg_addr)> cbMsgFunc; + be_t demuxerMsg, u32 cbArg_addr)>> cbMsgFunc; be_t cbArg_addr; }; struct CellDmuxEsCb { // CellDmuxCbEsMsg callback - mem_func_ptr_t esMsg, u32 cbArg_addr)> cbEsMsgFunc; + be_t esMsg, u32 cbArg_addr)>> cbEsMsgFunc; be_t cbArg_addr; }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index b602352289..1e33d4d572 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -122,7 +122,7 @@ int cellPamfGetHeaderSize(mem_ptr_t pAddr, u64 fileSize, mem64_t pSi //return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; - pSize = offset ? offset : 2048; //hack + pSize = offset /*? offset : 2048*/; //hack return CELL_OK; } @@ -139,7 +139,7 @@ int cellPamfGetHeaderSize2(mem_ptr_t pAddr, u64 fileSize, u32 attrib return CELL_OK; } -u32 hack_LastHeader = 0; +//u32 hack_LastHeader = 0; int cellPamfGetStreamOffsetAndSize(mem_ptr_t pAddr, u64 fileSize, mem64_t pOffset, mem64_t pSize) { @@ -150,10 +150,10 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t pAddr, u64 fileSize, me //return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; - pOffset = offset ? offset : 2048; //hack + pOffset = offset /*? offset : 2048*/; //hack const u64 size = (u64)pAddr->data_size << 11; - pSize = size ? size : (fileSize - 2048); //hack - if (!(u32)pAddr->magic) hack_LastHeader = pAddr.GetAddr(); + pSize = size /*? size : (fileSize - 2048)*/; //hack + //if (!(u32)pAddr->magic) hack_LastHeader = pAddr.GetAddr(); return CELL_OK; } @@ -177,7 +177,7 @@ int cellPamfReaderInitialize(mem_ptr_t pSelf, mem_ptr_tfileSize = ((u64)pAddr->data_offset << 11) + ((u64)pAddr->data_size << 11); } pSelf->pAddr = pAddr.GetAddr(); - if (hack_LastHeader) memcpy(Memory + pAddr.GetAddr(), Memory + hack_LastHeader, 2048); + //if (hack_LastHeader) memcpy(Memory + pAddr.GetAddr(), Memory + hack_LastHeader, 2048); if (attribute & CELL_PAMF_ATTRIBUTE_VERIFY_ON) { //TODO diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 9eb86ebb0a..32d684c3d2 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -175,8 +175,8 @@ void fsAioRead(u32 fd, mem_ptr_t aio, int xid, mem_func_ptr_toffset, buf_addr, (u64)aio->size, res, xid, path.c_str()); diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 0342c60861..6c832df354 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -5,6 +5,7 @@ #include "lv2/SC_Timer.h" #include "lv2/SC_Rwlock.h" #include "lv2/SC_SPU_Thread.h" +#include "lv2/SC_Lwmutex.h" //#define SYSCALLS_DEBUG #define declCPU PPUThread& CPU = GetCurrentPPUThread @@ -145,11 +146,11 @@ extern int sys_semaphore_post(u32 sem, int count); extern int sys_semaphore_get_value(u32 sem, u32 count_addr); //sys_lwmutex -extern int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr); -extern int sys_lwmutex_destroy(u64 lwmutex_addr); -extern int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout); -extern int sys_lwmutex_trylock(u64 lwmutex_addr); -extern int sys_lwmutex_unlock(u64 lwmutex_addr); +extern int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_t attr); +extern int sys_lwmutex_destroy(mem_ptr_t lwmutex); +extern int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout); +extern int sys_lwmutex_trylock(mem_ptr_t lwmutex); +extern int sys_lwmutex_unlock(mem_ptr_t lwmutex); //sys_cond extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index f483e90e00..c1e2779df4 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -1,122 +1,198 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/lv2/SC_Lwmutex.h" +#include -struct lwmutex_lock_info +SysCallBase sc_lwmutex("sys_lwmutex"); + +std::mutex g_lwmutex; + +int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_t attr) { - u32 owner; - u32 waiter; -}; + sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)", + lwmutex.GetAddr(), attr.GetAddr()); -union lwmutex_variable -{ - lwmutex_lock_info info; - u64 all_info; -}; + if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; -struct lwmutex -{ - lwmutex_variable lock_var; - u32 attribute; - u32 recursive_count; - u32 sleep_queue; - u32 pad; -}; - -struct lwmutex_attr -{ - u32 attr_protocol; - u32 attr_recursive; - char name[8]; -}; - -SysCallBase sc_lwmutex("sys_wmutex"); - -int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr) -{ - if(!Memory.IsGoodAddr(lwmutex_addr, 4) || !Memory.IsGoodAddr(lwmutex_attr_addr)) + switch ((u32)attr->attr_recursive) { - return CELL_EFAULT; + case SYS_SYNC_RECURSIVE: break; + case SYS_SYNC_NOT_RECURSIVE: break; + default: return CELL_EINVAL; } - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - lmtx.lock_var.all_info = 0; - lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr]; + switch ((u32)attr->attr_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; + default: return CELL_EINVAL; + } + + lwmutex->attribute = (u32)attr->attr_protocol | (u32)attr->attr_recursive; + lwmutex->all_info = 0; + lwmutex->pad = 0; + lwmutex->recursive_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); return CELL_OK; } -int sys_lwmutex_destroy(u64 lwmutex_addr) +int sys_lwmutex_destroy(mem_ptr_t lwmutex) { - //sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr); - - //lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - //Emu.GetIdManager().RemoveID(lmtx.attribute); + sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); return CELL_OK; } -int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout) +int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) { - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; + sc_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout); + + if (!lwmutex.IsGood()) return CELL_EFAULT; PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); - if(thr.GetId() == re(lmtx.lock_var.info.owner)) - { - re(lmtx.recursive_count, re(lmtx.recursive_count) + 1); - return CELL_OK; - } + { // global lock + std::lock_guard lock(g_lwmutex); - if(!lmtx.lock_var.info.owner) - { - re(lmtx.lock_var.info.owner, GetCurrentPPUThread().GetId()); - re(lmtx.recursive_count, 1); - } - else if(!lmtx.lock_var.info.waiter) - { - thr.Wait(true); - re(lmtx.lock_var.info.waiter, thr.GetId()); - } - else - { - ConLog.Warning("lwmutex has waiter!"); - return CELL_EBUSY; - } - - return CELL_OK; -} - -int sys_lwmutex_trylock(u64 lwmutex_addr) -{ - //sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr = 0x%llx)", lwmutex_addr); - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - - if(lmtx.lock_var.info.owner) return CELL_EBUSY; - - return CELL_OK; -} - -int sys_lwmutex_unlock(u64 lwmutex_addr) -{ - //sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr = 0x%llx)", lwmutex_addr); - - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - - re(lmtx.recursive_count, re(lmtx.recursive_count) - 1); - - if(!lmtx.recursive_count) - { - if(lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter) + if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE) { - lmtx.lock_var.info.waiter = 0; - CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner); - if(thr) + if (id == (u32)lwmutex->owner) { - thr->Wait(false); + 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 } - return CELL_OK; + u32 counter = 0; + const u32 max_counter = timeout ? (timeout / 1000) : 20000; + do // waiting + { + 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 + } + + if (counter++ > max_counter) + { + if (!timeout) + { // endless waiter + sc_lwmutex.Error("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr()); + return CELL_OK; + } + else + { + return CELL_ETIMEDOUT; + } + } + } while (true); +} + +int sys_lwmutex_trylock(mem_ptr_t lwmutex) +{ + sc_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + + if (!lwmutex.IsGood()) return CELL_EFAULT; + + 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; + } + } +} + +int sys_lwmutex_unlock(mem_ptr_t lwmutex) +{ + sc_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + + if (!lwmutex.IsGood()) return CELL_EFAULT; + + PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); + + { // 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; + } + } } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h new file mode 100644 index 0000000000..85f0f01fe8 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -0,0 +1,54 @@ +#pragma once + +// attr_protocol (waiting scheduling policy) +enum +{ + // First In, First Out + SYS_SYNC_FIFO = 1, + // Priority Order (doesn't care?) + SYS_SYNC_PRIORITY = 2, + // Basic Priority Inheritance Protocol + SYS_SYNC_PRIORITY_INHERIT = 3, + // ???? + SYS_SYNC_RETRY = 4, + // + SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF, +}; + +// attr_recursive (recursive locks policy) +enum +{ + // Recursive locks are allowed + SYS_SYNC_RECURSIVE = 0x10, + // Recursive locks are NOT allowed + SYS_SYNC_NOT_RECURSIVE = 0x20, + // + SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //??? +}; + +struct sys_lwmutex_t +{ + union // sys_lwmutex_variable_t + { + struct // sys_lwmutex_lock_info_t + { + /* volatile */ be_t owner; + /* volatile */ be_t waiter; + }; + struct + { + /* volatile */ be_t all_info; + }; + }; + be_t attribute; + be_t recursive_count; + be_t sleep_queue; + be_t pad; +}; + +struct sys_lwmutex_attribute_t +{ + be_t attr_protocol; + be_t attr_recursive; + char name[8]; +}; \ No newline at end of file