#include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" struct lwmutex_lock_info { u32 owner; u32 waiter; }; union lwmutex_variable { lwmutex_lock_info info; u64 all_info; }; 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)) { return CELL_EFAULT; } lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; lmtx.lock_var.all_info = 0; lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr]; return CELL_OK; } int sys_lwmutex_destroy(u64 lwmutex_addr) { //sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr); //lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; //Emu.GetIdManager().RemoveID(lmtx.attribute); return CELL_OK; } int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout) { lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; PPCThread& thr = GetCurrentPPUThread(); if(thr.GetId() == re(lmtx.lock_var.info.owner)) { re(lmtx.recursive_count, re(lmtx.recursive_count) + 1); return CELL_OK; } 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) { lmtx.lock_var.info.waiter = 0; CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner); if(thr) { thr->Wait(false); } } } return CELL_OK; }