mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
SC_Rwlock implementation, SC_Lwcond draft
Other small changes
This commit is contained in:
parent
4de64e5afe
commit
67a144df2a
@ -365,6 +365,8 @@ int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t<CellCodecEsFilterId
|
||||
|
||||
int cellPamfReaderGetStreamIndex(mem_ptr_t<CellPamfReader> pSelf)
|
||||
{
|
||||
cellPamf.Log("cellPamfReaderGetStreamIndex(pSelf=0x%x)", pSelf.GetAddr());
|
||||
|
||||
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)
|
||||
{
|
||||
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());
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -175,4 +175,11 @@ void sysPrxForUser_init()
|
||||
|
||||
sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_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_SPU_Thread.h"
|
||||
#include "lv2/SC_Lwmutex.h"
|
||||
#include "lv2/SC_Lwcond.h"
|
||||
#include "Emu/event.h"
|
||||
//#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_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
|
||||
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);
|
||||
|
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)
|
||||
{
|
||||
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;
|
||||
case SYS_SYNC_PRIORITY: sc_lwmutex.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||
case SYS_SYNC_RETRY: sc_lwmutex.Warning("TODO: SYS_SYNC_RETRY attr"); break;
|
||||
case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case SYS_SYNC_FIFO: sc_lwmutex.Log("TODO: SYS_SYNC_FIFO attr"); break;
|
||||
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->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);
|
||||
sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -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->attribute) return CELL_EINVAL;
|
||||
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
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
|
||||
{
|
||||
lwmutex->owner = id;
|
||||
lwmutex->owner = id;
|
||||
lwmutex->recursive_count = 1;
|
||||
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;
|
||||
do // waiting
|
||||
{
|
||||
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||
Sleep(1);
|
||||
|
||||
{ // global lock
|
||||
@ -108,9 +127,9 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
if (!timeout)
|
||||
{ // endless waiter
|
||||
sc_lwmutex.Error("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
|
||||
return CELL_OK;
|
||||
{
|
||||
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr());
|
||||
counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -126,6 +145,8 @@ int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
return CELL_OK;
|
||||
sys_rwlock.Warning("sys_rwlock_rlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
return CELL_OK;
|
||||
sys_rwlock.Warning("sys_rwlock_wlock(rw_lock_id=%d, timeout=%llu)", rw_lock_id, timeout);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -2,11 +2,153 @@
|
||||
|
||||
struct sys_rwlock_attribute_t
|
||||
{
|
||||
u32 attr_protocol; //sys_protocol_t
|
||||
u32 attr_pshared; //sys_process_shared_t
|
||||
u64 key; //sys_ipc_key_t
|
||||
s32 flags;
|
||||
u8 name[8];
|
||||
be_t<u32> attr_protocol;
|
||||
be_t<u32> attr_pshared; // == 0x200 (NOT SHARED)
|
||||
be_t<u64> key; // process-shared key (not used)
|
||||
be_t<s32> flags; // process-shared flags (not used)
|
||||
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];
|
||||
sys_spu_thread_group_attribute& attr;
|
||||
volatile long lock;
|
||||
std::atomic<u32> lock;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (_InterlockedCompareExchange(&group_info->lock, 1, 0)) //get lock
|
||||
if (group_info->lock.exchange(1)) //get lock
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -249,6 +249,7 @@
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_GCM.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Heap.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_Memory.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Mouse.cpp" />
|
||||
|
@ -370,6 +370,9 @@
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Lwcond.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
|
Loading…
Reference in New Issue
Block a user