mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ struct CellDmuxResourceEx
|
||||
be_t<u32> maxContention;
|
||||
};
|
||||
|
||||
/*
|
||||
struct CellDmuxResource2Ex
|
||||
{
|
||||
bool isResourceEx; //true
|
||||
@ -86,18 +87,42 @@ struct CellDmuxResource2NoEx
|
||||
bool isResourceEx; //false
|
||||
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
|
||||
{
|
||||
// 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;
|
||||
};
|
||||
|
||||
struct CellDmuxEsCb
|
||||
{
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
@ -122,7 +122,7 @@ int cellPamfGetHeaderSize(mem_ptr_t<PamfHeader> 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<PamfHeader> pAddr, u64 fileSize, u32 attrib
|
||||
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)
|
||||
{
|
||||
@ -150,10 +150,10 @@ int cellPamfGetStreamOffsetAndSize(mem_ptr_t<PamfHeader> 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<CellPamfReader> pSelf, mem_ptr_t<PamfHead
|
||||
pSelf->fileSize = ((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
|
||||
|
@ -175,8 +175,8 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
||||
}
|
||||
|
||||
//start callback thread
|
||||
if(func)
|
||||
func.async(aio.GetAddr(), error, xid, res);
|
||||
//if(func)
|
||||
//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])",
|
||||
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_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<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr);
|
||||
extern int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||
extern int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout);
|
||||
extern int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||
extern int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||
|
||||
//sys_cond
|
||||
extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr);
|
||||
|
@ -1,122 +1,198 @@
|
||||
#include "stdafx.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;
|
||||
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<sys_lwmutex_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<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();
|
||||
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<std::mutex> 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<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