1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

SC_Lwmutex

This commit is contained in:
Nekotekina 2014-01-20 01:19:37 +04:00
parent d65647acf3
commit 6fb1a67a83
7 changed files with 264 additions and 108 deletions

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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

View File

@ -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());

View File

@ -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);

View File

@ -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;
}
}
} }

View 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];
};