mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-15 11:18:36 +12:00
SMutex eliminated
This commit is contained in:
parent
0fb092f2a5
commit
b2de24db73
48 changed files with 768 additions and 907 deletions
|
@ -3,33 +3,36 @@
|
|||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
#include "Utilities/SMutex.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sys_lwmutex.h"
|
||||
#include "sleep_queue_type.h"
|
||||
#include "sys_time.h"
|
||||
#include "sys_mutex.h"
|
||||
|
||||
SysCallBase sys_mutex("sys_mutex");
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
if (u32 owner = m_mutex.GetOwner())
|
||||
if (u32 tid = owner.read_sync())
|
||||
{
|
||||
sys_mutex.Notice("Mutex(%d) was owned by thread %d (recursive=%d)", id, owner, recursive);
|
||||
sys_mutex.Notice("Mutex(%d) was owned by thread %d (recursive=%d)", id, tid, recursive);
|
||||
}
|
||||
|
||||
if (!m_queue.m_mutex.try_lock()) return;
|
||||
if (!queue.m_mutex.try_lock()) return;
|
||||
|
||||
for (u32 i = 0; i < m_queue.list.size(); i++)
|
||||
for (u32 i = 0; i < queue.list.size(); i++)
|
||||
{
|
||||
if (u32 owner = m_queue.list[i]) sys_mutex.Notice("Mutex(%d) was waited by thread %d", id, owner);
|
||||
if (u32 owner = queue.list[i])
|
||||
{
|
||||
sys_mutex.Notice("Mutex(%d) was waited by thread %d", id, owner);
|
||||
}
|
||||
}
|
||||
|
||||
m_queue.m_mutex.unlock();
|
||||
queue.m_mutex.unlock();
|
||||
}
|
||||
|
||||
s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
||||
s32 sys_mutex_create(PPUThread& CPU, vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.addr(), attr.addr());
|
||||
|
||||
|
@ -58,13 +61,10 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
|||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
Mutex* mutex = new Mutex((u32)attr->protocol, is_recursive, attr->name_u64);
|
||||
u32 id = sys_mutex.GetNewId(mutex, TYPE_MUTEX);
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->id = id;
|
||||
const u32 id = sys_mutex.GetNewId(mutex, TYPE_MUTEX);
|
||||
mutex->id.exchange(id);
|
||||
*mutex_id = id;
|
||||
mutex->m_mutex.unlock(tid);
|
||||
sys_mutex.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d",
|
||||
std::string(attr->name, 8).c_str(), (u32) attr->protocol, (is_recursive ? "true" : "false"), id);
|
||||
|
||||
|
@ -74,7 +74,7 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute> attr)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_destroy(u32 mutex_id)
|
||||
s32 sys_mutex_destroy(PPUThread& CPU, u32 mutex_id)
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_destroy(mutex_id=%d)", mutex_id);
|
||||
|
||||
|
@ -91,26 +91,32 @@ s32 sys_mutex_destroy(u32 mutex_id)
|
|||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.trylock(tid)) // check if locked
|
||||
if (mutex->owner.compare_and_swap_test(0, tid)) // check if locked
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
if (!mutex->m_queue.finalize())
|
||||
if (!mutex->queue.finalize())
|
||||
{
|
||||
mutex->m_mutex.unlock(tid);
|
||||
if (!mutex->owner.compare_and_swap_test(tid, 0))
|
||||
{
|
||||
assert(!"sys_mutex_destroy() failed (busy)");
|
||||
}
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
mutex->m_mutex.unlock(tid, ~0);
|
||||
if (!mutex->owner.compare_and_swap_test(tid, ~0))
|
||||
{
|
||||
assert(!"sys_mutex_destroy() failed");
|
||||
}
|
||||
Emu.GetIdManager().RemoveID(mutex_id);
|
||||
Emu.GetSyncPrimManager().EraseSyncPrimData(TYPE_MUTEX, mutex_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_lock(mutex_id=%d, timeout=%lld)", mutex_id, timeout);
|
||||
|
||||
|
@ -120,14 +126,13 @@ s32 sys_mutex_lock(u32 mutex_id, u64 timeout)
|
|||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
if (mutex->owner.read_sync() == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
if (++mutex->recursive == 0)
|
||||
if (!++mutex->recursive)
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
|
@ -138,48 +143,51 @@ s32 sys_mutex_lock(u32 mutex_id, u64 timeout)
|
|||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
else if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mutex->m_mutex.trylock(tid))
|
||||
if (mutex->owner.compare_and_swap_test(0, tid))
|
||||
{
|
||||
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||
case SMR_FAILED: break;
|
||||
default: goto abort;
|
||||
}
|
||||
|
||||
mutex->m_queue.push(tid);
|
||||
|
||||
switch (mutex->m_mutex.lock(tid, timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0))
|
||||
{
|
||||
case SMR_OK:
|
||||
mutex->m_queue.invalidate(tid);
|
||||
case SMR_SIGNAL:
|
||||
mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||
case SMR_TIMEOUT:
|
||||
mutex->m_queue.invalidate(tid); return CELL_ETIMEDOUT;
|
||||
default:
|
||||
mutex->m_queue.invalidate(tid); goto abort;
|
||||
}
|
||||
|
||||
abort:
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_lock(id=%d) aborted", mutex_id);
|
||||
mutex->recursive = 1;
|
||||
CPU.owned_mutexes++;
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_ESRCH;
|
||||
|
||||
mutex->queue.push(tid, mutex->protocol);
|
||||
|
||||
const u64 time_start = get_system_time();
|
||||
while (true)
|
||||
{
|
||||
auto old_owner = mutex->owner.compare_and_swap(0, tid);
|
||||
if (!old_owner)
|
||||
{
|
||||
mutex->queue.invalidate(tid);
|
||||
break;
|
||||
}
|
||||
if (old_owner == tid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
if (timeout && get_system_time() - time_start > timeout)
|
||||
{
|
||||
mutex->queue.invalidate(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
sys_mutex.Warning("sys_mutex_lock(id=%d) aborted", mutex_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
mutex->recursive = 1;
|
||||
CPU.owned_mutexes++;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_trylock(u32 mutex_id)
|
||||
s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_trylock(mutex_id=%d)", mutex_id);
|
||||
|
||||
|
@ -189,14 +197,13 @@ s32 sys_mutex_trylock(u32 mutex_id)
|
|||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
if (mutex->owner.read_sync() == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
if (++mutex->recursive == 0)
|
||||
if (!++mutex->recursive)
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
|
@ -207,25 +214,18 @@ s32 sys_mutex_trylock(u32 mutex_id)
|
|||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
else if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
|
||||
if (!mutex->owner.compare_and_swap_test(0, tid))
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
}
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
switch (mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||
default: return CELL_EBUSY;
|
||||
}
|
||||
mutex->recursive = 1;
|
||||
CPU.owned_mutexes++;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mutex_unlock(u32 mutex_id)
|
||||
s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id)
|
||||
{
|
||||
sys_mutex.Log("sys_mutex_unlock(mutex_id=%d)", mutex_id);
|
||||
|
||||
|
@ -235,24 +235,26 @@ s32 sys_mutex_unlock(u32 mutex_id)
|
|||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
const u32 tid = CPU.GetId();
|
||||
|
||||
if (mutex->m_mutex.unlock(tid, tid) == SMR_OK)
|
||||
if (mutex->owner.read_sync() != tid)
|
||||
{
|
||||
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive);
|
||||
mutex->recursive = 1;
|
||||
}
|
||||
mutex->recursive--;
|
||||
if (!mutex->recursive)
|
||||
{
|
||||
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
||||
t.owned_mutexes--;
|
||||
}
|
||||
return CELL_OK;
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
return CELL_EPERM;
|
||||
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
|
||||
{
|
||||
sys_mutex.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive);
|
||||
mutex->recursive = 1;
|
||||
}
|
||||
|
||||
if (!--mutex->recursive)
|
||||
{
|
||||
if (!mutex->owner.compare_and_swap_test(tid, mutex->queue.pop(mutex->protocol)))
|
||||
{
|
||||
assert(!"sys_mutex_unlock() failed");
|
||||
}
|
||||
CPU.owned_mutexes--;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue