mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +01:00
SC_Lwmutex
This commit is contained in:
parent
d65647acf3
commit
6fb1a67a83
@ -35,11 +35,11 @@ int cellDmuxOpenEx(mem_ptr_t<CellDmuxType> demuxerType, mem_ptr_t<CellDmuxResour
|
|||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellDmuxOpen2(mem_ptr_t<CellDmuxType2> demuxerType2, u32 demuxerResource2_addr,
|
int cellDmuxOpen2(mem_ptr_t<CellDmuxType2> demuxerType2, mem_ptr_t<CellDmuxResource2> demuxerResource2,
|
||||||
mem_ptr_t<CellDmuxCb> demuxerCb, u32 demuxerHandle_addr)
|
mem_ptr_t<CellDmuxCb> demuxerCb, u32 demuxerHandle_addr)
|
||||||
{
|
{
|
||||||
cellDmux.Error("cellDmuxOpen2(demuxerType2_addr=0x%x, demuxerResource2_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)",
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ struct CellDmuxResourceEx
|
|||||||
be_t<u32> maxContention;
|
be_t<u32> maxContention;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
struct CellDmuxResource2Ex
|
struct CellDmuxResource2Ex
|
||||||
{
|
{
|
||||||
bool isResourceEx; //true
|
bool isResourceEx; //true
|
||||||
@ -86,18 +87,42 @@ struct CellDmuxResource2NoEx
|
|||||||
bool isResourceEx; //false
|
bool isResourceEx; //false
|
||||||
CellDmuxResource resource;
|
CellDmuxResource resource;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct CellDmuxResource2
|
||||||
|
{
|
||||||
|
bool isResourceEx;
|
||||||
|
be_t<u32> memAddr;
|
||||||
|
be_t<u32> memSize;
|
||||||
|
be_t<u32> ppuThreadPriority;
|
||||||
|
be_t<u32> ppuThreadStackSize;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
be_t<u32> spuThreadPriority;
|
||||||
|
be_t<u32> numOfSpus;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
be_t<u32> ex_spurs_addr;
|
||||||
|
u8 ex_priority[8];
|
||||||
|
be_t<u32> ex_maxContention;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct CellDmuxCb
|
struct CellDmuxCb
|
||||||
{
|
{
|
||||||
// CellDmuxCbMsg callback
|
// CellDmuxCbMsg callback
|
||||||
mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, mem_ptr_t<CellDmuxMsg> demuxerMsg, u32 cbArg_addr)> cbMsgFunc;
|
be_t<mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, mem_ptr_t<CellDmuxMsg> demuxerMsg, u32 cbArg_addr)>> cbMsgFunc;
|
||||||
be_t<u32> cbArg_addr;
|
be_t<u32> cbArg_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellDmuxEsCb
|
struct CellDmuxEsCb
|
||||||
{
|
{
|
||||||
// CellDmuxCbEsMsg callback
|
// CellDmuxCbEsMsg callback
|
||||||
mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, u32 esHandle_addr, mem_ptr_t<CellDmuxEsMsg> esMsg, u32 cbArg_addr)> cbEsMsgFunc;
|
be_t<mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, u32 esHandle_addr, mem_ptr_t<CellDmuxEsMsg> esMsg, u32 cbArg_addr)>> cbEsMsgFunc;
|
||||||
be_t<u32> cbArg_addr;
|
be_t<u32> cbArg_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ int cellPamfGetHeaderSize(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, mem64_t pSi
|
|||||||
//return CELL_PAMF_ERROR_UNKNOWN_TYPE;
|
//return CELL_PAMF_ERROR_UNKNOWN_TYPE;
|
||||||
|
|
||||||
const u64 offset = (u64)pAddr->data_offset << 11;
|
const u64 offset = (u64)pAddr->data_offset << 11;
|
||||||
pSize = offset ? offset : 2048; //hack
|
pSize = offset /*? offset : 2048*/; //hack
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ int cellPamfGetHeaderSize2(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, u32 attrib
|
|||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 hack_LastHeader = 0;
|
//u32 hack_LastHeader = 0;
|
||||||
|
|
||||||
int cellPamfGetStreamOffsetAndSize(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, mem64_t pOffset, mem64_t pSize)
|
int cellPamfGetStreamOffsetAndSize(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, mem64_t pOffset, mem64_t pSize)
|
||||||
{
|
{
|
||||||
@ -150,10 +150,10 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t<PamfHeader> pAddr, u64 fileSize, me
|
|||||||
//return CELL_PAMF_ERROR_UNKNOWN_TYPE;
|
//return CELL_PAMF_ERROR_UNKNOWN_TYPE;
|
||||||
|
|
||||||
const u64 offset = (u64)pAddr->data_offset << 11;
|
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;
|
const u64 size = (u64)pAddr->data_size << 11;
|
||||||
pSize = size ? size : (fileSize - 2048); //hack
|
pSize = size /*? size : (fileSize - 2048)*/; //hack
|
||||||
if (!(u32)pAddr->magic) hack_LastHeader = pAddr.GetAddr();
|
//if (!(u32)pAddr->magic) hack_LastHeader = pAddr.GetAddr();
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ int cellPamfReaderInitialize(mem_ptr_t<CellPamfReader> pSelf, mem_ptr_t<PamfHead
|
|||||||
pSelf->fileSize = ((u64)pAddr->data_offset << 11) + ((u64)pAddr->data_size << 11);
|
pSelf->fileSize = ((u64)pAddr->data_offset << 11) + ((u64)pAddr->data_size << 11);
|
||||||
}
|
}
|
||||||
pSelf->pAddr = pAddr.GetAddr();
|
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)
|
if (attribute & CELL_PAMF_ATTRIBUTE_VERIFY_ON)
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
|
@ -175,8 +175,8 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
//start callback thread
|
//start callback thread
|
||||||
if(func)
|
//if(func)
|
||||||
func.async(aio.GetAddr(), error, xid, res);
|
//func.async(aio.GetAddr(), error, xid, res);
|
||||||
|
|
||||||
ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=%d, res=%d, xid=%d [%s])",
|
ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=%d, res=%d, xid=%d [%s])",
|
||||||
fd, (u64)aio->offset, buf_addr, (u64)aio->size, res, xid, path.c_str());
|
fd, (u64)aio->offset, buf_addr, (u64)aio->size, res, xid, path.c_str());
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "lv2/SC_Timer.h"
|
#include "lv2/SC_Timer.h"
|
||||||
#include "lv2/SC_Rwlock.h"
|
#include "lv2/SC_Rwlock.h"
|
||||||
#include "lv2/SC_SPU_Thread.h"
|
#include "lv2/SC_SPU_Thread.h"
|
||||||
|
#include "lv2/SC_Lwmutex.h"
|
||||||
//#define SYSCALLS_DEBUG
|
//#define SYSCALLS_DEBUG
|
||||||
|
|
||||||
#define declCPU PPUThread& CPU = GetCurrentPPUThread
|
#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);
|
extern int sys_semaphore_get_value(u32 sem, u32 count_addr);
|
||||||
|
|
||||||
//sys_lwmutex
|
//sys_lwmutex
|
||||||
extern int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr);
|
extern int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr);
|
||||||
extern int sys_lwmutex_destroy(u64 lwmutex_addr);
|
extern int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||||
extern int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout);
|
extern int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout);
|
||||||
extern int sys_lwmutex_trylock(u64 lwmutex_addr);
|
extern int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||||
extern int sys_lwmutex_unlock(u64 lwmutex_addr);
|
extern int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||||
|
|
||||||
//sys_cond
|
//sys_cond
|
||||||
extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr);
|
extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr);
|
||||||
|
@ -1,122 +1,198 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/SysCalls/SysCalls.h"
|
#include "Emu/SysCalls/SysCalls.h"
|
||||||
|
#include "Emu/SysCalls/lv2/SC_Lwmutex.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
struct lwmutex_lock_info
|
SysCallBase sc_lwmutex("sys_lwmutex");
|
||||||
|
|
||||||
|
std::mutex g_lwmutex;
|
||||||
|
|
||||||
|
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr)
|
||||||
{
|
{
|
||||||
u32 owner;
|
sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||||
u32 waiter;
|
lwmutex.GetAddr(), attr.GetAddr());
|
||||||
};
|
|
||||||
|
|
||||||
union lwmutex_variable
|
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||||
{
|
|
||||||
lwmutex_lock_info info;
|
|
||||||
u64 all_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lwmutex
|
switch ((u32)attr->attr_recursive)
|
||||||
{
|
|
||||||
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;
|
case SYS_SYNC_RECURSIVE: break;
|
||||||
|
case SYS_SYNC_NOT_RECURSIVE: break;
|
||||||
|
default: return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
|
switch ((u32)attr->attr_protocol)
|
||||||
lmtx.lock_var.all_info = 0;
|
{
|
||||||
lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr];
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_lwmutex_destroy(u64 lwmutex_addr)
|
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||||
{
|
{
|
||||||
//sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr);
|
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||||
|
|
||||||
//lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
|
|
||||||
//Emu.GetIdManager().RemoveID(lmtx.attribute);
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout)
|
int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_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();
|
PPCThread& thr = GetCurrentPPUThread();
|
||||||
|
const u32 id = thr.GetId();
|
||||||
|
|
||||||
if(thr.GetId() == re(lmtx.lock_var.info.owner))
|
{ // global lock
|
||||||
{
|
std::lock_guard<std::mutex> lock(g_lwmutex);
|
||||||
re(lmtx.recursive_count, re(lmtx.recursive_count) + 1);
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!lmtx.lock_var.info.owner)
|
if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE)
|
||||||
{
|
|
||||||
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;
|
if (id == (u32)lwmutex->owner)
|
||||||
CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner);
|
|
||||||
if(thr)
|
|
||||||
{
|
{
|
||||||
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<std::mutex> 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<sys_lwmutex_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<std::mutex> 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<sys_lwmutex_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<std::mutex> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
54
rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h
Normal file
54
rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h
Normal file
@ -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<u32> owner;
|
||||||
|
/* volatile */ be_t<u32> waiter;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* volatile */ be_t<u64> all_info;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
be_t<u32> attribute;
|
||||||
|
be_t<u32> recursive_count;
|
||||||
|
be_t<u32> sleep_queue;
|
||||||
|
be_t<u32> pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sys_lwmutex_attribute_t
|
||||||
|
{
|
||||||
|
be_t<u32> attr_protocol;
|
||||||
|
be_t<u32> attr_recursive;
|
||||||
|
char name[8];
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user