diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 42bdedb6d2..89a8c073ca 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -397,7 +397,7 @@ s32 sceKernelCreateEventFlag(vm::psv::ptr pName, u32 attr, u32 initP { sceLibKernel.Error("sceKernelCreateEventFlag(pName=*0x%x, attr=0x%x, initPattern=0x%x, pOptParam=*0x%x)", pName, attr, initPattern, pOptParam); - if (s32 id = g_psv_ef_list.add(new psv_event_flag_t(pName.get_ptr(), attr, initPattern), 0)) + if (s32 id = g_psv_ef_list.create(pName.get_ptr(), attr, initPattern)) { return id; } @@ -461,7 +461,7 @@ s32 sceKernelCreateSema(vm::psv::ptr pName, u32 attr, s32 initCount, { sceLibKernel.Error("sceKernelCreateSema(pName=*0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=*0x%x)", pName, attr, initCount, maxCount, pOptParam); - if (s32 id = g_psv_sema_list.add(new psv_sema_t(pName.get_ptr(), attr, initCount, maxCount), 0)) + if (s32 id = g_psv_sema_list.create(pName.get_ptr(), attr, initCount, maxCount)) { return id; } @@ -473,7 +473,7 @@ s32 sceKernelDeleteSema(s32 semaId) { sceLibKernel.Error("sceKernelDeleteSema(semaId=0x%x)", semaId); - ref_t sema = g_psv_sema_list.get(semaId); + const auto sema = g_psv_sema_list.get(semaId); if (!sema) { @@ -502,7 +502,7 @@ s32 sceKernelWaitSema(s32 semaId, s32 needCount, vm::psv::ptr pTimeout) { sceLibKernel.Error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=*0x%x)", semaId, needCount, pTimeout); - ref_t sema = g_psv_sema_list.get(semaId); + const auto sema = g_psv_sema_list.get(semaId); if (!sema) { @@ -545,7 +545,7 @@ s32 sceKernelCreateMutex(vm::psv::ptr pName, u32 attr, s32 initCount { sceLibKernel.Error("sceKernelCreateMutex(pName=*0x%x, attr=0x%x, initCount=%d, pOptParam=*0x%x)", pName, attr, initCount, pOptParam); - if (s32 id = g_psv_mutex_list.add(new psv_mutex_t(pName.get_ptr(), attr, initCount), 0)) + if (s32 id = g_psv_mutex_list.create(pName.get_ptr(), attr, initCount)) { return id; } @@ -646,7 +646,7 @@ s32 sceKernelCreateCond(vm::psv::ptr pName, u32 attr, s32 mutexId, v { sceLibKernel.Error("sceKernelCreateCond(pName=*0x%x, attr=0x%x, mutexId=0x%x, pOptParam=*0x%x)", pName, attr, mutexId, pOptParam); - if (s32 id = g_psv_cond_list.add(new psv_cond_t(pName.get_ptr(), attr, mutexId), 0)) + if (s32 id = g_psv_cond_list.create(pName.get_ptr(), attr, mutexId)) { return id; } diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 431cbbf33f..0b04eec212 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -21,18 +21,12 @@ union psv_uid_t } }; -template +template class psv_object_list_t // Class for managing object data { -public: - typedef refcounter_t rc_type; - typedef ref_t ref_type; - - static const u32 max = 0x8000; - -private: - std::array m_data; + std::array, 0x8000> m_data; std::atomic m_hint; // guessing next free position + std::mutex m_mutex; void error(s32 uid) { @@ -45,17 +39,8 @@ public: { } - psv_object_list_t(const psv_object_list_t&) = delete; - psv_object_list_t(psv_object_list_t&&) = delete; - - psv_object_list_t& operator =(const psv_object_list_t&) = delete; - psv_object_list_t& operator =(psv_object_list_t&&) = delete; - -public: - static const u32 uid_class = type; - // check if UID is potentially valid (will return true even if the object doesn't exist) - bool check(s32 uid) + inline static bool check(s32 uid) { const psv_uid_t id = psv_uid_t::make(uid); @@ -64,29 +49,35 @@ public: } // share object with UID specified - ref_type get(s32 uid) + __forceinline std::shared_ptr get(s32 uid) { if (!check(uid)) { - return ref_type(); + return nullptr; } - return &m_data[psv_uid_t::make(uid).number]; + std::lock_guard lock(m_mutex); + + return m_data[psv_uid_t::make(uid).number]; } - ref_type operator [](s32 uid) + __forceinline std::shared_ptr operator [](s32 uid) { - return get(uid); + return this->get(uid); } - // generate UID for newly created object (will return zero if the limit exceeded) - s32 add(T* data, s32 error_code) + // create new object and generate UID for it, or do nothing and return zero (if limit reached) + template s32 create(Args&&... args) { + std::lock_guard lock(m_mutex); + for (u32 i = 0, j = m_hint; i < m_data.size(); i++, j = (j + 1) % m_data.size()) { // find an empty position and copy the pointer - if (m_data[j].try_set(data)) + if (!m_data[j]) { + m_data[j] = std::make_shared(args...); // construct object with specified arguments + m_hint = (j + 1) % m_data.size(); // guess next position psv_uid_t id = psv_uid_t::make(1); // make UID @@ -97,8 +88,7 @@ public: } } - delete data; - return error_code; + return 0; } // remove object with specified UID @@ -109,19 +99,29 @@ public: return false; } + std::lock_guard lock(m_mutex); + const u32 pos = psv_uid_t::make(uid).number; m_hint = std::min(pos, m_hint); - return m_data[pos].try_remove(); + if (!m_data[pos]) + { + return false; + } + + m_data[pos].reset(); + return true; } // remove all objects void clear() { + std::lock_guard lock(m_mutex); + for (auto& v : m_data) { - v.try_remove(); + v.reset(); } m_hint = 0; diff --git a/rpcs3/Emu/Memory/refcnt.h b/rpcs3/Emu/Memory/refcnt.h deleted file mode 100644 index c756d93722..0000000000 --- a/rpcs3/Emu/Memory/refcnt.h +++ /dev/null @@ -1,196 +0,0 @@ -#pragma once -#include "atomic.h" - -// run endless loop for debugging -__forceinline static void deadlock() -{ - while (true) - { - std::this_thread::yield(); - } -} - -template -class ref_t; - -template -class refcounter_t // non-relocateable "smart" pointer with ref counter -{ -public: - typedef T type, * p_type; - typedef refcounter_t rc_type; - - // counter > 0, ptr != nullptr : object exists and shared - // counter > 0, ptr == nullptr : object exists and shared, but not owned by refcounter_t - // counter == 0, ptr != nullptr : object exists and not shared - // counter == 0, ptr == nullptr : object doesn't exist - // counter < 0 : bad state, used to provoke error for debugging - - struct sync_var_t - { - s64 counter; - p_type ptr; - }; - -private: - atomic_le_t m_var; - - friend class ref_t; - - // try to share object (increment counter), returns nullptr if doesn't exist or cannot be shared - __forceinline p_type ref_inc() - { - p_type out_ptr; - - m_var.atomic_op([&out_ptr](sync_var_t& v) - { - assert(v.counter >= 0); - - if ((out_ptr = v.ptr)) - { - v.counter++; - } - }); - - return out_ptr; - } - - // try to release previously shared object (decrement counter), returns true if should be deleted - __forceinline bool ref_dec() - { - bool do_delete; - - m_var.atomic_op([&do_delete](sync_var_t& v) - { - assert(v.counter > 0); - - do_delete = !--v.counter && !v.ptr; - }); - - return do_delete; - } - -public: - refcounter_t() - { - // initialize ref counter - m_var.write_relaxed({ 0, nullptr }); - } - - ~refcounter_t() - { - // set bad state - auto ref = m_var.exchange({ -1, nullptr }); - - // finalize - if (ref.counter) - { - deadlock(); - } - else if (ref.ptr) - { - delete ref.ptr; - } - } - - refcounter_t(const rc_type& right) = delete; - refcounter_t(rc_type&& right_rv) = delete; - - rc_type& operator =(const rc_type& right) = delete; - rc_type& operator =(rc_type&& right_rv) = delete; - -public: - // try to set new object (if it doesn't exist) - bool try_set(p_type ptr) - { - return m_var.compare_and_swap_test({ 0, nullptr }, { 0, ptr }); - } - - // try to remove object (if exists) - bool try_remove() - { - bool out_res; - p_type out_ptr; - - m_var.atomic_op([&out_res, &out_ptr](sync_var_t& v) - { - out_res = (out_ptr = v.ptr); - - if (v.counter) - { - out_ptr = nullptr; - } - - v.ptr = nullptr; - }); - - if (out_ptr) - { - delete out_ptr; - } - - return out_res; - } -}; - -template -class ref_t -{ -public: - typedef T type, * p_type; - typedef refcounter_t * rc_type; - -private: - rc_type m_rc; - p_type m_ptr; - -public: - ref_t() - : m_rc(nullptr) - , m_ptr(nullptr) - { - } - - ref_t(rc_type rc) - : m_rc(rc) - , m_ptr(rc->ref_inc()) - { - } - - ~ref_t() - { - if (m_ptr && m_rc->ref_dec()) - { - delete m_ptr; - } - } - - ref_t(const ref_t& right) = delete; - - ref_t(ref_t&& right_rv) - : m_rc(right_rv.m_rc) - , m_ptr(right_rv.m_ptr) - { - right_rv.m_rc = nullptr; - right_rv.m_ptr = nullptr; - } - - ref_t& operator =(const ref_t& right) = delete; - ref_t& operator =(ref_t&& right_rv) = delete; - -public: - T& operator *() const - { - return *m_ptr; - } - - T* operator ->() const - { - return m_ptr; - } - - explicit operator bool() const - { - return m_ptr; - } -}; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_cond.h b/rpcs3/Emu/SysCalls/lv2/sys_cond.h index 43164e58c7..25cd53b417 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_cond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_cond.h @@ -30,7 +30,7 @@ struct cond_t : mutex(mutex) , name(name) , signaled(0) - , waiters(0) + //, waiters(0) { } }; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h index 7e94ccbdc2..04a7587b6f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwcond.h @@ -32,7 +32,7 @@ struct lwcond_t : name(name) , signaled1(0) , signaled2(0) - , waiters(0) + //, waiters(0) { } }; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 70f6cb37cc..80ef571ee6 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -418,7 +418,6 @@ - diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 9adbdd03c6..aa8ddbdc0e 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1543,9 +1543,6 @@ Emu\Memory - - Emu\Memory - Emu\SysCalls\lv2 diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index b6a071cf0e..ddc41e96fe 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -61,7 +61,6 @@ template __forceinline T align(const T addr, int align) #include "Utilities/StrFmt.h" #include "Emu/Memory/atomic.h" -#include "Emu/Memory/refcnt.h" #define _PRGNAME_ "RPCS3" #define _PRGVER_ "0.0.0.5"