mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 16:31:28 +12:00
SC_Rwlock implementation, SC_Lwcond draft
Other small changes
This commit is contained in:
parent
4de64e5afe
commit
67a144df2a
11 changed files with 451 additions and 34 deletions
|
@ -365,6 +365,8 @@ int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t<CellCodecEsFilterId
|
||||||
|
|
||||||
int cellPamfReaderGetStreamIndex(mem_ptr_t<CellPamfReader> pSelf)
|
int cellPamfReaderGetStreamIndex(mem_ptr_t<CellPamfReader> pSelf)
|
||||||
{
|
{
|
||||||
|
cellPamf.Log("cellPamfReaderGetStreamIndex(pSelf=0x%x)", pSelf.GetAddr());
|
||||||
|
|
||||||
return pSelf->stream;
|
return pSelf->stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +508,7 @@ int cellPamfReaderGetNumberOfEp(mem_ptr_t<CellPamfReader> pSelf)
|
||||||
|
|
||||||
int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t<CellPamfReader> pSelf, u32 epIndex, mem_ptr_t<CellPamfEpIterator> pIt)
|
int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t<CellPamfReader> pSelf, u32 epIndex, mem_ptr_t<CellPamfEpIterator> pIt)
|
||||||
{
|
{
|
||||||
cellPamf.Warning("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)",
|
cellPamf.Error("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)",
|
||||||
pSelf.GetAddr(), pSelf->stream, epIndex, pIt.GetAddr());
|
pSelf.GetAddr(), pSelf->stream, epIndex, pIt.GetAddr());
|
||||||
|
|
||||||
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
||||||
|
@ -516,19 +518,25 @@ int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t<CellPamfReader> pSelf, u32 ep
|
||||||
|
|
||||||
int cellPamfReaderGetEpIteratorWithTimeStamp(mem_ptr_t<CellPamfReader> pSelf, mem_ptr_t<CellCodecTimeStamp> pTimeStamp, mem_ptr_t<CellPamfEpIterator> pIt)
|
int cellPamfReaderGetEpIteratorWithTimeStamp(mem_ptr_t<CellPamfReader> pSelf, mem_ptr_t<CellCodecTimeStamp> pTimeStamp, mem_ptr_t<CellPamfEpIterator> pIt)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellPamf);
|
cellPamf.Error("cellPamfReaderGetEpIteratorWithTimeStamp(pSelf=0x%x, pTimeStamp_addr=0x%x, pIt_addr=0x%x)",
|
||||||
|
pSelf.GetAddr(), pTimeStamp.GetAddr(), pIt.GetAddr());
|
||||||
|
|
||||||
|
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
||||||
|
//TODO:
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellPamfEpIteratorGetEp(mem_ptr_t<CellPamfEpIterator> pIt, mem_ptr_t<CellPamfEp> pEp)
|
int cellPamfEpIteratorGetEp(mem_ptr_t<CellPamfEpIterator> pIt, mem_ptr_t<CellPamfEp> pEp)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellPamf);
|
cellPamf.Error("cellPamfEpIteratorGetEp(pIt_addr=0x%x, pEp_addr=0x%x)", pIt.GetAddr(), pEp.GetAddr());
|
||||||
|
//TODO:
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellPamfEpIteratorMove(mem_ptr_t<CellPamfEpIterator> pIt, int steps, mem_ptr_t<CellPamfEp> pEp)
|
int cellPamfEpIteratorMove(mem_ptr_t<CellPamfEpIterator> pIt, int steps, mem_ptr_t<CellPamfEp> pEp)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(cellPamf);
|
cellPamf.Error("cellPamfEpIteratorMove(pIt_addr=0x%x, steps=%d, pEp_addr=0x%x)", pIt.GetAddr(), steps, pEp.GetAddr());
|
||||||
|
//TODO:
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,4 +175,11 @@ void sysPrxForUser_init()
|
||||||
|
|
||||||
sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_load);
|
sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_load);
|
||||||
sysPrxForUser.AddFunc(0xb995662e, sys_raw_spu_image_load);
|
sysPrxForUser.AddFunc(0xb995662e, sys_raw_spu_image_load);
|
||||||
|
|
||||||
|
sysPrxForUser.AddFunc(0xda0eb71a, sys_lwcond_create);
|
||||||
|
sysPrxForUser.AddFunc(0x1c9a942c, sys_lwcond_destroy);
|
||||||
|
sysPrxForUser.AddFunc(0xef87a695, sys_lwcond_signal);
|
||||||
|
sysPrxForUser.AddFunc(0xe9a1bd84, sys_lwcond_signal_all);
|
||||||
|
sysPrxForUser.AddFunc(0x52aadadf, sys_lwcond_signal_to);
|
||||||
|
sysPrxForUser.AddFunc(0x2a6d9d51, sys_lwcond_wait);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#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"
|
#include "lv2/SC_Lwmutex.h"
|
||||||
|
#include "lv2/SC_Lwcond.h"
|
||||||
#include "Emu/event.h"
|
#include "Emu/event.h"
|
||||||
//#define SYSCALLS_DEBUG
|
//#define SYSCALLS_DEBUG
|
||||||
|
|
||||||
|
@ -147,6 +148,14 @@ extern int sys_semaphore_trywait(u32 sem);
|
||||||
extern int sys_semaphore_post(u32 sem, int count);
|
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_lwcond
|
||||||
|
extern int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwcond_attribute_t> attr);
|
||||||
|
extern int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond);
|
||||||
|
extern int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond);
|
||||||
|
extern int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond);
|
||||||
|
extern int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id);
|
||||||
|
extern int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout);
|
||||||
|
|
||||||
//sys_lwmutex
|
//sys_lwmutex
|
||||||
extern int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr);
|
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_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||||
|
|
81
rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp
Normal file
81
rpcs3/Emu/SysCalls/lv2/SC_Lwcond.cpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Emu/SysCalls/SysCalls.h"
|
||||||
|
#include "SC_Lwmutex.h"
|
||||||
|
#include "SC_Lwcond.h"
|
||||||
|
|
||||||
|
SysCallBase sys_lwcond("sys_lwcond");
|
||||||
|
|
||||||
|
int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwcond_attribute_t> attr)
|
||||||
|
{
|
||||||
|
sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)",
|
||||||
|
lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr());
|
||||||
|
|
||||||
|
if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||||
|
|
||||||
|
lwcond->lwmutex_addr = lwmutex.GetAddr();
|
||||||
|
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(*(u64*)&attr->name));
|
||||||
|
|
||||||
|
sys_lwcond.Warning("*** lwcond created [%s]", attr->name);
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||||
|
{
|
||||||
|
sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.GetAddr());
|
||||||
|
|
||||||
|
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||||
|
LWCond* lwc;
|
||||||
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
|
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
Emu.GetIdManager().RemoveID(id);
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||||
|
{
|
||||||
|
sys_lwcond.Warning("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.GetAddr());
|
||||||
|
|
||||||
|
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||||
|
LWCond* lwc;
|
||||||
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
|
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||||
|
{
|
||||||
|
sys_lwcond.Warning("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.GetAddr());
|
||||||
|
|
||||||
|
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||||
|
LWCond* lwc;
|
||||||
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
|
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
||||||
|
{
|
||||||
|
sys_lwcond.Warning("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.GetAddr(), ppu_thread_id);
|
||||||
|
|
||||||
|
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||||
|
LWCond* lwc;
|
||||||
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
|
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
||||||
|
{
|
||||||
|
sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%llu)", lwcond.GetAddr(), timeout);
|
||||||
|
|
||||||
|
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||||
|
LWCond* lwc;
|
||||||
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
|
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
24
rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h
Normal file
24
rpcs3/Emu/SysCalls/lv2/SC_Lwcond.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct sys_lwcond_attribute_t
|
||||||
|
{
|
||||||
|
char name[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sys_lwcond_t
|
||||||
|
{
|
||||||
|
be_t<u32> lwmutex_addr;
|
||||||
|
be_t<u32> lwcond_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
struct LWCond
|
||||||
|
{
|
||||||
|
u64 m_name;
|
||||||
|
|
||||||
|
LWCond(u64 name)
|
||||||
|
: m_name(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
|
@ -23,10 +23,10 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||||
|
|
||||||
switch ((u32)attr->attr_protocol)
|
switch ((u32)attr->attr_protocol)
|
||||||
{
|
{
|
||||||
case SYS_SYNC_PRIORITY: break;
|
case SYS_SYNC_PRIORITY: sc_lwmutex.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||||
case SYS_SYNC_RETRY: sc_lwmutex.Error("TODO: SYS_SYNC_RETRY attr"); break;
|
case SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break;
|
||||||
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Error("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||||
case SYS_SYNC_FIFO: sc_lwmutex.Error("TODO: SYS_SYNC_FIFO attr"); break;
|
case SYS_SYNC_FIFO: sc_lwmutex.Log("TODO: SYS_SYNC_FIFO attr"); break;
|
||||||
default: return CELL_EINVAL;
|
default: return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,15 +36,31 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||||
lwmutex->recursive_count = 0;
|
lwmutex->recursive_count = 0;
|
||||||
lwmutex->sleep_queue = 0;
|
lwmutex->sleep_queue = 0;
|
||||||
|
|
||||||
sc_lwmutex.Log("*** lwmutex created [%s] (protocol=0x%x, recursive=0x%x)",
|
sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute);
|
||||||
attr->name, (u32)attr->attr_protocol, (u32)attr->attr_recursive);
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||||
{
|
{
|
||||||
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||||
|
|
||||||
|
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||||
|
|
||||||
|
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||||
|
|
||||||
|
{ // global lock
|
||||||
|
std::lock_guard<std::mutex> lock(g_lwmutex);
|
||||||
|
|
||||||
|
if (!lwmutex->owner)
|
||||||
|
{
|
||||||
|
lwmutex->attribute = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CELL_EBUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +71,8 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||||
|
|
||||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||||
|
|
||||||
|
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||||
|
|
||||||
PPCThread& thr = GetCurrentPPUThread();
|
PPCThread& thr = GetCurrentPPUThread();
|
||||||
const u32 id = thr.GetId();
|
const u32 id = thr.GetId();
|
||||||
|
|
||||||
|
@ -80,7 +98,7 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||||
|
|
||||||
if (!lwmutex->owner) // lock
|
if (!lwmutex->owner) // lock
|
||||||
{
|
{
|
||||||
lwmutex->owner = id;
|
lwmutex->owner = id;
|
||||||
lwmutex->recursive_count = 1;
|
lwmutex->recursive_count = 1;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +109,7 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||||
do // waiting
|
do // waiting
|
||||||
{
|
{
|
||||||
|
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
|
|
||||||
{ // global lock
|
{ // global lock
|
||||||
|
@ -108,9 +127,9 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||||
if (counter++ > max_counter)
|
if (counter++ > max_counter)
|
||||||
{
|
{
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
{ // endless waiter
|
{
|
||||||
sc_lwmutex.Error("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
|
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
|
||||||
return CELL_OK;
|
counter = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -126,6 +145,8 @@ int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||||
|
|
||||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||||
|
|
||||||
|
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||||
|
|
||||||
PPCThread& thr = GetCurrentPPUThread();
|
PPCThread& thr = GetCurrentPPUThread();
|
||||||
const u32 id = thr.GetId();
|
const u32 id = thr.GetId();
|
||||||
|
|
||||||
|
|
|
@ -6,48 +6,169 @@ SysCallBase sys_rwlock("sys_rwlock");
|
||||||
|
|
||||||
int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr)
|
int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr());
|
sys_rwlock.Warning("sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.GetAddr(), attr.GetAddr());
|
||||||
|
|
||||||
|
if (!rw_lock_id.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||||
|
|
||||||
|
switch ((u32)attr->attr_protocol)
|
||||||
|
{
|
||||||
|
case SYS_SYNC_PRIORITY: sys_rwlock.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||||
|
case SYS_SYNC_RETRY: sys_rwlock.Error("Invalid SYS_SYNC_RETRY attr"); break;
|
||||||
|
case SYS_SYNC_PRIORITY_INHERIT: sys_rwlock.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||||
|
case SYS_SYNC_FIFO: break;
|
||||||
|
default: return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((u32)attr->attr_pshared != 0x200)
|
||||||
|
{
|
||||||
|
sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared);
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared,
|
||||||
|
(u64)attr->key, (s32)attr->flags, *(u64*)&attr->name));
|
||||||
|
|
||||||
|
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x)", attr->name, (u32)attr->attr_protocol);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_destroy(u32 rw_lock_id)
|
int sys_rwlock_destroy(u32 rw_lock_id)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id);
|
sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id);
|
||||||
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(rw->m_lock);
|
||||||
|
|
||||||
|
if (rw->wlock_queue.GetCount() || rw->rlock_list.GetCount() || rw->wlock_thread) return CELL_EBUSY;
|
||||||
|
|
||||||
|
Emu.GetIdManager().RemoveID(rw_lock_id);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
|
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
|
||||||
return CELL_OK;
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
PPCThread& thr = GetCurrentPPUThread();
|
||||||
|
const u32 id = thr.GetId();
|
||||||
|
|
||||||
|
if (rw->rlock_trylock(id)) return CELL_OK;
|
||||||
|
|
||||||
|
u32 counter = 0;
|
||||||
|
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||||
|
Sleep(1);
|
||||||
|
|
||||||
|
if (rw->rlock_trylock(id)) return CELL_OK;
|
||||||
|
|
||||||
|
if (counter++ > max_counter)
|
||||||
|
{
|
||||||
|
if (!timeout)
|
||||||
|
{
|
||||||
|
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d): TIMEOUT", rw_lock_id);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CELL_ETIMEDOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_tryrlock(u32 rw_lock_id)
|
int sys_rwlock_tryrlock(u32 rw_lock_id)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
|
sys_rwlock.Warning("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
|
||||||
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
if (!rw->rlock_trylock(GetCurrentPPUThread().GetId())) return CELL_EBUSY;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_runlock(u32 rw_lock_id)
|
int sys_rwlock_runlock(u32 rw_lock_id)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
|
sys_rwlock.Warning("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
|
||||||
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
if (!rw->rlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
|
int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
|
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
|
||||||
return CELL_OK;
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
PPCThread& thr = GetCurrentPPUThread();
|
||||||
|
const u32 id = thr.GetId();
|
||||||
|
|
||||||
|
if (!rw->wlock_check(id)) return CELL_EDEADLK;
|
||||||
|
|
||||||
|
if (rw->wlock_trylock(id, true)) return CELL_OK;
|
||||||
|
|
||||||
|
u32 counter = 0;
|
||||||
|
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||||
|
Sleep(1);
|
||||||
|
|
||||||
|
if (rw->wlock_trylock(id, true)) return CELL_OK;
|
||||||
|
|
||||||
|
if (counter++ > max_counter)
|
||||||
|
{
|
||||||
|
if (!timeout)
|
||||||
|
{
|
||||||
|
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d): TIMEOUT", rw_lock_id);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CELL_ETIMEDOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_trywlock(u32 rw_lock_id)
|
int sys_rwlock_trywlock(u32 rw_lock_id)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
|
sys_rwlock.Warning("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
|
||||||
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
PPCThread& thr = GetCurrentPPUThread();
|
||||||
|
const u32 id = thr.GetId();
|
||||||
|
|
||||||
|
if (!rw->wlock_check(id)) return CELL_EDEADLK;
|
||||||
|
|
||||||
|
if (!rw->wlock_trylock(id, false)) return CELL_EBUSY;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_rwlock_wunlock(u32 rw_lock_id)
|
int sys_rwlock_wunlock(u32 rw_lock_id)
|
||||||
{
|
{
|
||||||
sys_rwlock.Warning("Unimplemented function: sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
|
sys_rwlock.Warning("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
|
||||||
|
|
||||||
|
RWLock* rw;
|
||||||
|
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
if (!rw->wlock_unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,153 @@
|
||||||
|
|
||||||
struct sys_rwlock_attribute_t
|
struct sys_rwlock_attribute_t
|
||||||
{
|
{
|
||||||
u32 attr_protocol; //sys_protocol_t
|
be_t<u32> attr_protocol;
|
||||||
u32 attr_pshared; //sys_process_shared_t
|
be_t<u32> attr_pshared; // == 0x200 (NOT SHARED)
|
||||||
u64 key; //sys_ipc_key_t
|
be_t<u64> key; // process-shared key (not used)
|
||||||
s32 flags;
|
be_t<s32> flags; // process-shared flags (not used)
|
||||||
u8 name[8];
|
be_t<u32> pad;
|
||||||
|
char name[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
struct RWLock
|
||||||
|
{
|
||||||
|
std::mutex m_lock; // internal lock
|
||||||
|
u32 wlock_thread; // write lock owner
|
||||||
|
Array<u32> wlock_queue; // write lock queue
|
||||||
|
Array<u32> rlock_list; // read lock list
|
||||||
|
u32 m_protocol; // TODO
|
||||||
|
|
||||||
|
u32 m_pshared; // not used
|
||||||
|
u64 m_key; // not used
|
||||||
|
s32 m_flags; // not used
|
||||||
|
union
|
||||||
|
{
|
||||||
|
u64 m_name_data; // not used
|
||||||
|
char m_name[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name)
|
||||||
|
: m_protocol(protocol)
|
||||||
|
, m_pshared(pshared)
|
||||||
|
, m_key(key)
|
||||||
|
, m_flags(flags)
|
||||||
|
, m_name_data(name)
|
||||||
|
, wlock_thread(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rlock_trylock(u32 id)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_lock);
|
||||||
|
|
||||||
|
if (!wlock_thread && !wlock_queue.GetCount())
|
||||||
|
{
|
||||||
|
rlock_list.AddCpy(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rlock_unlock(u32 id)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_lock);
|
||||||
|
|
||||||
|
for (u32 i = rlock_list.GetCount() - 1; ~i; i--)
|
||||||
|
{
|
||||||
|
if (rlock_list[i] == id)
|
||||||
|
{
|
||||||
|
rlock_list.RemoveAt(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlock_check(u32 id)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_lock);
|
||||||
|
|
||||||
|
if (wlock_thread == id)
|
||||||
|
{
|
||||||
|
return false; // deadlock
|
||||||
|
}
|
||||||
|
for (u32 i = rlock_list.GetCount() - 1; ~i; i--)
|
||||||
|
{
|
||||||
|
if (rlock_list[i] == id)
|
||||||
|
{
|
||||||
|
return false; // deadlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlock_trylock(u32 id, bool enqueue)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_lock);
|
||||||
|
|
||||||
|
if (wlock_thread || rlock_list.GetCount()) // already locked
|
||||||
|
{
|
||||||
|
if (!enqueue)
|
||||||
|
{
|
||||||
|
return false; // do not enqueue
|
||||||
|
}
|
||||||
|
for (u32 i = wlock_queue.GetCount() - 1; ~i; i--)
|
||||||
|
{
|
||||||
|
if (wlock_queue[i] == id)
|
||||||
|
{
|
||||||
|
return false; // already enqueued
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wlock_queue.AddCpy(id); // enqueue new thread
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wlock_queue.GetCount())
|
||||||
|
{
|
||||||
|
// SYNC_FIFO only yet
|
||||||
|
if (wlock_queue[0] == id)
|
||||||
|
{
|
||||||
|
wlock_thread = id;
|
||||||
|
wlock_queue.RemoveAt(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!enqueue)
|
||||||
|
{
|
||||||
|
return false; // do not enqueue
|
||||||
|
}
|
||||||
|
for (u32 i = wlock_queue.GetCount() - 1; ~i; i--)
|
||||||
|
{
|
||||||
|
if (wlock_queue[i] == id)
|
||||||
|
{
|
||||||
|
return false; // already enqueued
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wlock_queue.AddCpy(id); // enqueue new thread
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wlock_thread = id; // easy way
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlock_unlock(u32 id)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_lock);
|
||||||
|
|
||||||
|
if (wlock_thread == id)
|
||||||
|
{
|
||||||
|
wlock_thread = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
|
@ -15,7 +15,7 @@ struct SpuGroupInfo
|
||||||
{
|
{
|
||||||
CPUThread* threads[g_spu_group_thr_count];
|
CPUThread* threads[g_spu_group_thr_count];
|
||||||
sys_spu_thread_group_attribute& attr;
|
sys_spu_thread_group_attribute& attr;
|
||||||
volatile long lock;
|
std::atomic<u32> lock;
|
||||||
|
|
||||||
SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr), lock(0)
|
SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr), lock(0)
|
||||||
{
|
{
|
||||||
|
@ -259,7 +259,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_InterlockedCompareExchange(&group_info->lock, 1, 0)) //get lock
|
if (group_info->lock.exchange(1)) //get lock
|
||||||
{
|
{
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +275,7 @@ int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_InterlockedExchange(&group_info->lock, 0); //release lock
|
group_info->lock = 0; //release lock
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,7 @@
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
|
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.cpp" />
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Keyboard.cpp" />
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Keyboard.cpp" />
|
||||||
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwcond.cpp" />
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwmutex.cpp" />
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwmutex.cpp" />
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Memory.cpp" />
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Memory.cpp" />
|
||||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Mouse.cpp" />
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Mouse.cpp" />
|
||||||
|
|
|
@ -370,6 +370,9 @@
|
||||||
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp">
|
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp">
|
||||||
<Filter>Emu\SysCalls\Modules</Filter>
|
<Filter>Emu\SysCalls\Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwcond.cpp">
|
||||||
|
<Filter>Emu\SysCalls\lv2</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="rpcs3.rc" />
|
<ResourceCompile Include="rpcs3.rc" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue