From 0fb092f2a5f8237d7d8da489cf2b8727605064f0 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 22 Dec 2014 03:56:04 +0300 Subject: [PATCH] Syscalls: minor fixes --- rpcs3/Emu/Cell/SPURSManager.h | 2 - rpcs3/Emu/Cell/SPUThread.cpp | 1 + rpcs3/Emu/Cell/SPUThread.h | 7 +- rpcs3/Emu/Event.cpp | 6 +- rpcs3/Emu/Event.h | 3 +- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 6 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 4 + rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 3 - rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp | 5 + rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 4 + rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 2 + rpcs3/Emu/SysCalls/SysCalls.cpp | 4 + rpcs3/Emu/SysCalls/lv2/sys_cond.cpp | 16 +-- rpcs3/Emu/SysCalls/lv2/sys_cond.h | 1 - rpcs3/Emu/SysCalls/lv2/sys_event.cpp | 3 + rpcs3/Emu/SysCalls/lv2/sys_event.h | 3 +- rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp | 2 + rpcs3/Emu/SysCalls/lv2/sys_event_flag.h | 2 - rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp | 34 ++--- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 137 +++++++++---------- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h | 11 +- rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp | 3 + rpcs3/Emu/SysCalls/lv2/sys_mutex.h | 1 - rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp | 1 + rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp | 2 + rpcs3/Emu/SysCalls/lv2/sys_semaphore.h | 2 - rpcs3/Emu/SysCalls/lv2/sys_timer.cpp | 1 + 27 files changed, 144 insertions(+), 122 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURSManager.h b/rpcs3/Emu/Cell/SPURSManager.h index 001d244fa7..55bf5de181 100644 --- a/rpcs3/Emu/Cell/SPURSManager.h +++ b/rpcs3/Emu/Cell/SPURSManager.h @@ -1,7 +1,5 @@ #pragma once -#include "Emu/SysCalls/Modules/cellSpurs.h" - class SPURSManagerEventFlag { public: diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 719cdc8cab..f82a84f683 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -8,6 +8,7 @@ #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" #include "Emu/SysCalls/ErrorCodes.h" +#include "Utilities/SMutex.h" #include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/SysCalls/lv2/sys_event_flag.h" #include "Emu/SysCalls/lv2/sys_time.h" diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index aaffd7d00d..b64573e17f 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -1,10 +1,13 @@ #pragma once +#include "Utilities/SMutex.h" #include "Emu/Memory/atomic_type.h" #include "PPCThread.h" +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_event.h" #include "Emu/Event.h" #include "MFC.h" -enum SPUchannels +enum SPUchannels { SPU_RdEventStat = 0, //Read event status with mask applied SPU_WrEventMask = 1, //Write event mask @@ -22,7 +25,7 @@ enum SPUchannels SPU_WrOutIntrMbox = 30, //Write outbound interrupt mailbox contents (interrupting PPU) }; -enum MFCchannels +enum MFCchannels { MFC_WrMSSyncReq = 9, //Write multisource synchronization request MFC_RdTagMask = 12, //Read tag mask diff --git a/rpcs3/Emu/Event.cpp b/rpcs3/Emu/Event.cpp index 5dce5b6884..b8485942b9 100644 --- a/rpcs3/Emu/Event.cpp +++ b/rpcs3/Emu/Event.cpp @@ -1,6 +1,10 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" -//#include "Emu/System.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" + +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_event.h" #include "Event.h" void EventManager::Init() diff --git a/rpcs3/Emu/Event.h b/rpcs3/Emu/Event.h index 31a33e3db5..a1f27901c8 100644 --- a/rpcs3/Emu/Event.h +++ b/rpcs3/Emu/Event.h @@ -1,7 +1,8 @@ #pragma once -#include "Emu/SysCalls/lv2/sys_event.h" #include +struct EventQueue; + class EventManager { std::mutex m_lock; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index f302a9fc2f..7ace6e1414 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -2,11 +2,15 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/Memory/atomic_type.h" #include "rpcs3/Ini.h" #include "Utilities/SQueue.h" -#include "Emu/Event.h" +#include "Utilities/SMutex.h" #include "Emu/SysCalls/lv2/sys_time.h" +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_event.h" +#include "Emu/Event.h" #include "Emu/Audio/AudioManager.h" #include "Emu/Audio/AudioDumper.h" #include "Emu/Audio/cellAudio.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index d4735492da..6d432a18a4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -3,8 +3,12 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/CB_FUNC.h" +#include "Emu/Memory/atomic_type.h" #include "Emu/Cell/SPUThread.h" +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_lwcond.h" +#include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/SysCalls/lv2/sys_ppu_thread.h" #include "Emu/SysCalls/lv2/sys_memory.h" #include "Emu/SysCalls/lv2/sys_process.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 4e72b50826..d546474c1a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -1,7 +1,4 @@ #pragma once -#include "Emu/SysCalls/lv2/sys_lwmutex.h" -#include "Emu/SysCalls/lv2/sys_lwcond.h" -#include "Emu/SysCalls/lv2/sys_spu.h" // Core return codes. enum diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp index c1ad643060..e1094c6cd9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursJq.cpp @@ -2,7 +2,12 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_lwcond.h" +#include "Emu/SysCalls/lv2/sys_spu.h" #include "cellSpurs.h" #include "cellSpursJq.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index afac57e65e..6534688cbd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -3,7 +3,11 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/CB_FUNC.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" +#include "Emu/SysCalls/lv2/sys_lwmutex.h" +#include "Emu/SysCalls/lv2/sys_event.h" #include "Emu/SysCalls/lv2/sys_process.h" #include "Emu/Event.h" #include "cellSync.h" diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 987877493f..ff2e042147 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -3,6 +3,8 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/CB_FUNC.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" #include "Emu/FS/vfsFile.h" #include "Emu/SysCalls/lv2/sys_spu.h" diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index af6777ecff..bf4e2ebc31 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -5,8 +5,12 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "ModuleManager.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" #include "lv2/lv2Fs.h" +#include "lv2/sys_lwmutex.h" +#include "lv2/sys_mutex.h" #include "lv2/sys_cond.h" #include "lv2/sys_event.h" #include "lv2/sys_event_flag.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp index ab53f0699a..c6c71ed9a9 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp @@ -2,9 +2,13 @@ #include "Emu/Memory/Memory.h" #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 "sys_mutex.h" #include "sys_cond.h" SysCallBase sys_cond("sys_cond"); @@ -28,11 +32,6 @@ s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptris_recursive) - { - sys_cond.Warning("*** condition on recursive mutex(%d)", mutex_id); - } - Cond* cond = new Cond(mutex, attr->name_u64); u32 id = sys_cond.GetNewId(cond, TYPE_COND); *cond_id = id; @@ -175,10 +174,7 @@ s32 sys_cond_wait(u32 cond_id, u64 timeout) cond->m_queue.push(tid); - if (mutex->recursive != 1) - { - sys_cond.Warning("sys_cond_wait(cond_id=%d): associated mutex had wrong recursive value (%d)", cond_id, mutex->recursive); - } + auto old_recursive = mutex->recursive; mutex->recursive = 0; mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop()); @@ -207,7 +203,7 @@ s32 sys_cond_wait(u32 cond_id, u64 timeout) goto abort; } } - mutex->recursive = 1; + mutex->recursive = old_recursive; cond->signal.unlock(tid); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.h b/rpcs3/Emu/SysCalls/lv2/sys_cond.h index f1278a484d..faed699815 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.h @@ -1,5 +1,4 @@ #pragma once -#include "sys_mutex.h" struct sys_cond_attribute { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index 701c827c40..69d2add6f7 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -2,9 +2,12 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" #include "Emu/Cell/PPUThread.h" #include "Emu/Event.h" +#include "sys_lwmutex.h" #include "sys_process.h" #include "sys_event.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.h b/rpcs3/Emu/SysCalls/lv2/sys_event.h index 61180f5982..2dac0184b9 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.h @@ -1,6 +1,7 @@ #pragma once -#include "sys_lwmutex.h" +//#include "sys_lwmutex.h" +//#include "Utilities/SMutex.h" #define FIX_SPUQ(x) ((u64)x | 0x5350555100000000ULL) // arbitrary code to prevent "special" zero value in key argument diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp index 9a0da23fe6..80fe3c0738 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp @@ -2,6 +2,8 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" #include "Emu/Cell/PPUThread.h" #include "sys_lwmutex.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h index 05309fb748..51f4fcb03e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.h @@ -1,7 +1,5 @@ #pragma once -#include "Utilities/SMutex.h" - enum { SYS_SYNC_WAITER_SINGLE = 0x10000, diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index a7d277977b..0cd6b28401 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -2,6 +2,8 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" +#include "Utilities/SMutex.h" #include "Emu/Cell/PPUThread.h" #include "sys_lwmutex.h" @@ -161,9 +163,15 @@ s32 sys_lwcond_wait(vm::ptr lwcond, u64 timeout) be_t tid = be_t::make(tid_le); SleepQueue* sq = nullptr; - Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq); + if (!Emu.GetIdManager().GetIDData((u32)mutex->sleep_queue, sq) && mutex->attribute.ToBE() != se32(SYS_SYNC_RETRY)) + { + sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had invalid sleep queue (%d)", + (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); + return CELL_ESRCH; + } - if (mutex->mutex.GetOwner() != tid) + auto old_owner = mutex->mutex.read_sync(); + if (old_owner != tid) { sys_lwcond.Warning("sys_lwcond_wait(id=%d) failed (EPERM)", (u32)lwcond->lwcond_queue); return CELL_EPERM; // caller must own this lwmutex @@ -171,25 +179,13 @@ s32 sys_lwcond_wait(vm::ptr lwcond, u64 timeout) lw->m_queue.push(tid_le); - if (mutex->recursive_count.ToBE() != se32(1)) - { - sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had wrong recursive value (%d)", - (u32)lwcond->lwcond_queue, (u32)mutex->recursive_count); - } + auto old_recursive = mutex->recursive_count; mutex->recursive_count = 0; - if (sq) + be_t target = sq ? (be_t::make(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())) : be_t::make(0); + if (!mutex->mutex.compare_and_swap_test(tid, target)) { - mutex->mutex.unlock(tid, be_t::make(mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())); - } - else if (mutex->attribute.ToBE() == se32(SYS_SYNC_RETRY)) - { - mutex->mutex.unlock(tid); // SYS_SYNC_RETRY - } - else - { - sys_lwcond.Warning("sys_lwcond_wait(id=%d): associated mutex had invalid sleep queue (%d)", - (u32)lwcond->lwcond_queue, (u32)mutex->sleep_queue); + assert(!"sys_lwcond_wait(): mutex unlocking failed"); } u64 counter = 0; @@ -209,7 +205,7 @@ s32 sys_lwcond_wait(vm::ptr lwcond, u64 timeout) case static_cast(CELL_EINVAL): goto abort; } - mutex->recursive_count = 1; + mutex->recursive_count = old_recursive; lw->signal.unlock(tid); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index c6a08033bd..dd78b03030 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -2,9 +2,11 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" +#include "sys_time.h" #include "sys_lwmutex.h" SysCallBase sys_lwmutex("sys_lwmutex"); @@ -15,8 +17,8 @@ s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name { LV2_LOCK(0); - lwmutex.waiter = ~0; - lwmutex.mutex.initialize(); + lwmutex.mutex.write_relaxed(be_t::make(0)); + lwmutex.waiter.write_relaxed(be_t::make(~0)); lwmutex.attribute = protocol | recursive; lwmutex.recursive_count = 0; u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(name_u64), TYPE_LWMUTEX); @@ -63,7 +65,7 @@ s32 sys_lwmutex_destroy(vm::ptr lwmutex) if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH; // try to make it unable to lock - switch (int res = lwmutex->trylock(lwmutex->mutex.GetDeadValue())) + switch (int res = lwmutex->trylock(be_t::make(~0))) { case CELL_OK: lwmutex->all_info() = 0; @@ -79,10 +81,7 @@ s32 sys_lwmutex_lock(vm::ptr lwmutex, u64 timeout) { sys_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.addr(), timeout); - //ConLog.Write("*** lock mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)", - //lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter); - - return lwmutex->lock(be_t::make(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0); + return lwmutex->lock(be_t::make(GetCurrentPPUThread().GetId()), timeout); } s32 sys_lwmutex_trylock(vm::ptr lwmutex) @@ -96,9 +95,6 @@ s32 sys_lwmutex_unlock(vm::ptr lwmutex) { sys_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.addr()); - //ConLog.Write("*** unlocking mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)", - //lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, (u32)lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter); - return lwmutex->unlock(be_t::make(GetCurrentPPUThread().GetId())); } @@ -219,43 +215,11 @@ bool SleepQueue::finalize() return true; } -int sys_lwmutex_t::trylock(be_t tid) +s32 sys_lwmutex_t::trylock(be_t tid) { if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL; - be_t owner_tid = mutex.GetFreeValue(); - - if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value - { - owner_tid = mutex.GetOwner(); - /*if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid)) - { - if (!tt->IsAlive()) - { - sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid); - mutex.unlock(owner_tid, tid); - recursive_count = 1; - return CELL_OK; - } - } - else - { - sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid); - mutex.unlock(owner_tid, tid); - recursive_count = 1; - return CELL_OK; - }*/ - } - - /*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0) - { - if (Emu.IsStopped()) - { - LOG_WARNING(HLE, "(hack) sys_lwmutex_t::(try)lock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute); - return CELL_ESRCH; - } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - }*/ + be_t owner_tid = mutex.read_sync(); if (tid == owner_tid) { @@ -271,17 +235,18 @@ int sys_lwmutex_t::trylock(be_t tid) } } - switch (mutex.trylock(tid)) + if (!mutex.compare_and_swap_test(be_t::make(0), tid)) { - case SMR_OK: recursive_count = 1; return CELL_OK; - case SMR_FAILED: return CELL_EBUSY; - default: return CELL_EINVAL; + return CELL_EBUSY; } + + recursive_count = 1; + return CELL_OK; } -int sys_lwmutex_t::unlock(be_t tid) +s32 sys_lwmutex_t::unlock(be_t tid) { - if (mutex.unlock(tid, tid) != SMR_OK) + if (mutex.read_sync() != tid) { return CELL_EPERM; } @@ -292,6 +257,7 @@ int sys_lwmutex_t::unlock(be_t tid) sys_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value fixed (%d)", (u32)sleep_queue, (u32)recursive_count); recursive_count = 1; } + recursive_count -= 1; if (!recursive_count.ToBE()) { @@ -300,48 +266,79 @@ int sys_lwmutex_t::unlock(be_t tid) { case se32(SYS_SYNC_FIFO): case se32(SYS_SYNC_PRIORITY): + { SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH; + if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) + { + return CELL_ESRCH; + } + target = attribute & SYS_SYNC_FIFO ? sq->pop() : sq->pop_prio(); - case se32(SYS_SYNC_RETRY): break; } - if (target) mutex.unlock(tid, target); - else mutex.unlock(tid); + } + + if (!mutex.compare_and_swap_test(tid, target)) + { + assert(!"sys_lwmutex_t::unlock() failed"); + } } + return CELL_OK; } } -int sys_lwmutex_t::lock(be_t tid, u64 timeout) +s32 sys_lwmutex_t::lock(be_t tid, u64 timeout) { - switch (int res = trylock(tid)) + switch (s32 res = trylock(tid)) { - case static_cast(CELL_EBUSY): break; + case static_cast(CELL_EBUSY): break; default: return res; } SleepQueue* sq; - if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH; + if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) + { + return CELL_ESRCH; + } switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK)) { case se32(SYS_SYNC_PRIORITY): case se32(SYS_SYNC_FIFO): + { sq->push(tid); - default: break; + } } - switch (mutex.lock(tid, timeout)) + const u64 time_start = get_system_time(); + while (true) { - case SMR_OK: - sq->invalidate(tid); - case SMR_SIGNAL: - recursive_count = 1; return CELL_OK; - case SMR_TIMEOUT: - sq->invalidate(tid); return CELL_ETIMEDOUT; - case SMR_ABORT: - if (Emu.IsStopped()) sys_lwmutex.Warning("sys_lwmutex_t::lock(sq=%d) aborted", (u32)sleep_queue); - default: - sq->invalidate(tid); return CELL_EINVAL; + auto old_owner = mutex.compare_and_swap(be_t::make(0), tid); + if (!old_owner.ToBE()) + { + sq->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) + { + sq->invalidate(tid); + return CELL_ETIMEDOUT; + } + + if (Emu.IsStopped()) + { + sys_lwmutex.Warning("sys_lwmutex_t::lock(sq=%d) aborted", (u32)sleep_queue); + return CELL_OK; + } } + + recursive_count = 1; + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h index 16a2381f60..354b9082bd 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.h @@ -1,5 +1,4 @@ #pragma once -#include // attr_protocol (waiting scheduling policy) enum @@ -66,8 +65,8 @@ struct SleepQueue struct sys_lwmutex_t { - SMutexBase> mutex; - be_t waiter; // currently not used + atomic_t mutex; + atomic_t waiter; // currently not used be_t attribute; be_t recursive_count; be_t sleep_queue; @@ -78,9 +77,9 @@ struct sys_lwmutex_t return *(reinterpret_cast(this)); } - int trylock(be_t tid); - int unlock(be_t tid); - int lock(be_t tid, u64 timeout); + s32 trylock(be_t tid); + s32 unlock(be_t tid); + s32 lock(be_t tid, u64 timeout); }; // Aux diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp index f22dd97d87..6bf9439f02 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp @@ -2,9 +2,12 @@ #include "Emu/Memory/Memory.h" #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 "sys_mutex.h" SysCallBase sys_mutex("sys_mutex"); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h index 74a7378e63..6a8843fb68 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h @@ -1,5 +1,4 @@ #pragma once -#include "sys_lwmutex.h" struct sys_mutex_attribute { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp index b35ff563ff..b4c9f8e77b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" #include "Emu/Cell/PPUThread.h" #include "sys_lwmutex.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp index d194a0b563..ab1de1d1b6 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp @@ -2,9 +2,11 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" +#include "sys_lwmutex.h" #include "sys_time.h" #include "sys_semaphore.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h index 19956ad377..30d034cea2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.h @@ -1,7 +1,5 @@ #pragma once -#include "sys_lwmutex.h" - struct sys_semaphore_attribute { be_t protocol; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp index c2f5d259d7..76cce5c01f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/Memory/atomic_type.h" #include "Emu/Event.h" #include "sys_timer.h"