mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
Bugs fixed, lwcond implementation
Modules: mutex added
This commit is contained in:
parent
67a144df2a
commit
6efe751d4c
7 changed files with 301 additions and 156 deletions
|
@ -1,11 +1,13 @@
|
|||
#include "stdafx.h"
|
||||
#include "SysCalls.h"
|
||||
#include "SC_FUNC.h"
|
||||
#include <mutex>
|
||||
|
||||
Module* g_modules[3][0xff] = {0};
|
||||
uint g_max_module_id = 0;
|
||||
uint g_module_2_count = 0;
|
||||
ArrayF<ModuleFunc> g_modules_funcs_list;
|
||||
std::mutex g_funcs_lock;
|
||||
|
||||
struct ModuleInfo
|
||||
{
|
||||
|
@ -142,20 +144,31 @@ bool IsLoadedFunc(u32 id)
|
|||
|
||||
bool CallFunc(u32 num)
|
||||
{
|
||||
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
|
||||
func_caller* func = nullptr;
|
||||
{
|
||||
if(g_modules_funcs_list[i].id == num)
|
||||
std::lock_guard<std::mutex> lock(g_funcs_lock);
|
||||
|
||||
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
|
||||
{
|
||||
(*g_modules_funcs_list[i].func)();
|
||||
return true;
|
||||
if(g_modules_funcs_list[i].id == num)
|
||||
{
|
||||
func = g_modules_funcs_list[i].func;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (func)
|
||||
{
|
||||
(*func)();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnloadFunc(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_funcs_lock);
|
||||
|
||||
for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
|
||||
{
|
||||
if(g_modules_funcs_list[i].id == id)
|
||||
|
@ -187,6 +200,7 @@ void UnloadModules()
|
|||
}
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(g_funcs_lock);
|
||||
g_modules_funcs_list.Clear();
|
||||
}
|
||||
|
||||
|
@ -318,8 +332,10 @@ void Module::Load()
|
|||
|
||||
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
|
||||
{
|
||||
if(IsLoadedFunc(m_funcs_list[i].id)) continue;
|
||||
std::lock_guard<std::mutex> lock(g_funcs_lock);
|
||||
|
||||
if(IsLoadedFunc(m_funcs_list[i].id)) continue;
|
||||
|
||||
g_modules_funcs_list.Add(m_funcs_list[i]);
|
||||
}
|
||||
|
||||
|
@ -343,6 +359,8 @@ void Module::UnLoad()
|
|||
|
||||
bool Module::Load(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_funcs_lock);
|
||||
|
||||
if(IsLoadedFunc(id)) return false;
|
||||
|
||||
for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
|
||||
|
|
|
@ -12,10 +12,20 @@ int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> l
|
|||
|
||||
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));
|
||||
u32 protocol = (u32)lwmutex->attribute & SYS_SYNC_ATTR_PROTOCOL_MASK;
|
||||
switch (protocol)
|
||||
{
|
||||
case SYS_SYNC_PRIORITY: break;
|
||||
case SYS_SYNC_RETRY: sys_lwcond.Error("Invalid SYS_SYNC_RETRY attr"); break;
|
||||
case SYS_SYNC_PRIORITY_INHERIT: sys_lwcond.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case SYS_SYNC_FIFO: break;
|
||||
default: sys_lwcond.Error("Invalid lwmutex protocol(%d)", protocol); break;
|
||||
}
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s]", attr->name);
|
||||
lwcond->lwmutex_addr = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(protocol, *(u64*)&attr->name));
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x)", attr->name, protocol);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -41,6 +51,8 @@ int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
|
|||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
|
||||
lwc->signal();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -53,6 +65,8 @@ int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
|
|||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
|
||||
lwc->signal_all();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -65,6 +79,8 @@ int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
|||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
|
||||
if (!lwc->signal_to(ppu_thread_id)) return CELL_EPERM;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -76,6 +92,40 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
|||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
mem_ptr_t<sys_lwmutex_t> lwmutex((u32)lwcond->lwmutex_addr);
|
||||
|
||||
return CELL_OK;
|
||||
if ((u32)lwmutex->owner != tid) return CELL_EPERM; // caller must own this lwmutex
|
||||
lwc->begin_waiting(tid);
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
bool was_locked = true;
|
||||
do
|
||||
{
|
||||
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||
if (was_locked) lwmutex->unlock(tid);
|
||||
Sleep(1);
|
||||
if (was_locked = (lwmutex->trylock(tid) == CELL_OK))
|
||||
{
|
||||
if (lwc->check(tid))
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
if (!timeout)
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x): TIMEOUT", lwcond.GetAddr());
|
||||
counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lwc->stop_waiting(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
|
|
@ -15,10 +15,104 @@ struct sys_lwcond_t
|
|||
|
||||
struct LWCond
|
||||
{
|
||||
u64 m_name;
|
||||
std::mutex m_lock;
|
||||
Array<u32> waiters; // list of waiting threads
|
||||
Array<u32> signaled; // list of signaled threads
|
||||
u32 m_protocol; // protocol
|
||||
u64 m_name; // not used
|
||||
|
||||
LWCond(u64 name)
|
||||
LWCond(u32 prot, u64 name)
|
||||
: m_name(name)
|
||||
, m_protocol(prot)
|
||||
{
|
||||
}
|
||||
|
||||
void signal()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (waiters.GetCount())
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
u64 max_prio = 0;
|
||||
u32 sel = 0;
|
||||
for (u32 i = 0; i < waiters.GetCount(); i++)
|
||||
{
|
||||
CPUThread* t = Emu.GetCPU().GetThread(waiters[i]);
|
||||
if (!t) continue;
|
||||
|
||||
u64 prio = t->GetPrio();
|
||||
if (prio > max_prio)
|
||||
{
|
||||
max_prio = prio;
|
||||
sel = i;
|
||||
}
|
||||
}
|
||||
signaled.AddCpy(waiters[sel]);
|
||||
waiters.RemoveAt(sel);
|
||||
}
|
||||
else // SYS_SYNC_FIFO
|
||||
{
|
||||
signaled.AddCpy(waiters[0]);
|
||||
waiters.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void signal_all()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
signaled.AppendFrom(waiters); // "nobody cares" protocol (!)
|
||||
waiters.Clear();
|
||||
}
|
||||
|
||||
bool signal_to(u32 id) // returns false if not found
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
for (u32 i = waiters.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (waiters[i] == id)
|
||||
{
|
||||
waiters.RemoveAt(i);
|
||||
signaled.AddCpy(id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void begin_waiting(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
waiters.AddCpy(id);
|
||||
}
|
||||
|
||||
void stop_waiting(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
for (u32 i = waiters.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (waiters[i] == id)
|
||||
{
|
||||
waiters.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool check(u32 id) // returns true if signaled
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
for (u32 i = signaled.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (signaled[i] == id)
|
||||
{
|
||||
signaled.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
|
@ -9,7 +9,7 @@ std::mutex g_lwmutex;
|
|||
|
||||
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr)
|
||||
{
|
||||
sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||
sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||
lwmutex.GetAddr(), attr.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||
|
@ -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: sc_lwmutex.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||
case SYS_SYNC_PRIORITY: sc_lwmutex.Warning("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;
|
||||
case SYS_SYNC_FIFO: sc_lwmutex.Warning("TODO: SYS_SYNC_FIFO attr"); break;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
|
||||
|
@ -36,14 +36,14 @@ 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] (attribute=0x%x)", attr->name, (u32)lwmutex->attribute);
|
||||
sc_lwmutex.Warning("*** 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.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
|
@ -54,6 +54,7 @@ int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
|||
|
||||
if (!lwmutex->owner)
|
||||
{
|
||||
lwmutex->owner = ~0; // make it unable to lock
|
||||
lwmutex->attribute = 0;
|
||||
}
|
||||
else
|
||||
|
@ -67,43 +68,16 @@ int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
|||
|
||||
int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
||||
{
|
||||
sc_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout);
|
||||
sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout);
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
const u32 id = thr.GetId();
|
||||
const u32 tid = GetCurrentPPUThread().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) // lock
|
||||
{
|
||||
lwmutex->owner = id;
|
||||
lwmutex->recursive_count = 1;
|
||||
return CELL_OK;
|
||||
}
|
||||
lwmutex->waiter = id; // not used yet
|
||||
}
|
||||
int res = lwmutex->trylock(tid);
|
||||
if (res != CELL_EBUSY) return res;
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
|
@ -112,17 +86,9 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
|||
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||
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
|
||||
}
|
||||
res = lwmutex->trylock(tid);
|
||||
if (res != CELL_EBUSY) return res;
|
||||
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
|
@ -141,79 +107,23 @@ int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout)
|
|||
|
||||
int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sc_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
if (!lwmutex->attribute) return CELL_EINVAL;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return lwmutex->trylock(GetCurrentPPUThread().GetId());
|
||||
}
|
||||
|
||||
int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sc_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
const u32 id = thr.GetId();
|
||||
if (!lwmutex->unlock(GetCurrentPPUThread().GetId())) return CELL_EPERM;
|
||||
|
||||
{ // 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;
|
||||
}
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ enum
|
|||
{
|
||||
// First In, First Out
|
||||
SYS_SYNC_FIFO = 1,
|
||||
// Priority Order (doesn't care?)
|
||||
// Priority Order
|
||||
SYS_SYNC_PRIORITY = 2,
|
||||
// Basic Priority Inheritance Protocol
|
||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
||||
|
@ -26,6 +26,15 @@ enum
|
|||
SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //???
|
||||
};
|
||||
|
||||
struct sys_lwmutex_attribute_t
|
||||
{
|
||||
be_t<u32> attr_protocol;
|
||||
be_t<u32> attr_recursive;
|
||||
char name[8];
|
||||
};
|
||||
|
||||
extern std::mutex g_lwmutex;
|
||||
|
||||
struct sys_lwmutex_t
|
||||
{
|
||||
union // sys_lwmutex_variable_t
|
||||
|
@ -44,11 +53,78 @@ struct sys_lwmutex_t
|
|||
be_t<u32> recursive_count;
|
||||
be_t<u32> sleep_queue;
|
||||
be_t<u32> pad;
|
||||
|
||||
int trylock(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock
|
||||
|
||||
if ((u32)attribute & SYS_SYNC_RECURSIVE)
|
||||
{
|
||||
if (tid == (u32)owner)
|
||||
{
|
||||
recursive_count = (u32)recursive_count + 1;
|
||||
if ((u32)recursive_count == 0xffffffff) return CELL_EKRESOURCE;
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
else // recursive not allowed
|
||||
{
|
||||
if (tid == (u32)owner)
|
||||
{
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(u32)owner) // try lock
|
||||
{
|
||||
owner = tid;
|
||||
recursive_count = 1;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
bool unlock(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_lwmutex); // global lock
|
||||
|
||||
if (tid != (u32)owner)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
recursive_count = (u32)recursive_count - 1;
|
||||
if (!(u32)recursive_count)
|
||||
{
|
||||
waiter = 0; // not used yet
|
||||
owner = 0; // release
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct sys_lwmutex_attribute_t
|
||||
struct lwmutex_locker
|
||||
{
|
||||
be_t<u32> attr_protocol;
|
||||
be_t<u32> attr_recursive;
|
||||
char name[8];
|
||||
private:
|
||||
mem_ptr_t<sys_lwmutex_t> m_mutex;
|
||||
u32 m_id;
|
||||
public:
|
||||
const int res;
|
||||
|
||||
lwmutex_locker(u32 lwmutex_addr, u32 tid)
|
||||
: m_id(tid)
|
||||
, m_mutex(lwmutex_addr)
|
||||
, res(m_mutex->trylock(m_id))
|
||||
{
|
||||
}
|
||||
|
||||
~lwmutex_locker()
|
||||
{
|
||||
if (res == CELL_OK) m_mutex->unlock(m_id);
|
||||
}
|
||||
};
|
|
@ -12,7 +12,7 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr
|
|||
|
||||
switch ((u32)attr->attr_protocol)
|
||||
{
|
||||
case SYS_SYNC_PRIORITY: sys_rwlock.Log("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||
case SYS_SYNC_PRIORITY: sys_rwlock.Warning("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;
|
||||
|
@ -55,10 +55,9 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
|||
|
||||
RWLock* rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
const u32 id = thr.GetId();
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (rw->rlock_trylock(id)) return CELL_OK;
|
||||
if (rw->rlock_trylock(tid)) return CELL_OK;
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
|
@ -67,7 +66,7 @@ int sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
|
|||
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||
Sleep(1);
|
||||
|
||||
if (rw->rlock_trylock(id)) return CELL_OK;
|
||||
if (rw->rlock_trylock(tid)) return CELL_OK;
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
|
@ -114,12 +113,11 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
|
|||
|
||||
RWLock* rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
const u32 id = thr.GetId();
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (!rw->wlock_check(id)) return CELL_EDEADLK;
|
||||
if (!rw->wlock_check(tid)) return CELL_EDEADLK;
|
||||
|
||||
if (rw->wlock_trylock(id, true)) return CELL_OK;
|
||||
if (rw->wlock_trylock(tid, true)) return CELL_OK;
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
|
@ -128,7 +126,7 @@ int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout)
|
|||
if (Emu.IsStopped()) return CELL_ETIMEDOUT;
|
||||
Sleep(1);
|
||||
|
||||
if (rw->wlock_trylock(id, true)) return CELL_OK;
|
||||
if (rw->wlock_trylock(tid, true)) return CELL_OK;
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
|
@ -151,12 +149,11 @@ int sys_rwlock_trywlock(u32 rw_lock_id)
|
|||
|
||||
RWLock* rw;
|
||||
if (!sys_rwlock.CheckId(rw_lock_id, rw)) return CELL_ESRCH;
|
||||
PPCThread& thr = GetCurrentPPUThread();
|
||||
const u32 id = thr.GetId();
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (!rw->wlock_check(id)) return CELL_EDEADLK;
|
||||
if (!rw->wlock_check(tid)) return CELL_EDEADLK;
|
||||
|
||||
if (!rw->wlock_trylock(id, false)) return CELL_EBUSY;
|
||||
if (!rw->wlock_trylock(tid, false)) return CELL_EBUSY;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -39,25 +39,25 @@ struct RWLock
|
|||
{
|
||||
}
|
||||
|
||||
bool rlock_trylock(u32 id)
|
||||
bool rlock_trylock(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (!wlock_thread && !wlock_queue.GetCount())
|
||||
{
|
||||
rlock_list.AddCpy(id);
|
||||
rlock_list.AddCpy(tid);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rlock_unlock(u32 id)
|
||||
bool rlock_unlock(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
for (u32 i = rlock_list.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (rlock_list[i] == id)
|
||||
if (rlock_list[i] == tid)
|
||||
{
|
||||
rlock_list.RemoveAt(i);
|
||||
return true;
|
||||
|
@ -66,17 +66,17 @@ struct RWLock
|
|||
return false;
|
||||
}
|
||||
|
||||
bool wlock_check(u32 id)
|
||||
bool wlock_check(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (wlock_thread == id)
|
||||
if (wlock_thread == tid)
|
||||
{
|
||||
return false; // deadlock
|
||||
}
|
||||
for (u32 i = rlock_list.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (rlock_list[i] == id)
|
||||
if (rlock_list[i] == tid)
|
||||
{
|
||||
return false; // deadlock
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ struct RWLock
|
|||
return true;
|
||||
}
|
||||
|
||||
bool wlock_trylock(u32 id, bool enqueue)
|
||||
bool wlock_trylock(u32 tid, bool enqueue)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
|
@ -96,12 +96,12 @@ struct RWLock
|
|||
}
|
||||
for (u32 i = wlock_queue.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (wlock_queue[i] == id)
|
||||
if (wlock_queue[i] == tid)
|
||||
{
|
||||
return false; // already enqueued
|
||||
}
|
||||
}
|
||||
wlock_queue.AddCpy(id); // enqueue new thread
|
||||
wlock_queue.AddCpy(tid); // enqueue new thread
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -109,9 +109,9 @@ struct RWLock
|
|||
if (wlock_queue.GetCount())
|
||||
{
|
||||
// SYNC_FIFO only yet
|
||||
if (wlock_queue[0] == id)
|
||||
if (wlock_queue[0] == tid)
|
||||
{
|
||||
wlock_thread = id;
|
||||
wlock_thread = tid;
|
||||
wlock_queue.RemoveAt(0);
|
||||
return true;
|
||||
}
|
||||
|
@ -123,28 +123,28 @@ struct RWLock
|
|||
}
|
||||
for (u32 i = wlock_queue.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (wlock_queue[i] == id)
|
||||
if (wlock_queue[i] == tid)
|
||||
{
|
||||
return false; // already enqueued
|
||||
}
|
||||
}
|
||||
wlock_queue.AddCpy(id); // enqueue new thread
|
||||
wlock_queue.AddCpy(tid); // enqueue new thread
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wlock_thread = id; // easy way
|
||||
wlock_thread = tid; // easy way
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wlock_unlock(u32 id)
|
||||
bool wlock_unlock(u32 tid)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (wlock_thread == id)
|
||||
if (wlock_thread == tid)
|
||||
{
|
||||
wlock_thread = 0;
|
||||
return true;
|
||||
|
|
Loading…
Add table
Reference in a new issue