From ef65299dff61cce3cfd33288692cb26ef4eb61a4 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Mar 2015 01:10:04 +0300 Subject: [PATCH] Lv2 Cond/Mutex rewritten, bugfixes --- Utilities/Thread.cpp | 48 ++++ rpcs3/Emu/CPU/CPUThreadManager.cpp | 2 +- rpcs3/Emu/Cell/SPUThread.cpp | 12 +- rpcs3/Emu/IdManager.h | 61 +++-- rpcs3/Emu/SysCalls/Modules.cpp | 20 -- rpcs3/Emu/SysCalls/Modules.h | 38 ---- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp | 13 +- rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp | 13 +- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellVpost.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 10 +- rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp | 8 +- rpcs3/Emu/SysCalls/SysCalls.cpp | 18 -- rpcs3/Emu/SysCalls/SysCalls.h | 39 +--- rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 55 +++-- rpcs3/Emu/SysCalls/lv2/sys_cond.cpp | 163 +++++++------- rpcs3/Emu/SysCalls/lv2/sys_cond.h | 25 ++- rpcs3/Emu/SysCalls/lv2/sys_event.cpp | 28 +-- rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp | 29 +-- rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_memory.cpp | 11 +- rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp | 15 +- rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp | 223 +++++++++---------- rpcs3/Emu/SysCalls/lv2/sys_mutex.h | 41 ++-- rpcs3/Emu/SysCalls/lv2/sys_prx.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp | 16 +- rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_timer.cpp | 16 +- rpcs3/Emu/SysCalls/lv2/sys_vm.cpp | 2 +- 35 files changed, 425 insertions(+), 507 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index cb0af16729..5763b8e7d4 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -116,6 +116,7 @@ enum x64_op_t : u32 X64OP_STOS, X64OP_XCHG, X64OP_CMPXCHG, + X64OP_LOAD_AND_STORE, }; void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, size_t& out_size, size_t& out_length) @@ -310,6 +311,30 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz break; } + case 0x20: + { + if (!oso) + { + out_op = X64OP_LOAD_AND_STORE; + out_reg = rex & 8 ? get_modRM_reg(code, rex) : get_modRM_reg_lh(code); + out_size = 1; + out_length += get_modRM_size(code); + return; + } + break; + } + case 0x21: + { + if (true) + { + out_op = X64OP_LOAD_AND_STORE; + out_reg = get_modRM_reg(code, rex); + out_size = get_op_size(rex, oso); + out_length += get_modRM_size(code); + return; + } + break; + } case 0x86: { if (!oso) // XCHG r8/m8, r8 @@ -1013,6 +1038,29 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) } break; } + case X64OP_LOAD_AND_STORE: + { + u64 value; + if (!get_x64_reg_value(context, reg, d_size, i_size, value)) + { + return false; + } + + switch (d_size) + { + case 1: value = vm::priv_ref>(addr) &= value; break; + case 2: value = vm::priv_ref>(addr) &= value; break; + case 4: value = vm::priv_ref>(addr) &= value; break; + case 8: value = vm::priv_ref>(addr) &= value; break; + default: return false; + } + + if (!set_x64_cmp_flags(context, d_size, value, 0)) + { + return false; + } + break; + } default: { LOG_ERROR(MEMORY, "Invalid or unsupported operation (op=%d, reg=%d, d_size=%lld, a_size=0x%llx, i_size=%lld)", op, reg, d_size, a_size, i_size); diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index 603c58e635..575899f5ff 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -67,7 +67,7 @@ std::shared_ptr CPUThreadManager::AddThread(CPUThreadType type) if (new_thread) { - new_thread->SetId(Emu.GetIdManager().GetNewID(new_thread->GetTypeString() + " Thread", new_thread)); + new_thread->SetId(Emu.GetIdManager().GetNewID(new_thread)); m_threads.push_back(new_thread); SendDbgCommand(DID_CREATE_THREAD, new_thread.get()); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index cc2a7b0d09..5ccec5fcc5 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -991,15 +991,13 @@ void SPUThread::stop_and_signal(u32 code) } // protocol is ignored in current implementation - queue->waiters++; - assert(queue->waiters > 0); + queue->waiters++; assert(queue->waiters > 0); while (queue->events.empty()) { if (queue->waiters < 0) { - queue->waiters--; - assert(queue->waiters < 0); + queue->waiters--; assert(queue->waiters < 0); ch_in_mbox.push_uncond(CELL_ECANCELED); return; } @@ -1020,8 +1018,7 @@ void SPUThread::stop_and_signal(u32 code) ch_in_mbox.push_uncond((u32)event.data3); queue->events.pop_front(); - queue->waiters--; - assert(queue->waiters >= 0); + queue->waiters--; assert(queue->waiters >= 0); if (queue->events.size()) { @@ -1050,7 +1047,8 @@ void SPUThread::stop_and_signal(u32 code) LV2_LOCK; std::shared_ptr group = tg.lock(); - if (group) + + if (!group) { LOG_ERROR(SPU, "sys_spu_thread_group_exit(status=0x%x): invalid group", value); throw __FUNCTION__; diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index ac066d142f..b82722f829 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -48,60 +48,56 @@ public: m_destr(m_ptr); } - template std::shared_ptr get() + template std::shared_ptr get() const { return *(std::shared_ptr*)m_ptr; } - - template std::shared_ptr get() const - { - return *(std::shared_ptr*)m_ptr; - } }; class ID { - std::string m_name; + const std::type_info& m_info; IDData* m_data; IDType m_type; public: template - ID(const std::string& name, std::shared_ptr& data, const IDType type) - : m_name(name) + ID(std::shared_ptr& data, const IDType type) + : m_info(typeid(T)) , m_type(type) { m_data = new IDData(new std::shared_ptr(data), [](void *ptr) -> void { delete (std::shared_ptr*)ptr; }); } - ID() : m_data(nullptr) + ID() + : m_info(typeid(nullptr_t)) + , m_data(nullptr) { } - ID(ID&& other) + ID(const ID& right) = delete; + + ID(ID&& right) + : m_info(right.m_info) + , m_data(right.m_data) + , m_type(right.m_type) { - m_name = other.m_name; - m_type = other.m_type; - m_data = other.m_data; - other.m_data = nullptr; + right.m_data = nullptr; } - ID& operator=(ID&& other) + ID& operator=(ID&& other) = delete; + + ~ID() { - std::swap(m_name,other.m_name); - std::swap(m_type,other.m_type); - std::swap(m_data,other.m_data); - return *this; + if (m_data) + { + delete m_data; + } } - void Kill() + const std::type_info& GetInfo() const { - delete m_data; - } - - const std::string& GetName() const - { - return m_name; + return m_info; } IDData* GetData() const @@ -147,10 +143,6 @@ public: { std::lock_guard lock(m_mtx_main); - for(auto& i : m_id_map) { - i.second.Kill(); - } - m_id_map.clear(); m_cur_id = s_first_id; } @@ -160,11 +152,11 @@ public: = char #endif > - u32 GetNewID(const std::string& name = "", std::shared_ptr& data = nullptr, const IDType type = TYPE_OTHER) + u32 GetNewID(std::shared_ptr& data = nullptr, const IDType type = TYPE_OTHER) { std::lock_guard lock(m_mtx_main); - m_id_map[m_cur_id] = ID(name, data, type); + m_id_map.emplace(m_cur_id, ID(data, type)); if (type < TYPE_OTHER) { m_types[type].insert(m_cur_id); } @@ -185,7 +177,7 @@ public: std::lock_guard lock(m_mtx_main); auto f = m_id_map.find(id); - if (f == m_id_map.end()) { + if (f == m_id_map.end() || f->second.GetInfo() != typeid(T)) { return false; } @@ -219,7 +211,6 @@ public: m_types[item->second.GetType()].erase(id); } - item->second.Kill(); m_id_map.erase(item); return true; diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index b8a21ab81e..cd15049463 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -599,23 +599,3 @@ void Module::SetName(const std::string& name) { m_name = name; } - -bool Module::CheckID(u32 id) const -{ - return Emu.GetIdManager().CheckID(id) && Emu.GetIdManager().GetID(id).GetName() == GetName(); -} - -bool Module::CheckID(u32 id, ID*& _id) const -{ - return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->GetName() == GetName(); -} - -bool Module::RemoveId(u32 id) -{ - return Emu.GetIdManager().RemoveID(id); -} - -IdManager& Module::GetIdManager() const -{ - return Emu.GetIdManager(); -} diff --git a/rpcs3/Emu/SysCalls/Modules.h b/rpcs3/Emu/SysCalls/Modules.h index 58ea0d9cf7..84e2b519d2 100644 --- a/rpcs3/Emu/SysCalls/Modules.h +++ b/rpcs3/Emu/SysCalls/Modules.h @@ -76,8 +76,6 @@ class Module : public LogBase bool m_is_loaded; void(*m_init)(); - IdManager& GetIdManager() const; - Module() = delete; public: @@ -104,42 +102,6 @@ public: virtual const std::string& GetName() const override; void SetName(const std::string& name); - -public: - bool CheckID(u32 id) const; - - template bool CheckId(u32 id, std::shared_ptr& data) - { - ID* id_data; - - if(!CheckID(id, id_data)) return false; - - data = id_data->GetData()->get(); - - return true; - } - - template bool CheckId(u32 id, std::shared_ptr& data, IDType& type) - { - ID* id_data; - - if(!CheckID(id, id_data)) return false; - - data = id_data->GetData()->get(); - type = id_data->GetType(); - - return true; - } - - bool CheckID(u32 id, ID*& _id) const; - - template - u32 GetNewId(std::shared_ptr& data, IDType type = TYPE_OTHER) - { - return GetIdManager().GetNewID(GetName(), data, type); - } - - bool RemoveId(u32 id); }; u32 add_ppu_func(ModuleFunc func); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 4dca0a6a27..b129dd3a0b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -219,7 +219,7 @@ u32 adecOpen(AudioDecoder* adec_ptr) std::shared_ptr sptr(adec_ptr); AudioDecoder& adec = *adec_ptr; - u32 adec_id = cellAdec.GetNewId(sptr); + u32 adec_id = Emu.GetIdManager().GetNewID(sptr); adec.id = adec_id; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 2f45e35988..fde14e55b4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -790,7 +790,7 @@ int cellAudioCreateNotifyEventQueue(vm::ptr id, vm::ptr key) return CELL_AUDIO_ERROR_EVENT_QUEUE; } - *id = cellAudio.GetNewId(eq); + *id = Emu.GetIdManager().GetNewID(eq); *key = event_key; return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index f02cd09424..edef462275 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -301,7 +301,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr) std::shared_ptr sptr(dmux_ptr); Demuxer& dmux = *dmux_ptr; - u32 dmux_id = cellDmux.GetNewId(sptr); + u32 dmux_id = Emu.GetIdManager().GetNewID(sptr); dmux.id = dmux_id; @@ -990,7 +990,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr esFil esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2, esCb->cbEsMsgFunc.to_le(), esCb->cbArg, esSpecificInfo_addr)); - u32 id = cellDmux.GetNewId(es); + u32 id = Emu.GetIdManager().GetNewID(es); es->id = id; *esHandle = id; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp index b78fe6e90c..f25a97b38d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/System.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/Modules.h" @@ -52,7 +53,7 @@ int cellGifDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr mainHandle, subHandle, info.addr()); std::shared_ptr subHandle_data; - if(!cellGifDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_GIFDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; @@ -113,7 +114,7 @@ int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr subHandle_data; - if(!cellGifDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_GIFDEC_ERROR_FATAL; CellGifDecInfo& current_info = subHandle_data->info; @@ -145,7 +146,7 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP; std::shared_ptr subHandle_data; - if(!cellGifDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_GIFDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; @@ -260,11 +261,11 @@ int cellGifDecClose(u32 mainHandle, u32 subHandle) mainHandle, subHandle); std::shared_ptr subHandle_data; - if(!cellGifDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_GIFDEC_ERROR_FATAL; cellFsClose(subHandle_data->fd); - cellGifDec.RemoveId(subHandle); + Emu.GetIdManager().RemoveID(subHandle); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index ea49bf80cd..b5b6dcac86 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/System.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/Modules.h" @@ -58,7 +59,7 @@ int cellJpgDecOpen(u32 mainHandle, vm::ptr subHandle, vm::ptr subHandle_data; - if(!cellJpgDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_JPGDEC_ERROR_FATAL; cellFsClose(subHandle_data->fd); - cellJpgDec.RemoveId(subHandle); + Emu.GetIdManager().RemoveID(subHandle); return CELL_OK; } @@ -83,7 +84,7 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle, subHandle, info.addr()); std::shared_ptr subHandle_data; - if(!cellJpgDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_JPGDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; @@ -152,7 +153,7 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP; std::shared_ptr subHandle_data; - if(!cellJpgDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_JPGDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; @@ -282,7 +283,7 @@ int cellJpgDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr subHandle_data; - if(!cellJpgDec.CheckId(subHandle, subHandle_data)) + if(!Emu.GetIdManager().GetIDData(subHandle, subHandle_data)) return CELL_JPGDEC_ERROR_FATAL; CellJpgDecInfo& current_info = subHandle_data->info; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 0ad437fe47..4dca8694bd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -209,7 +209,7 @@ u32 vdecOpen(VideoDecoder* vdec_ptr) std::shared_ptr sptr(vdec_ptr); VideoDecoder& vdec = *vdec_ptr; - u32 vdec_id = cellVdec.GetNewId(sptr); + u32 vdec_id = Emu.GetIdManager().GetNewID(sptr); vdec.id = vdec_id; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index bd681ef0bf..2a8a49afcc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -29,7 +29,7 @@ int cellVpostQueryAttr(vm::ptr cfgParam, vm::ptr data_ptr(data); - u32 id = cellVpost.GetNewId(data_ptr); + u32 id = Emu.GetIdManager().GetNewID(data_ptr); cellVpost.Notice("*** Vpost instance created (to_rgba=%d): id = %d", data->to_rgba, id); diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 10c71f313b..5f74856db2 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -226,7 +226,7 @@ int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size) sysPrxForUser.Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size); std::shared_ptr heap(new HeapInfo(heap_addr, align, size)); - u32 heap_id = sysPrxForUser.GetNewId(heap); + u32 heap_id = Emu.GetIdManager().GetNewID(heap); sysPrxForUser.Warning("*** sys_heap created: id = %d", heap_id); return heap_id; } @@ -236,7 +236,7 @@ u32 _sys_heap_malloc(const u32 heap_id, const u32 size) sysPrxForUser.Warning("_sys_heap_malloc(heap_id=%d, size=0x%x)", heap_id, size); std::shared_ptr heap; - if(!sysPrxForUser.CheckId(heap_id, heap)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(heap_id, heap)) return CELL_ESRCH; return (u32)Memory.Alloc(size, 1); } @@ -246,7 +246,7 @@ u32 _sys_heap_memalign(u32 heap_id, u32 align, u32 size) sysPrxForUser.Warning("_sys_heap_memalign(heap_id=%d, align=0x%x, size=0x%x)", heap_id, align, size); std::shared_ptr heap; - if(!sysPrxForUser.CheckId(heap_id, heap)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(heap_id, heap)) return CELL_ESRCH; return (u32)Memory.Alloc(size, align); } @@ -267,9 +267,7 @@ s32 sys_interrupt_thread_disestablish(PPUThread& CPU, u32 ih) { sysPrxForUser.Todo("sys_interrupt_thread_disestablish(ih=%d)", ih); - vm::stackvar r13(CPU); - - return _sys_interrupt_thread_disestablish(ih, r13); + return _sys_interrupt_thread_disestablish(ih, vm::stackvar(CPU)); } int sys_process_is_stack(u32 p) diff --git a/rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp b/rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp index a848c05b28..32994abd06 100644 --- a/rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp +++ b/rpcs3/Emu/SysCalls/SyncPrimitivesManager.cpp @@ -50,20 +50,20 @@ std::string SyncPrimManager::GetSyncPrimName(u32 id, IDType type) case TYPE_MUTEX: { - std::shared_ptr mutex; + std::shared_ptr mutex; if (Emu.GetIdManager().GetIDData(id, mutex)) { - return std::string((const char*)&mutex->queue.name, 8); + return std::string((const char*)&mutex->name, 8); } break; } case TYPE_COND: { - std::shared_ptr cond; + std::shared_ptr cond; if (Emu.GetIdManager().GetIDData(id, cond)) { - return std::string((const char*)&cond->queue.name, 8); + return std::string((const char*)&cond->name, 8); } break; } diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 765e9d592a..a132eb2da9 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -33,14 +33,6 @@ #include "SysCalls.h" -namespace detail -{ - bool CheckIdID(u32 id, ID*& _id, const std::string &name) - { - return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->GetName() == name; - } -} - void null_func(PPUThread& CPU); const int kSyscallTableLength = 1024; @@ -952,13 +944,3 @@ void SysCalls::DoSyscall(PPUThread& CPU, u64 code) CPU.m_last_syscall = old_last_syscall; } - -IdManager& SysCallBase::GetIdManager() const -{ - return Emu.GetIdManager(); -} - -bool SysCallBase::RemoveId(u32 id) -{ - return Emu.GetIdManager().RemoveID(id); -} diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 5d27667da0..9822ab7ac0 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -5,32 +5,14 @@ //#define SYSCALLS_DEBUG -class SysCallBase; - -namespace detail -{ - bool CheckIdID(u32 id, ID*& _id, const std::string& name); - - template bool CheckId(u32 id, std::shared_ptr& data, const std::string& name) - { - ID* id_data; - if(!CheckIdID(id, id_data, name)) return false; - data = id_data->GetData()->get(); - return true; - } -} - class SysCallBase : public LogBase { private: std::string m_module_name; - //u32 m_id; - IdManager& GetIdManager() const; public: - SysCallBase(const std::string& name/*, u32 id*/) + SysCallBase(const std::string& name) : m_module_name(name) - //, m_id(id) { } @@ -38,25 +20,6 @@ public: { return m_module_name; } - - bool CheckId(u32 id) const - { - return GetIdManager().CheckID(id) && GetIdManager().GetID(id).GetName() == GetName(); - } - - template - bool CheckId(u32 id, std::shared_ptr& data) const - { - return detail::CheckId(id, data, GetName()); - } - - template - u32 GetNewId(std::shared_ptr& data, IDType type = TYPE_OTHER) - { - return GetIdManager().GetNewID(GetName(), data, type); - } - - bool RemoveId(u32 id); }; extern bool dump_enable; diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 9221419d31..ba34da0e02 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -115,7 +115,7 @@ s32 cellFsOpen(vm::ptr path, s32 flags, vm::ptr> fd, vm::p return CELL_ENOENT; } - u32 id = sys_fs.GetNewId(stream, TYPE_FS_FILE); + u32 id = Emu.GetIdManager().GetNewID(stream, TYPE_FS_FILE); *fd = id; sys_fs.Notice("cellFsOpen(): '%s' opened, id -> 0x%x", path.get_ptr(), id); @@ -127,7 +127,7 @@ s32 cellFsRead(u32 fd, vm::ptr buf, u64 nbytes, vm::ptr> nread) sys_fs.Log("cellFsRead(fd=0x%x, buf=0x%x, nbytes=0x%llx, nread=0x%x)", fd, buf, nbytes, nread); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; if (nbytes != (u32)nbytes) @@ -147,7 +147,7 @@ s32 cellFsWrite(u32 fd, vm::ptr buf, u64 nbytes, vm::ptr nwrite sys_fs.Log("cellFsWrite(fd=0x%x, buf=0x%x, nbytes=0x%llx, nwrite=0x%x)", fd, buf, nbytes, nwrite); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) return CELL_ESRCH; + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; if (nbytes != (u32)nbytes) return CELL_ENOMEM; @@ -181,7 +181,7 @@ s32 cellFsOpendir(vm::ptr path, vm::ptr fd) return CELL_ENOENT; } - *fd = sys_fs.GetNewId(dir, TYPE_FS_DIR); + *fd = Emu.GetIdManager().GetNewID(dir, TYPE_FS_DIR); return CELL_OK; } @@ -190,7 +190,7 @@ s32 cellFsReaddir(u32 fd, vm::ptr dir, vm::ptr nread) sys_fs.Warning("cellFsReaddir(fd=0x%x, dir=0x%x, nread=0x%x)", fd, dir, nread); std::shared_ptr directory; - if (!sys_fs.CheckId(fd, directory)) + if (!Emu.GetIdManager().GetIDData(fd, directory)) return CELL_ESRCH; const DirEntryInfo* info = directory->Read(); @@ -306,9 +306,8 @@ s32 cellFsFstat(u32 fd, vm::ptr sb) { sys_fs.Warning("cellFsFstat(fd=0x%x, sb=0x%x)", fd, sb); - IDType type; std::shared_ptr file; - if (!sys_fs.CheckId(fd, file, type) || type != TYPE_FS_FILE) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; sb->st_mode = @@ -452,9 +451,8 @@ s32 cellFsLseek(u32 fd, s64 offset, u32 whence, vm::ptr> pos) return CELL_EINVAL; } - IDType type; std::shared_ptr file; - if (!sys_fs.CheckId(fd, file, type) || type != TYPE_FS_FILE) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; *pos = file->Seek(offset, seek_mode); @@ -465,9 +463,8 @@ s32 cellFsFtruncate(u32 fd, u64 size) { sys_fs.Warning("cellFsFtruncate(fd=0x%x, size=0x%llx)", fd, size); - IDType type; std::shared_ptr file; - if (!sys_fs.CheckId(fd, file, type) || type != TYPE_FS_FILE) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; u64 initialSize = file->GetSize(); @@ -526,7 +523,7 @@ s32 cellFsFGetBlockSize(u32 fd, vm::ptr sector_size, vm::ptr block_siz sys_fs.Warning("cellFsFGetBlockSize(fd=0x%x, sector_size=0x%x, block_size=0x%x)", fd, sector_size, block_size); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; *sector_size = 4096; // ? @@ -563,7 +560,7 @@ s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr entries, u32 sys_fs.Warning("cellFsGetDirectoryEntries(fd=0x%x, entries=0x%x, entries_size=0x%x, data_count=0x%x)", fd, entries, entries_size, data_count); std::shared_ptr directory; - if (!sys_fs.CheckId(fd, directory)) + if (!Emu.GetIdManager().GetIDData(fd, directory)) return CELL_ESRCH; const DirEntryInfo* info = directory->Read(); @@ -599,7 +596,7 @@ s32 cellFsStReadInit(u32 fd, vm::ptr ringbuf) sys_fs.Warning("cellFsStReadInit(fd=0x%x, ringbuf=0x%x)", fd, ringbuf); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; fs_config.m_ring_buffer = *ringbuf; @@ -624,7 +621,7 @@ s32 cellFsStReadFinish(u32 fd) sys_fs.Warning("cellFsStReadFinish(fd=0x%x)", fd); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; Memory.Free(fs_config.m_buffer); @@ -638,7 +635,7 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr ringbuf) sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, ringbuf=0x%x)", fd, ringbuf); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; *ringbuf = fs_config.m_ring_buffer; @@ -653,7 +650,7 @@ s32 cellFsStReadGetStatus(u32 fd, vm::ptr status) sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, status=0x%x)", fd, status); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; *status = fs_config.m_fs_status; @@ -666,7 +663,7 @@ s32 cellFsStReadGetRegid(u32 fd, vm::ptr regid) sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, regid=0x%x)", fd, regid); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; *regid = fs_config.m_regid; @@ -679,7 +676,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size) sys_fs.Todo("cellFsStReadStart(fd=0x%x, offset=0x%llx, size=0x%llx)", fd, offset, size); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; fs_config.m_current_addr = fs_config.m_buffer + (u32)offset; @@ -693,7 +690,7 @@ s32 cellFsStReadStop(u32 fd) sys_fs.Warning("cellFsStReadStop(fd=0x%x)", fd); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; fs_config.m_fs_status = CELL_FS_ST_STOP; @@ -706,7 +703,7 @@ s32 cellFsStRead(u32 fd, vm::ptr buf, u64 size, vm::ptr rsize) sys_fs.Warning("cellFsStRead(fd=0x%x, buf=0x%x, size=0x%llx, rsize=0x%x)", fd, buf, size, rsize); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; // TODO: use ringbuffer (fs_config) @@ -725,7 +722,7 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr> addr, vm::ptr s sys_fs.Todo("cellFsStReadGetCurrentAddr(fd=0x%x, addr=0x%x, size=0x%x)", fd, addr, size); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; return CELL_OK; @@ -736,7 +733,7 @@ s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr addr, u64 size) sys_fs.Todo("cellFsStReadPutCurrentAddr(fd=0x%x, addr=0x%x, size=0x%llx)", fd, addr, size); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; return CELL_OK; @@ -747,7 +744,7 @@ s32 cellFsStReadWait(u32 fd, u64 size) sys_fs.Todo("cellFsStReadWait(fd=0x%x, size=0x%llx)", fd, size); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; return CELL_OK; @@ -758,7 +755,7 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr sys_fs.Todo("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=0x%x)", fd, size, func); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; return CELL_OK; @@ -882,7 +879,7 @@ s32 cellFsSdataOpen(vm::ptr path, s32 flags, vm::ptr> fd, int ret = sdata_unpack(path, unpacked_path); if (ret) return ret; - fd = sys_fs.GetNewId(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE); + fd = Emu.GetIdManager().GetNewID(Emu.GetVFS().OpenFile(unpacked_path, vfsRead), TYPE_FS_FILE); return CELL_OK;*/ @@ -918,7 +915,7 @@ void fsAioRead(u32 fd, vm::ptr aio, int xid, vm::ptr orig_file; - if (!sys_fs.CheckId(fd, orig_file)) + if (!Emu.GetIdManager().GetIDData(fd, orig_file)) { sys_fs.Error("Wrong fd (%s)", fd); Emu.Pause(); @@ -969,7 +966,7 @@ s32 cellFsAioRead(vm::ptr aio, vm::ptr id, vm::ptr orig_file; u32 fd = aio->fd; - if (!sys_fs.CheckId(fd, orig_file)) + if (!Emu.GetIdManager().GetIDData(fd, orig_file)) { return CELL_EBADF; } @@ -1039,7 +1036,7 @@ s32 cellFsSetIoBufferFromDefaultContainer(u32 fd, u32 buffer_size, u32 page_type sys_fs.Todo("cellFsSetIoBufferFromDefaultContainer(fd=%d, buffer_size=%d, page_type=%d)", fd, buffer_size, page_type); std::shared_ptr file; - if (!sys_fs.CheckId(fd, file)) + if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH; return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp index da99354969..f2393e0f3b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.cpp @@ -12,30 +12,34 @@ SysCallBase sys_cond("sys_cond"); -s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptr attr) +s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptr attr) { - sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=0x%x)", cond_id.addr(), mutex_id, attr.addr()); + sys_cond.Warning("sys_cond_create(cond_id=*0x%x, mutex_id=%d, attr=*0x%x)", cond_id, mutex_id, attr); - if (attr->pshared.data() != se32(0x200)) - { - sys_cond.Error("Unknown pshared attribute (0x%x)", attr->pshared); - return CELL_EINVAL; - } + LV2_LOCK; + + std::shared_ptr mutex; - std::shared_ptr mutex; if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { return CELL_ESRCH; } - std::shared_ptr cond(new Cond(mutex, attr->name_u64)); + if (attr->pshared.data() != se32(0x200) || attr->ipc_key.data() || attr->flags.data()) + { + sys_cond.Error("sys_cond_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags); + return CELL_EINVAL; + } - const u32 id = sys_cond.GetNewId(cond, TYPE_COND); - cond->queue.set_full_name(fmt::Format("Cond(%d, mutex_id=%d)", id, mutex_id)); - *cond_id = id; - mutex->cond_count++; // TODO: check safety + if (!++mutex->cond_count) + { + throw __FUNCTION__; + } + + std::shared_ptr cond(new cond_t(mutex, attr->name_u64)); + + *cond_id = Emu.GetIdManager().GetNewID(cond, TYPE_COND); - sys_cond.Warning("*** cond created [%s] (mutex_id=%d): id = %d", std::string(attr->name, 8).c_str(), mutex_id, id); return CELL_OK; } @@ -43,19 +47,27 @@ s32 sys_cond_destroy(u32 cond_id) { sys_cond.Warning("sys_cond_destroy(cond_id=%d)", cond_id); - std::shared_ptr cond; + LV2_LOCK; + + std::shared_ptr cond; + if (!Emu.GetIdManager().GetIDData(cond_id, cond)) { return CELL_ESRCH; } - if (cond->queue.count()) // TODO: safely make object unusable + if (cond->waiters || cond->signaled) { return CELL_EBUSY; } - cond->mutex->cond_count--; // TODO: check safety + if (!cond->mutex->cond_count--) + { + throw __FUNCTION__; + } + Emu.GetIdManager().RemoveID(cond_id); + return CELL_OK; } @@ -63,13 +75,22 @@ s32 sys_cond_signal(u32 cond_id) { sys_cond.Log("sys_cond_signal(cond_id=%d)", cond_id); - std::shared_ptr cond; + LV2_LOCK; + + std::shared_ptr cond; + if (!Emu.GetIdManager().GetIDData(cond_id, cond)) { return CELL_ESRCH; } - u32 target = cond->queue.signal(cond->mutex->protocol); + if (cond->waiters) + { + cond->signaled++; + cond->waiters--; + cond->mutex->cv.notify_one(); + } + return CELL_OK; } @@ -77,21 +98,19 @@ s32 sys_cond_signal_all(u32 cond_id) { sys_cond.Log("sys_cond_signal_all(cond_id=%d)", cond_id); - std::shared_ptr cond; + LV2_LOCK; + + std::shared_ptr cond; + if (!Emu.GetIdManager().GetIDData(cond_id, cond)) { return CELL_ESRCH; } - Mutex* mutex = cond->mutex.get(); - - while (u32 target = cond->queue.signal(mutex->protocol)) + if (cond->waiters) { - if (Emu.IsStopped()) - { - sys_cond.Warning("sys_cond_signal_all(id=%d) aborted", cond_id); - break; - } + cond->signaled += cond->waiters.exchange(0); + cond->mutex->cv.notify_all(); } return CELL_OK; @@ -99,9 +118,12 @@ s32 sys_cond_signal_all(u32 cond_id) s32 sys_cond_signal_to(u32 cond_id, u32 thread_id) { - sys_cond.Log("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id); + sys_cond.Todo("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id); + + LV2_LOCK; + + std::shared_ptr cond; - std::shared_ptr cond; if (!Emu.GetIdManager().GetIDData(cond_id, cond)) { return CELL_ESRCH; @@ -112,10 +134,14 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id) return CELL_ESRCH; } - if (!cond->queue.signal_selected(thread_id)) + if (!cond->waiters) { return CELL_EPERM; } + + cond->signaled++; + cond->waiters--; + cond->mutex->cv.notify_one(); return CELL_OK; } @@ -125,62 +151,38 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout) const u64 start_time = get_system_time(); - std::shared_ptr cond; + LV2_LOCK; + + std::shared_ptr cond; + if (!Emu.GetIdManager().GetIDData(cond_id, cond)) { return CELL_ESRCH; } - Mutex* mutex = cond->mutex.get(); + std::shared_ptr thread = Emu.GetCPU().GetThread(CPU.GetId()); - const u32 tid = CPU.GetId(); - if (mutex->owner.read_sync() != tid) + if (cond->mutex->owner.owner_before(thread) || thread.owner_before(cond->mutex->owner)) // check equality { return CELL_EPERM; } - cond->queue.push(tid, mutex->protocol); + // protocol is ignored in current implementation + cond->waiters++; assert(cond->waiters > 0); - auto old_recursive = mutex->recursive_count.load(); - mutex->recursive_count = 0; - if (!mutex->owner.compare_and_swap_test(tid, mutex->queue.signal(mutex->protocol))) + // unlock mutex + cond->mutex->owner.reset(); + + // not sure whether the recursive value is precisely saved + const u32 recursive_value = cond->mutex->recursive_count.exchange(0); + + while (!cond->mutex->owner.expired() || !cond->signaled) { - assert(!"sys_cond_wait() failed"); - } - - bool pushed_in_sleep_queue = false, signaled = false; - while (true) - { - if ((signaled = signaled || cond->queue.pop(tid, mutex->protocol))) // check if signaled + if (!cond->signaled && timeout && get_system_time() - start_time > timeout) { - if (mutex->owner.compare_and_swap_test(0, tid)) // try to lock - { - break; - } - - if (!pushed_in_sleep_queue) - { - mutex->queue.push(tid, mutex->protocol); - pushed_in_sleep_queue = true; - } - - auto old_owner = mutex->owner.compare_and_swap(0, tid); - if (!old_owner || old_owner == tid) - { - break; - } - } - - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - - if (timeout && get_system_time() - start_time > timeout) - { - if (!cond->queue.invalidate(tid, mutex->protocol)) - { - assert(!"sys_cond_wait() failed (timeout)"); - } - CPU.owned_mutexes--; // ??? - return CELL_ETIMEDOUT; // mutex not locked + // TODO: mutex not locked, timeout is possible only when signaled == 0 + cond->waiters--; assert(cond->waiters >= 0); + return CELL_ETIMEDOUT; } if (Emu.IsStopped()) @@ -188,12 +190,15 @@ s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout) sys_cond.Warning("sys_cond_wait(id=%d) aborted", cond_id); return CELL_OK; } + + cond->mutex->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } - if (pushed_in_sleep_queue && !mutex->queue.invalidate(tid, mutex->protocol) && !mutex->queue.pop(tid, mutex->protocol)) - { - assert(!"sys_cond_wait() failed (locking)"); - } - mutex->recursive_count = old_recursive; + // restore mutex owner + cond->mutex->owner = thread; + cond->mutex->recursive_count = recursive_value; + + cond->signaled--; assert(cond->signaled >= 0); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.h b/rpcs3/Emu/SysCalls/lv2/sys_cond.h index 13c8b7f5cd..979493d97c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.h @@ -1,10 +1,13 @@ #pragma once -struct sys_cond_attribute +struct mutex_t; + +struct sys_cond_attribute_t { be_t pshared; - be_t ipc_key; be_t flags; + be_t ipc_key; + union { char name[8]; @@ -12,14 +15,20 @@ struct sys_cond_attribute }; }; -struct Cond +struct cond_t { - std::shared_ptr mutex; // associated with mutex - sleep_queue_t queue; + const u64 name; + const std::shared_ptr mutex; // associated mutex - Cond(std::shared_ptr& mutex, u64 name) + // TODO: use sleep queue + std::atomic waiters; + std::atomic signaled; + + cond_t(std::shared_ptr& mutex, u64 name) : mutex(mutex) - , queue(name) + , name(name) + , waiters(0) + , signaled(0) { } }; @@ -27,7 +36,7 @@ struct Cond class PPUThread; // SysCalls -s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptr attr); +s32 sys_cond_create(vm::ptr cond_id, u32 mutex_id, vm::ptr attr); s32 sys_cond_destroy(u32 cond_id); s32 sys_cond_wait(PPUThread& CPU, u32 cond_id, u64 timeout); s32 sys_cond_signal(u32 cond_id); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp index 96cbdd5fe8..e4978cb8e7 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event.cpp @@ -18,7 +18,7 @@ u32 event_queue_create(u32 protocol, s32 type, u64 name_u64, u64 event_queue_key Emu.GetEventManager().RegisterKey(queue, event_queue_key); - return sys_event.GetNewId(queue, TYPE_EVENT_QUEUE); + return Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE); } s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr attr, u64 event_queue_key, s32 size) @@ -35,10 +35,10 @@ s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr switch (protocol) { case SYS_SYNC_PRIORITY: break; - case SYS_SYNC_RETRY: sys_event.Error("Invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL; - case SYS_SYNC_PRIORITY_INHERIT: sys_event.Error("Invalid protocol (SYS_SYNC_PRIORITY_INHERIT)"); return CELL_EINVAL; + case SYS_SYNC_RETRY: sys_event.Error("sys_event_queue_create(): invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL; + case SYS_SYNC_PRIORITY_INHERIT: sys_event.Error("sys_event_queue_create(): invalid protocol (SYS_SYNC_PRIORITY_INHERIT)"); return CELL_EINVAL; case SYS_SYNC_FIFO: break; - default: sys_event.Error("Unknown protocol (0x%x)", protocol); return CELL_EINVAL; + default: sys_event.Error("sys_event_queue_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL; } const u32 type = attr->type; @@ -47,7 +47,7 @@ s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr { case SYS_PPU_QUEUE: break; case SYS_SPU_QUEUE: break; - default: sys_event.Error("Unknown event queue type (0x%x)", type); return CELL_EINVAL; + default: sys_event.Error("sys_event_queue_create(): unknown type (0x%x)", type); return CELL_EINVAL; } LV2_LOCK; @@ -64,7 +64,7 @@ s32 sys_event_queue_create(vm::ptr equeue_id, vm::ptr return CELL_EAGAIN; } - *equeue_id = sys_event.GetNewId(queue, TYPE_EVENT_QUEUE); + *equeue_id = Emu.GetIdManager().GetNewID(queue, TYPE_EVENT_QUEUE); return CELL_OK; } @@ -170,22 +170,19 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr } // protocol is ignored in current implementation - queue->waiters++; - assert(queue->waiters > 0); + queue->waiters++; assert(queue->waiters > 0); while (queue->events.empty()) { if (queue->waiters < 0) { - queue->waiters--; - assert(queue->waiters < 0); + queue->waiters--; assert(queue->waiters < 0); return CELL_ECANCELED; } if (timeout && get_system_time() - start_time > timeout) { - queue->waiters--; - assert(queue->waiters >= 0); + queue->waiters--; assert(queue->waiters >= 0); return CELL_ETIMEDOUT; } @@ -206,8 +203,7 @@ s32 sys_event_queue_receive(PPUThread& CPU, u32 equeue_id, vm::ptr CPU.GPR[7] = event.data3; queue->events.pop_front(); - queue->waiters--; - assert(queue->waiters >= 0); + queue->waiters--; assert(queue->waiters >= 0); if (queue->events.size()) { @@ -239,7 +235,7 @@ u32 event_port_create(u64 name) { std::shared_ptr eport(new event_port_t(SYS_EVENT_PORT_LOCAL, name)); - return sys_event.GetNewId(eport, TYPE_EVENT_PORT); + return Emu.GetIdManager().GetNewID(eport, TYPE_EVENT_PORT); } s32 sys_event_port_create(vm::ptr eport_id, s32 port_type, u64 name) @@ -256,7 +252,7 @@ s32 sys_event_port_create(vm::ptr eport_id, s32 port_type, u64 name) std::shared_ptr eport(new event_port_t(port_type, name)); - *eport_id = sys_event.GetNewId(eport, TYPE_EVENT_PORT); + *eport_id = Emu.GetIdManager().GetNewID(eport, TYPE_EVENT_PORT); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp index 84ca4eba40..e16ffaa976 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_event_flag.cpp @@ -27,15 +27,15 @@ s32 sys_event_flag_create(vm::ptr id, vm::ptr attr, u6 switch (protocol) { case SYS_SYNC_PRIORITY: break; - case SYS_SYNC_RETRY: sys_event_flag.Todo("SYS_SYNC_RETRY"); break; - case SYS_SYNC_PRIORITY_INHERIT: sys_event_flag.Todo("SYS_SYNC_PRIORITY_INHERIT"); break; + case SYS_SYNC_RETRY: sys_event_flag.Todo("sys_event_flag_create(): SYS_SYNC_RETRY"); break; + case SYS_SYNC_PRIORITY_INHERIT: sys_event_flag.Todo("sys_event_flag_create(): SYS_SYNC_PRIORITY_INHERIT"); break; case SYS_SYNC_FIFO: break; - default: sys_event_flag.Error("Unknown protocol (0x%x)", attr->protocol); return CELL_EINVAL; + default: sys_event_flag.Error("sys_event_flag_create(): unknown protocol (0x%x)", attr->protocol); return CELL_EINVAL; } - if (attr->pshared.data() != se32(0x200)) + if (attr->pshared.data() != se32(0x200) || attr->ipc_key.data() || attr->flags.data()) { - sys_event_flag.Error("Unknown pshared attribute (0x%x)", attr->pshared); + sys_event_flag.Error("sys_event_flag_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags); return CELL_EINVAL; } @@ -45,12 +45,12 @@ s32 sys_event_flag_create(vm::ptr id, vm::ptr attr, u6 { case SYS_SYNC_WAITER_SINGLE: break; case SYS_SYNC_WAITER_MULTIPLE: break; - default: sys_event_flag.Error("Unknown event flag type (0x%x)", attr->type); return CELL_EINVAL; + default: sys_event_flag.Error("sys_event_flag_create(): unknown type (0x%x)", attr->type); return CELL_EINVAL; } std::shared_ptr ef(new event_flag_t(init, protocol, type, attr->name_u64)); - *id = sys_event_flag.GetNewId(ef, TYPE_EVENT_FLAG); + *id = Emu.GetIdManager().GetNewID(ef, TYPE_EVENT_FLAG); return CELL_OK; } @@ -151,15 +151,19 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t if (ef->waiters <= 0) { - ef->waiters++; - assert(ef->waiters <= 0); + ef->waiters++; assert(ef->waiters <= 0); + + if (!ef->waiters) + { + ef->cv.notify_all(); + } + return CELL_ECANCELED; } if (timeout && get_system_time() - start_time > timeout) { - ef->waiters--; - assert(ef->waiters >= 0); + ef->waiters--; assert(ef->waiters >= 0); return CELL_ETIMEDOUT; } @@ -182,8 +186,7 @@ s32 sys_event_flag_wait(u32 id, u64 bitptn, u32 mode, vm::ptr result, u64 t ef->flags = 0; } - ef->waiters--; - assert(ef->waiters >= 0); + ef->waiters--; assert(ef->waiters >= 0); if (ef->flags) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp index d1d0dbfc66..0bc74d26ce 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_interrupt.cpp @@ -121,7 +121,7 @@ s32 sys_interrupt_thread_establish(vm::ptr ih, u32 intrtag, u64 intrthread, }; } - *ih = sys_interrupt.GetNewId(handler, TYPE_INTR_SERVICE_HANDLE); + *ih = Emu.GetIdManager().GetNewID(handler, TYPE_INTR_SERVICE_HANDLE); ppu.Exec(); return CELL_OK; @@ -132,7 +132,7 @@ s32 _sys_interrupt_thread_disestablish(u32 ih, vm::ptr r13) sys_interrupt.Todo("_sys_interrupt_thread_disestablish(ih=%d)", ih); std::shared_ptr handler; - if (!sys_interrupt.CheckId(ih, handler)) + if (!Emu.GetIdManager().GetIDData(ih, handler)) { return CELL_ESRCH; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp index a5f7f684e7..60a0bf1283 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.cpp @@ -17,7 +17,7 @@ s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64) std::shared_ptr lw(new Lwcond(name_u64, addr)); - const u32 id = sys_lwcond.GetNewId(lw, TYPE_LWCOND); + const u32 id = Emu.GetIdManager().GetNewID(lw, TYPE_LWCOND); lw->queue.set_full_name(fmt::Format("Lwcond(%d, addr=0x%x)", id, lw->addr)); lwcond.lwmutex.set(addr); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index 31f47e9278..9cd3de546b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -19,7 +19,7 @@ s32 lwmutex_create(sys_lwmutex_t& lwmutex, u32 protocol, u32 recursive, u64 name lwmutex.waiter.write_relaxed(be_t::make(~0)); lwmutex.attribute = protocol | recursive; lwmutex.recursive_count.write_relaxed(be_t::make(0)); - u32 sq_id = sys_lwmutex.GetNewId(sq, TYPE_LWMUTEX); + u32 sq_id = Emu.GetIdManager().GetNewID(sq, TYPE_LWMUTEX); lwmutex.sleep_queue = sq_id; sq->set_full_name(fmt::Format("Lwmutex(%d, addr=0x%x)", sq_id, vm::get_addr(&lwmutex))); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp b/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp index b6b5e9ea57..28e714a955 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/System.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/SysCalls.h" @@ -44,7 +45,7 @@ s32 sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_a // Check if this container ID is valid. std::shared_ptr ct; - if (!sys_memory.CheckId(cid, ct)) + if (!Emu.GetIdManager().GetIDData(cid, ct)) return CELL_ESRCH; // Check page size. @@ -120,7 +121,7 @@ s32 sys_memory_container_create(vm::ptr cid, u32 yield_size) // Wrap the allocated memory in a memory container. std::shared_ptr ct(new MemoryContainerInfo(addr, yield_size)); - u32 id = sys_memory.GetNewId(ct, TYPE_MEM); + u32 id = Emu.GetIdManager().GetNewID(ct, TYPE_MEM); *cid = id; sys_memory.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, id); @@ -134,12 +135,12 @@ s32 sys_memory_container_destroy(u32 cid) // Check if this container ID is valid. std::shared_ptr ct; - if (!sys_memory.CheckId(cid, ct)) + if (!Emu.GetIdManager().GetIDData(cid, ct)) return CELL_ESRCH; // Release the allocated memory and remove the ID. Memory.Free(ct->addr); - sys_memory.RemoveId(cid); + Emu.GetIdManager().RemoveID(cid); return CELL_OK; } @@ -150,7 +151,7 @@ s32 sys_memory_container_get_size(vm::ptr mem_info, u32 cid) // Check if this container ID is valid. std::shared_ptr ct; - if (!sys_memory.CheckId(cid, ct)) + if (!Emu.GetIdManager().GetIDData(cid, ct)) return CELL_ESRCH; // HACK: Return all memory. diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp index 8c7f221160..3ade8bfea7 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/System.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/SysCalls.h" @@ -76,7 +77,7 @@ s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr mem_id) // Generate a new mem ID. std::shared_ptr info(new mmapper_info(size, flags)); - *mem_id = sys_mmapper.GetNewId(info); + *mem_id = Emu.GetIdManager().GetNewID(info); return CELL_OK; } @@ -88,7 +89,7 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm: // Check if this container ID is valid. std::shared_ptr ct; - if(!sys_mmapper.CheckId(cid, ct)) + if(!Emu.GetIdManager().GetIDData(cid, ct)) return CELL_ESRCH; // Check page granularity. @@ -112,7 +113,7 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm: // Generate a new mem ID. std::shared_ptr info(new mmapper_info(ct->size, flags)); - *mem_id = sys_mmapper.GetNewId(info, TYPE_MEM); + *mem_id = Emu.GetIdManager().GetNewID(info, TYPE_MEM); return CELL_OK; } @@ -141,11 +142,11 @@ s32 sys_mmapper_free_memory(u32 mem_id) // Check if this mem ID is valid. std::shared_ptr info; - if(!sys_mmapper.CheckId(mem_id, info)) + if(!Emu.GetIdManager().GetIDData(mem_id, info)) return CELL_ESRCH; // Release the allocated memory and remove the ID. - sys_mmapper.RemoveId(mem_id); + Emu.GetIdManager().RemoveID(mem_id); return CELL_OK; } @@ -156,7 +157,7 @@ s32 sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) // Check if this mem ID is valid. std::shared_ptr info; - if(!sys_mmapper.CheckId(mem_id, info)) + if(!Emu.GetIdManager().GetIDData(mem_id, info)) return CELL_ESRCH; // Map the memory into the process address. @@ -176,7 +177,7 @@ s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_ // Check if this mem ID is valid. std::shared_ptr info; - if(!sys_mmapper.CheckId(mem_id, info)) + if(!Emu.GetIdManager().GetIDData(mem_id, info)) return CELL_ESRCH; // Search for a mappable address. diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp index 99b4da4b10..5f1d2bc331 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.cpp @@ -11,143 +11,124 @@ SysCallBase sys_mutex("sys_mutex"); -Mutex::~Mutex() +s32 sys_mutex_create(vm::ptr mutex_id, vm::ptr attr) { - if (u32 tid = owner.read_sync()) + sys_mutex.Warning("sys_mutex_create(mutex_id=*0x%x, attr=*0x%x)", mutex_id, attr); + + LV2_LOCK; + + if (!mutex_id || !attr) { - sys_mutex.Notice("Mutex(%d) was owned by thread %d (recursive=%d)", id.read_relaxed(), tid, recursive_count.load()); + return CELL_EFAULT; } - if (u32 count = queue.count()) - { - sys_mutex.Notice("Mutex(%d) was waited by %d threads", id.read_relaxed(), count); - } -} + const u32 protocol = attr->protocol; -s32 sys_mutex_create(PPUThread& CPU, vm::ptr mutex_id, vm::ptr attr) -{ - sys_mutex.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.addr(), attr.addr()); - - switch (attr->protocol.data()) + switch (protocol) { - case se32(SYS_SYNC_FIFO): break; - case se32(SYS_SYNC_PRIORITY): break; - case se32(SYS_SYNC_PRIORITY_INHERIT): sys_mutex.Todo("SYS_SYNC_PRIORITY_INHERIT"); break; - case se32(SYS_SYNC_RETRY): sys_mutex.Error("Invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL; - default: sys_mutex.Error("Unknown protocol (0x%x)", attr->protocol); return CELL_EINVAL; + case SYS_SYNC_FIFO: break; + case SYS_SYNC_PRIORITY: break; + case SYS_SYNC_PRIORITY_INHERIT: sys_mutex.Todo("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT"); break; + case SYS_SYNC_RETRY: sys_mutex.Error("sys_mutex_create(): invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL; + default: sys_mutex.Error("sys_mutex_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL; } - bool is_recursive; - switch (attr->recursive.data()) - { - case se32(SYS_SYNC_RECURSIVE): is_recursive = true; break; - case se32(SYS_SYNC_NOT_RECURSIVE): is_recursive = false; break; - default: sys_mutex.Error("Unknown recursive attribute (0x%x)", attr->recursive); return CELL_EINVAL; - } + const bool recursive = attr->recursive.data() == se32(SYS_SYNC_RECURSIVE); - if (attr->pshared.data() != se32(0x200)) + if ((!recursive && attr->recursive.data() != se32(SYS_SYNC_NOT_RECURSIVE)) || attr->pshared.data() != se32(0x200) || attr->adaptive.data() != se32(0x2000) || attr->ipc_key.data() || attr->flags.data()) { - sys_mutex.Error("Unknown pshared attribute (0x%x)", attr->pshared); + sys_mutex.Error("sys_mutex_create(): unknown attributes (recursive=0x%x, pshared=0x%x, adaptive=0x%x, ipc_key=0x%llx, flags=0x%x)", + attr->recursive, attr->pshared, attr->adaptive, attr->ipc_key, attr->flags); + return CELL_EINVAL; } - std::shared_ptr mutex(new Mutex(attr->protocol, is_recursive, attr->name_u64)); + std::shared_ptr mutex(new mutex_t(recursive, protocol, attr->name_u64)); - const u32 id = sys_mutex.GetNewId(mutex, TYPE_MUTEX); - mutex->id.exchange(id); - *mutex_id = id; - mutex->queue.set_full_name(fmt::Format("Mutex(%d)", id)); + *mutex_id = Emu.GetIdManager().GetNewID(mutex, TYPE_MUTEX); - sys_mutex.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d", std::string(attr->name, 8).c_str(), attr->protocol, is_recursive, id); - // TODO: unlock mutex when owner thread does exit return CELL_OK; } -s32 sys_mutex_destroy(PPUThread& CPU, u32 mutex_id) +s32 sys_mutex_destroy(u32 mutex_id) { sys_mutex.Warning("sys_mutex_destroy(mutex_id=%d)", mutex_id); - std::shared_ptr mutex; + LV2_LOCK; + + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { return CELL_ESRCH; } - // check if associated condition variable exists - if (mutex->cond_count) // TODO: check safety - { - return CELL_EPERM; - } - - if (!mutex->owner.compare_and_swap_test(0, ~0)) // check if locked and make unusable + if (!mutex->owner.expired()) { return CELL_EBUSY; } + // assuming that the mutex is locked immediately by another waiting thread when unlocked + if (mutex->waiters) + { + return CELL_EBUSY; + } + + if (mutex->cond_count) + { + return CELL_EPERM; + } + Emu.GetIdManager().RemoveID(mutex_id); + return CELL_OK; } 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); + sys_mutex.Log("sys_mutex_lock(mutex_id=%d, timeout=0x%llx)", mutex_id, timeout); const u64 start_time = get_system_time(); - std::shared_ptr mutex; + LV2_LOCK; + + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { return CELL_ESRCH; } - const u32 tid = CPU.GetId(); + std::shared_ptr thread = Emu.GetCPU().GetThread(CPU.GetId(), CPU_THREAD_PPU); - const u32 old_owner = mutex->owner.compare_and_swap(0, tid); - if (!~old_owner) + if (!mutex->owner.owner_before(thread) && !thread.owner_before(mutex->owner)) // check equality { - return CELL_ESRCH; // mutex is going to be destroyed - } - if (old_owner == tid) - { - if (mutex->is_recursive) + if (mutex->recursive) { - if (!~mutex->recursive_count) + if (mutex->recursive_count == 0xffffffffu) { return CELL_EKRESOURCE; } - mutex->recursive_count++; + + if (!mutex->recursive_count++) + { + throw __FUNCTION__; + } + return CELL_OK; } - else - { - return CELL_EDEADLK; - } - } - else if (!old_owner) - { - mutex->recursive_count = 1; - CPU.owned_mutexes++; - return CELL_OK; + + return CELL_EDEADLK; } - mutex->queue.push(tid, mutex->protocol); + // protocol is ignored in current implementation + mutex->waiters++; assert(mutex->waiters > 0); - while (true) + while (!mutex->owner.expired()) { - auto old_owner = mutex->owner.compare_and_swap(0, tid); - if (!old_owner || old_owner == tid) - { - break; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - if (timeout && get_system_time() - start_time > timeout) { - if (!mutex->queue.invalidate(tid, mutex->protocol)) - { - assert(!"sys_mutex_lock() failed (timeout)"); - } + mutex->waiters--; assert(mutex->waiters >= 0); return CELL_ETIMEDOUT; } @@ -156,14 +137,14 @@ s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout) sys_mutex.Warning("sys_mutex_lock(id=%d) aborted", mutex_id); return CELL_OK; } + + mutex->cv.wait_for(lv2_lock, std::chrono::milliseconds(1)); } - if (!mutex->queue.invalidate(tid, mutex->protocol) && !mutex->queue.pop(tid, mutex->protocol)) - { - assert(!"sys_mutex_lock() failed (locking)"); - } + mutex->owner = thread; mutex->recursive_count = 1; - CPU.owned_mutexes++; + mutex->waiters--; assert(mutex->waiters >= 0); + return CELL_OK; } @@ -171,80 +152,78 @@ s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id) { sys_mutex.Log("sys_mutex_trylock(mutex_id=%d)", mutex_id); - std::shared_ptr mutex; + LV2_LOCK; + + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { return CELL_ESRCH; } - const u32 tid = CPU.GetId(); + std::shared_ptr thread = Emu.GetCPU().GetThread(CPU.GetId()); - const u32 old_owner = mutex->owner.compare_and_swap(0, tid); - if (!~old_owner) + if (!mutex->owner.owner_before(thread) && !thread.owner_before(mutex->owner)) // check equality { - return CELL_ESRCH; // mutex is going to be destroyed - } - if (old_owner == tid) - { - if (mutex->is_recursive) + if (mutex->recursive) { - if (!~mutex->recursive_count) + if (mutex->recursive_count == 0xffffffffu) { return CELL_EKRESOURCE; } - mutex->recursive_count++; + + if (!mutex->recursive_count++) + { + throw __FUNCTION__; + } + return CELL_OK; } - else - { - return CELL_EDEADLK; - } - } - else if (!old_owner) - { - mutex->recursive_count = 1; - CPU.owned_mutexes++; - return CELL_OK; + + return CELL_EDEADLK; } - return CELL_EBUSY; + if (!mutex->owner.expired()) + { + return CELL_EBUSY; + } + + mutex->owner = thread; + mutex->recursive_count = 1; + + return CELL_OK; } s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id) { sys_mutex.Log("sys_mutex_unlock(mutex_id=%d)", mutex_id); - std::shared_ptr mutex; + LV2_LOCK; + + std::shared_ptr mutex; + if (!Emu.GetIdManager().GetIDData(mutex_id, mutex)) { return CELL_ESRCH; } - const u32 tid = CPU.GetId(); + std::shared_ptr thread = Emu.GetCPU().GetThread(CPU.GetId()); - const u32 owner = mutex->owner.read_sync(); - if (!~owner) - { - return CELL_ESRCH; // mutex is going to be destroyed - } - if (owner != tid) + if (mutex->owner.owner_before(thread) || thread.owner_before(mutex->owner)) // check equality { return CELL_EPERM; } - if (!mutex->recursive_count || (mutex->recursive_count != 1 && !mutex->is_recursive)) + if (!mutex->recursive_count || (!mutex->recursive && mutex->recursive_count != 1)) { - sys_mutex.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive_count.load()); - mutex->recursive_count = 1; + throw __FUNCTION__; } if (!--mutex->recursive_count) { - if (!mutex->owner.compare_and_swap_test(tid, mutex->queue.signal(mutex->protocol))) - { - assert(!"sys_mutex_unlock() failed"); - } - CPU.owned_mutexes--; + mutex->owner.reset(); + mutex->cv.notify_one(); } + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h index 2767dbe31c..3d5f01e509 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mutex.h @@ -1,14 +1,15 @@ #pragma once -struct sys_mutex_attribute +struct sys_mutex_attribute_t { be_t protocol; // SYS_SYNC_FIFO, SYS_SYNC_PRIORITY or SYS_SYNC_PRIORITY_INHERIT be_t recursive; // SYS_SYNC_RECURSIVE or SYS_SYNC_NOT_RECURSIVE - be_t pshared; // always 0x200 (not shared) + be_t pshared; be_t adaptive; be_t ipc_key; be_t flags; be_t pad; + union { char name[8]; @@ -16,34 +17,36 @@ struct sys_mutex_attribute }; }; -struct Mutex +struct mutex_t { - atomic_le_t id; - atomic_le_t owner; - std::atomic recursive_count; // recursive locks count - std::atomic cond_count; // count of condition variables associated - sleep_queue_t queue; - + const bool recursive; const u32 protocol; - const bool is_recursive; + const u64 name; - Mutex(u32 protocol, bool is_recursive, u64 name) - : protocol(protocol) - , is_recursive(is_recursive) - , queue(name) + std::atomic cond_count; // count of condition variables associated + std::atomic recursive_count; + std::weak_ptr owner; + + // TODO: use sleep queue, possibly remove condition variable + std::condition_variable cv; + std::atomic waiters; + + mutex_t(bool recursive, u32 protocol, u64 name) + : recursive(recursive) + , protocol(protocol) + , name(name) , cond_count(0) + , recursive_count(0) + , waiters(0) { - owner.write_relaxed(0); } - - ~Mutex(); }; class PPUThread; // SysCalls -s32 sys_mutex_create(PPUThread& CPU, vm::ptr mutex_id, vm::ptr attr); -s32 sys_mutex_destroy(PPUThread& CPU, u32 mutex_id); +s32 sys_mutex_create(vm::ptr mutex_id, vm::ptr attr); +s32 sys_mutex_destroy(u32 mutex_id); s32 sys_mutex_lock(PPUThread& CPU, u32 mutex_id, u64 timeout); s32 sys_mutex_trylock(PPUThread& CPU, u32 mutex_id); s32 sys_mutex_unlock(PPUThread& CPU, u32 mutex_id); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp b/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp index 70def9c4a3..26ddf369d5 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp @@ -39,7 +39,7 @@ s32 sys_prx_load_module(vm::ptr path, u64 flags, vm::ptraddress), prx->size); - u32 id = sys_prx.GetNewId(prx, TYPE_PRX); + u32 id = Emu.GetIdManager().GetNewID(prx, TYPE_PRX); return id; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp index 35bfa1163e..afc33e5f02 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_rwlock.cpp @@ -36,7 +36,7 @@ s32 sys_rwlock_create(vm::ptr rw_lock_id, vm::ptr a } std::shared_ptr rw(new RWLock(attr->protocol, attr->name_u64)); - const u32 id = sys_rwlock.GetNewId(rw, TYPE_RWLOCK); + const u32 id = Emu.GetIdManager().GetNewID(rw, TYPE_RWLOCK); *rw_lock_id = id; rw->wqueue.set_full_name(fmt::Format("Rwlock(%d)", id)); @@ -49,7 +49,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id) sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } @@ -70,7 +70,7 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout) const u64 start_time = get_system_time(); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } @@ -114,7 +114,7 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id) sys_rwlock.Log("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } @@ -142,7 +142,7 @@ s32 sys_rwlock_runlock(u32 rw_lock_id) sys_rwlock.Log("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } @@ -172,7 +172,7 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout) const u64 start_time = get_system_time(); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } @@ -229,7 +229,7 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id) sys_rwlock.Log("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } @@ -254,7 +254,7 @@ s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id) sys_rwlock.Log("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id); std::shared_ptr rw; - if (!sys_rwlock.CheckId(rw_lock_id, rw)) + if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw)) { return CELL_ESRCH; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp index 18dc511958..9c7d0d864a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_semaphore.cpp @@ -15,7 +15,7 @@ u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u6 { std::shared_ptr sem(new Semaphore(initial_count, max_count, protocol, name_u64)); - const u32 id = sys_semaphore.GetNewId(sem, TYPE_SEMAPHORE); + const u32 id = Emu.GetIdManager().GetNewID(sem, TYPE_SEMAPHORE); sem->queue.set_full_name(fmt::Format("Semaphore(%d)", id)); sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", std::string((const char*)&name_u64, 8).c_str(), protocol, id); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 148a7fa4e6..65940d960b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -221,7 +221,7 @@ u32 spu_thread_group_create(const std::string& name, u32 num, s32 prio, s32 type std::shared_ptr group(new spu_group_t(name, num, prio, type, container)); - return sys_spu.GetNewId(group); + return Emu.GetIdManager().GetNewID(group); } s32 sys_spu_thread_group_create(vm::ptr id, u32 num, s32 prio, vm::ptr attr) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp index 0ebdacd6fe..e663f170ae 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp @@ -13,7 +13,7 @@ s32 sys_timer_create(vm::ptr timer_id) sys_timer.Warning("sys_timer_create(timer_id_addr=0x%x)", timer_id.addr()); std::shared_ptr timer_data(new timer); - *timer_id = sys_timer.GetNewId(timer_data, TYPE_TIMER); + *timer_id = Emu.GetIdManager().GetNewID(timer_data, TYPE_TIMER); return CELL_OK; } @@ -21,7 +21,7 @@ s32 sys_timer_destroy(u32 timer_id) { sys_timer.Todo("sys_timer_destroy(timer_id=%d)", timer_id); - if(!sys_timer.CheckId(timer_id)) return CELL_ESRCH; + if(!Emu.GetIdManager().CheckID(timer_id)) return CELL_ESRCH; Emu.GetIdManager().RemoveID(timer_id); return CELL_OK; @@ -32,7 +32,7 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr inf sys_timer.Warning("sys_timer_get_information(timer_id=%d, info_addr=0x%x)", timer_id, info.addr()); std::shared_ptr timer_data = nullptr; - if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(timer_id, timer_data)) return CELL_ESRCH; *info = timer_data->timer_information_t; return CELL_OK; @@ -43,7 +43,7 @@ s32 sys_timer_start(u32 timer_id, s64 base_time, u64 period) sys_timer.Warning("sys_timer_start_periodic_absolute(timer_id=%d, basetime=%lld, period=%lld)", timer_id, base_time, period); std::shared_ptr timer_data = nullptr; - if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(timer_id, timer_data)) return CELL_ESRCH; if(timer_data->timer_information_t.timer_state != SYS_TIMER_STATE_STOP) return CELL_EBUSY; if(period < 100) return CELL_EINVAL; @@ -67,7 +67,7 @@ s32 sys_timer_stop(u32 timer_id) sys_timer.Todo("sys_timer_stop()"); std::shared_ptr timer_data = nullptr; - if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(timer_id, timer_data)) return CELL_ESRCH; timer_data->timer_information_t.timer_state = SYS_TIMER_STATE_STOP; return CELL_OK; @@ -80,8 +80,8 @@ s32 sys_timer_connect_event_queue(u32 timer_id, u32 queue_id, u64 name, u64 data std::shared_ptr timer_data = nullptr; std::shared_ptr equeue = nullptr; - if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH; - if(!sys_timer.CheckId(queue_id, equeue)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(timer_id, timer_data)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(queue_id, equeue)) return CELL_ESRCH; //TODO: ? @@ -93,7 +93,7 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id) sys_timer.Todo("sys_timer_disconnect_event_queue(timer_id=%d)", timer_id); std::shared_ptr timer_data = nullptr; - if(!sys_timer.CheckId(timer_id, timer_data)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(timer_id, timer_data)) return CELL_ESRCH; //TODO: ? diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp index ab9c5cdcf6..c7a70e3c0b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp @@ -39,7 +39,7 @@ s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 a { // Check memory container. std::shared_ptr ct; - if(!sys_vm.CheckId(cid, ct)) return CELL_ESRCH; + if(!Emu.GetIdManager().GetIDData(cid, ct)) return CELL_ESRCH; current_ct = ct; }