diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index 1b8994f4eb..6cf5180289 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -61,8 +61,19 @@ class ID_manager { std::mutex m_mutex; + // 0 is invalid ID + // 1..0x7fffffff : general purpose IDs + // 0x80000000+ : occupied by fixed IDs std::unordered_map m_id_map; - u32 m_cur_id = 1; // first ID + + // contains the next ID or 0x80000000 | current_ID + u32 m_cur_id = 1; + + static u32 get_type_fixed_id(const std::type_info& type) + { + // TODO: more reliable way of fixed ID generation + return 0x80000000 | static_cast(type.hash_code()); + } public: // check if ID exists and has specified type @@ -70,7 +81,7 @@ public: { std::lock_guard lock(m_mutex); - auto f = m_id_map.find(id); + const auto f = m_id_map.find(id); return f != m_id_map.end() && f->second.info == typeid(T); } @@ -80,26 +91,20 @@ public: { std::lock_guard lock(m_mutex); - auto f = m_id_map.find(id); + const auto f = m_id_map.find(id); return f != m_id_map.end() && f->second.type == type; } - // must be called from the constructor called through make() to get further ID of current object + // must be called from the constructor called through make() or make_ptr() to get further ID of current object u32 get_current_id() { - // if called correctly from make(), the mutex is locked - // if called illegally, the mutex is unlocked with high probability (wrong ID is returned otherwise) - - if (m_mutex.try_lock()) + if ((m_cur_id & 0x80000000) == 0) { - // schedule unlocking - std::lock_guard lock(m_mutex, std::adopt_lock); - throw EXCEPTION("Current ID is not available"); } - return m_cur_id; + return m_cur_id & 0x7fffffff; } void clear() @@ -110,6 +115,36 @@ public: m_cur_id = 1; // first ID } + // add fixed ID of specified type only if it doesn't exist (each type has unique id) + template::value>> std::shared_ptr make_fixed(Args&&... args) + { + std::lock_guard lock(m_mutex); + + const u32 type = ID_type::type; + + static const u32 id = get_type_fixed_id(typeid(T)); + + const auto found = m_id_map.find(id); + + // ensure that this ID doesn't exist + if (found == m_id_map.end()) + { + auto ptr = std::make_shared(std::forward(args)...); + + m_id_map.emplace(id, ID_data_t(ptr, type, id)); + + return std::move(ptr); + } + + // ensure that this ID is not occupied by the object of another type + if (found->second.info == typeid(T)) + { + return nullptr; + } + + throw EXCEPTION("Collision occured ('%s' and '%s', id=0x%x)", found->second.info.name(), typeid(T).name(), id); + } + // add new ID of specified type with specified constructor arguments (returns object) template::value>> std::shared_ptr make_ptr(Args&&... args) { @@ -117,11 +152,20 @@ public: const u32 type = ID_type::type; - auto ptr = std::make_shared(std::forward(args)...); + m_cur_id |= 0x80000000; - m_id_map.emplace(m_cur_id, ID_data_t(ptr, type, m_cur_id)); + if (const u32 id = m_cur_id & 0x7fffffff) + { + auto ptr = std::make_shared(std::forward(args)...); - return m_cur_id++, std::move(ptr); + m_id_map.emplace(id, ID_data_t(ptr, type, id)); + + m_cur_id = id + 1; + + return std::move(ptr); + } + + throw EXCEPTION("Out of IDs"); } // add new ID of specified type with specified constructor arguments (returns id) @@ -131,9 +175,35 @@ public: const u32 type = ID_type::type; - m_id_map.emplace(m_cur_id, ID_data_t(std::make_shared(std::forward(args)...), type, m_cur_id)); + m_cur_id |= 0x80000000; - return m_cur_id++; + if (const u32 id = m_cur_id & 0x7fffffff) + { + m_id_map.emplace(id, ID_data_t(std::make_shared(std::forward(args)...), type, id)); + + m_cur_id = id + 1; + + return id; + } + + throw EXCEPTION("Out of IDs"); + } + + // load fixed ID of specified type Orig, optionally static_cast to T + template auto get() -> decltype(std::shared_ptr(static_cast(std::declval()))) + { + std::lock_guard lock(m_mutex); + + static const u32 id = get_type_fixed_id(typeid(T)); + + const auto found = m_id_map.find(id); + + if (found == m_id_map.end() || found->second.info != typeid(Orig)) + { + return nullptr; + } + + return std::static_pointer_cast(found->second.data); } // load ID created with type Orig, optionally static_cast to T @@ -141,14 +211,14 @@ public: { std::lock_guard lock(m_mutex); - auto f = m_id_map.find(id); + const auto found = m_id_map.find(id); - if (f == m_id_map.end() || f->second.info != typeid(Orig)) + if (found == m_id_map.end() || found->second.info != typeid(Orig)) { return nullptr; } - return std::static_pointer_cast(f->second.data); + return std::static_pointer_cast(found->second.data); } // load all IDs created with type Orig, optionally static_cast to T @@ -171,18 +241,38 @@ public: return result; } - template bool remove(u32 id) + // remove fixed ID created with type T + template bool remove() { std::lock_guard lock(m_mutex); - auto item = m_id_map.find(id); + static const u32 id = get_type_fixed_id(typeid(T)); - if (item == m_id_map.end() || item->second.info != typeid(T)) + const auto found = m_id_map.find(id); + + if (found == m_id_map.end() || found->second.info != typeid(T)) { return false; } - m_id_map.erase(item); + m_id_map.erase(found); + + return true; + } + + // remove ID created with type T + template bool remove(u32 id) + { + std::lock_guard lock(m_mutex); + + const auto found = m_id_map.find(id); + + if (found == m_id_map.end() || found->second.info != typeid(T)) + { + return false; + } + + m_id_map.erase(found); return true; } @@ -224,7 +314,7 @@ public: } // get sorted ID list - template std::set get_IDs() + template std::set get_set() { std::lock_guard lock(m_mutex); @@ -244,7 +334,7 @@ public: } // get sorted ID list - std::set get_IDs(u32 type) + std::set get_set(u32 type) { std::lock_guard lock(m_mutex); diff --git a/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp b/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp index 7d91dff15f..8f6cf56c85 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp @@ -1,14 +1,14 @@ #include "stdafx.h" #include "Ini.h" #include "Emu/Memory/Memory.h" +#include "Emu/IdManager.h" +#include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "cellCamera.h" extern Module cellCamera; -std::unique_ptr g_camera; - s32 cellCameraInit() { cellCamera.Warning("cellCameraInit()"); @@ -18,53 +18,50 @@ s32 cellCameraInit() return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND; } - if (g_camera->init) + const auto camera = Emu.GetIdManager().make_fixed(); + + if (!camera) { return CELL_CAMERA_ERROR_ALREADY_INIT; } if (Ini.CameraType.GetValue() == 1) { - g_camera->attr[CELL_CAMERA_SATURATION] = { 164 }; - g_camera->attr[CELL_CAMERA_BRIGHTNESS] = { 96 }; - g_camera->attr[CELL_CAMERA_AEC] = { 1 }; - g_camera->attr[CELL_CAMERA_AGC] = { 1 }; - g_camera->attr[CELL_CAMERA_AWB] = { 1 }; - g_camera->attr[CELL_CAMERA_ABC] = { 0 }; - g_camera->attr[CELL_CAMERA_LED] = { 1 }; - g_camera->attr[CELL_CAMERA_QS] = { 0 }; - g_camera->attr[CELL_CAMERA_NONZEROCOEFFS] = { 32, 32 }; - g_camera->attr[CELL_CAMERA_YUVFLAG] = { 0 }; - g_camera->attr[CELL_CAMERA_BACKLIGHTCOMP] = { 0 }; - g_camera->attr[CELL_CAMERA_MIRRORFLAG] = { 1 }; - g_camera->attr[CELL_CAMERA_422FLAG] = { 1 }; - g_camera->attr[CELL_CAMERA_USBLOAD] = { 4 }; + camera->attr[CELL_CAMERA_SATURATION] = { 164 }; + camera->attr[CELL_CAMERA_BRIGHTNESS] = { 96 }; + camera->attr[CELL_CAMERA_AEC] = { 1 }; + camera->attr[CELL_CAMERA_AGC] = { 1 }; + camera->attr[CELL_CAMERA_AWB] = { 1 }; + camera->attr[CELL_CAMERA_ABC] = { 0 }; + camera->attr[CELL_CAMERA_LED] = { 1 }; + camera->attr[CELL_CAMERA_QS] = { 0 }; + camera->attr[CELL_CAMERA_NONZEROCOEFFS] = { 32, 32 }; + camera->attr[CELL_CAMERA_YUVFLAG] = { 0 }; + camera->attr[CELL_CAMERA_BACKLIGHTCOMP] = { 0 }; + camera->attr[CELL_CAMERA_MIRRORFLAG] = { 1 }; + camera->attr[CELL_CAMERA_422FLAG] = { 1 }; + camera->attr[CELL_CAMERA_USBLOAD] = { 4 }; } else if (Ini.CameraType.GetValue() == 2) { - g_camera->attr[CELL_CAMERA_SATURATION] = { 64 }; - g_camera->attr[CELL_CAMERA_BRIGHTNESS] = { 8 }; - g_camera->attr[CELL_CAMERA_AEC] = { 1 }; - g_camera->attr[CELL_CAMERA_AGC] = { 1 }; - g_camera->attr[CELL_CAMERA_AWB] = { 1 }; - g_camera->attr[CELL_CAMERA_LED] = { 1 }; - g_camera->attr[CELL_CAMERA_BACKLIGHTCOMP] = { 0 }; - g_camera->attr[CELL_CAMERA_MIRRORFLAG] = { 1 }; - g_camera->attr[CELL_CAMERA_GAMMA] = { 1 }; - g_camera->attr[CELL_CAMERA_AGCLIMIT] = { 4 }; - g_camera->attr[CELL_CAMERA_DENOISE] = { 0 }; - g_camera->attr[CELL_CAMERA_FRAMERATEADJUST] = { 0 }; - g_camera->attr[CELL_CAMERA_PIXELOUTLIERFILTER] = { 1 }; - g_camera->attr[CELL_CAMERA_AGCLOW] = { 48 }; - g_camera->attr[CELL_CAMERA_AGCHIGH] = { 64 }; + camera->attr[CELL_CAMERA_SATURATION] = { 64 }; + camera->attr[CELL_CAMERA_BRIGHTNESS] = { 8 }; + camera->attr[CELL_CAMERA_AEC] = { 1 }; + camera->attr[CELL_CAMERA_AGC] = { 1 }; + camera->attr[CELL_CAMERA_AWB] = { 1 }; + camera->attr[CELL_CAMERA_LED] = { 1 }; + camera->attr[CELL_CAMERA_BACKLIGHTCOMP] = { 0 }; + camera->attr[CELL_CAMERA_MIRRORFLAG] = { 1 }; + camera->attr[CELL_CAMERA_GAMMA] = { 1 }; + camera->attr[CELL_CAMERA_AGCLIMIT] = { 4 }; + camera->attr[CELL_CAMERA_DENOISE] = { 0 }; + camera->attr[CELL_CAMERA_FRAMERATEADJUST] = { 0 }; + camera->attr[CELL_CAMERA_PIXELOUTLIERFILTER] = { 1 }; + camera->attr[CELL_CAMERA_AGCLOW] = { 48 }; + camera->attr[CELL_CAMERA_AGCHIGH] = { 64 }; } // TODO: Some other default attributes? Need to check the actual behaviour on a real PS3. - if (g_camera->init.exchange(true)) - { - throw EXCEPTION("Unexpected"); - } - return CELL_OK; } @@ -72,16 +69,11 @@ s32 cellCameraEnd() { cellCamera.Warning("cellCameraEnd()"); - if (!g_camera->init) + if (!Emu.GetIdManager().remove()) { return CELL_CAMERA_ERROR_NOT_INIT; } - if (!g_camera->init.exchange(false)) - { - throw EXCEPTION("Unexpected"); - } - return CELL_OK; } @@ -113,7 +105,9 @@ s32 cellCameraGetType(s32 dev_num, vm::ptr type) { cellCamera.Warning("cellCameraGetType(dev_num=%d, type=*0x%x)", dev_num, type); - if (!g_camera->init.load()) + const auto camera = Emu.GetIdManager().get(); + + if (!camera) { return CELL_CAMERA_ERROR_NOT_INIT; } @@ -165,7 +159,9 @@ s32 cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr arg1, vm::ptrinit.load()) + const auto camera = Emu.GetIdManager().get(); + + if (!camera) { return CELL_CAMERA_ERROR_NOT_INIT; } @@ -175,8 +171,8 @@ s32 cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr arg1, vm::ptrattr[attrib].v1; - *arg2 = g_camera->attr[attrib].v2; + *arg1 = camera->attr[attrib].v1; + *arg2 = camera->attr[attrib].v2; return CELL_OK; } @@ -187,7 +183,9 @@ s32 cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2) const auto attr_name = camera_t::get_attr_name(attrib); - if (!g_camera->init.load()) + const auto camera = Emu.GetIdManager().get(); + + if (!camera) { return CELL_CAMERA_ERROR_NOT_INIT; } @@ -197,7 +195,7 @@ s32 cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2) return CELL_CAMERA_ERROR_PARAM; } - g_camera->attr[attrib] = { arg1, arg2 }; + camera->attr[attrib] = { arg1, arg2 }; return CELL_OK; } @@ -306,8 +304,6 @@ s32 cellCameraRemoveNotifyEventQueue2(u64 key) Module cellCamera("cellCamera", []() { - g_camera = std::make_unique(); - REG_FUNC(cellCamera, cellCameraInit); REG_FUNC(cellCamera, cellCameraEnd); REG_FUNC(cellCamera, cellCameraOpen); // was "renamed", but exists diff --git a/rpcs3/Emu/SysCalls/Modules/cellCamera.h b/rpcs3/Emu/SysCalls/Modules/cellCamera.h index 2718516e6d..df91a1bd04 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCamera.h +++ b/rpcs3/Emu/SysCalls/Modules/cellCamera.h @@ -315,8 +315,6 @@ struct CellCameraReadEx // Custom struct to keep track of cameras struct camera_t { - std::atomic init{ false }; - struct attr_t { u32 v1, v2; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp index 9580a4cf98..70f788ff94 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_process.cpp @@ -113,7 +113,7 @@ s32 sys_process_get_id(u32 object, vm::ptr buffer, u32 size, vm::ptr s case SYS_LWCOND_OBJECT: case SYS_EVENT_FLAG_OBJECT: { - const auto objects = Emu.GetIdManager().get_IDs(object); + const auto objects = Emu.GetIdManager().get_set(object); u32 i = 0; diff --git a/rpcs3/Gui/KernelExplorer.cpp b/rpcs3/Gui/KernelExplorer.cpp index 9f81ed4b85..6ea6438768 100644 --- a/rpcs3/Gui/KernelExplorer.cpp +++ b/rpcs3/Gui/KernelExplorer.cpp @@ -14,7 +14,9 @@ #include "Emu/SysCalls/lv2/sys_cond.h" #include "Emu/SysCalls/lv2/sys_semaphore.h" #include "Emu/SysCalls/lv2/sys_event.h" -#include "Emu/SysCalls/lv2/sys_process.h" +#include "Emu/SysCalls/lv2/sys_event_flag.h" +#include "Emu/SysCalls/lv2/sys_prx.h" +#include "Emu/SysCalls/lv2/sys_memory.h" #include "KernelExplorer.h" @@ -78,12 +80,12 @@ void KernelExplorer::Update() // TODO: FileSystem // Semaphores - if (u32 count = Emu.GetIdManager().get_count(SYS_SEMAPHORE_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Semaphores (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_SEMAPHORE_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto sem = Emu.GetIdManager().get(id); sprintf(name, "Semaphore: ID = 0x%x '%s', Count = %d, Max Count = %d, Waiters = %#llx", id, &name64(sem->name), sem->value.load(), sem->max, sem->sq.size()); @@ -92,12 +94,12 @@ void KernelExplorer::Update() } // Mutexes - if (u32 count = Emu.GetIdManager().get_count(SYS_MUTEX_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Mutexes (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_MUTEX_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto mutex = Emu.GetIdManager().get(id); sprintf(name, "Mutex: ID = 0x%x '%s'", id, &name64(mutex->name)); @@ -106,12 +108,12 @@ void KernelExplorer::Update() } // Light Weight Mutexes - if (u32 count = Emu.GetIdManager().get_count(SYS_LWMUTEX_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Lightweight Mutexes (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_LWMUTEX_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto lwm = Emu.GetIdManager().get(id); sprintf(name, "Lightweight Mutex: ID = 0x%x '%s'", id, &name64(lwm->name)); @@ -120,12 +122,12 @@ void KernelExplorer::Update() } // Condition Variables - if (u32 count = Emu.GetIdManager().get_count(SYS_COND_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Condition Variables (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_COND_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto cond = Emu.GetIdManager().get(id); sprintf(name, "Condition Variable: ID = 0x%x '%s'", id, &name64(cond->name)); @@ -134,12 +136,12 @@ void KernelExplorer::Update() } // Light Weight Condition Variables - if (u32 count = Emu.GetIdManager().get_count(SYS_LWCOND_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Lightweight Condition Variables (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_LWCOND_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto lwc = Emu.GetIdManager().get(id); sprintf(name, "Lightweight Condition Variable: ID = 0x%x '%s'", id, &name64(lwc->name)); @@ -148,12 +150,12 @@ void KernelExplorer::Update() } // Event Queues - if (u32 count = Emu.GetIdManager().get_count(SYS_EVENT_QUEUE_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Event Queues (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_EVENT_QUEUE_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto queue = Emu.GetIdManager().get(id); sprintf(name, "Event Queue: ID = 0x%x '%s', Key = %#llx", id, &name64(queue->name), queue->key); @@ -162,12 +164,12 @@ void KernelExplorer::Update() } // Event Ports - if (u32 count = Emu.GetIdManager().get_count(SYS_EVENT_PORT_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Event Ports (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto id : Emu.GetIdManager().get_IDs(SYS_EVENT_PORT_OBJECT)) + for (const auto id : Emu.GetIdManager().get_set()) { const auto port = Emu.GetIdManager().get(id); sprintf(name, "Event Port: ID = 0x%x, Name = %#llx", id, port->name); @@ -176,14 +178,14 @@ void KernelExplorer::Update() } // Modules - if (u32 count = Emu.GetIdManager().get_count(SYS_PRX_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Modules (%d)", count); const auto& node = m_tree->AppendItem(root, name); //sprintf(name, "Segment List (%l)", 2 * objects.size()); // TODO: Assuming 2 segments per PRX file is not good //m_tree->AppendItem(node, name); - for (const auto& id : Emu.GetIdManager().get_IDs(SYS_PRX_OBJECT)) + for (const auto& id : Emu.GetIdManager().get_set()) { sprintf(name, "PRX: ID = 0x%x", id); m_tree->AppendItem(node, name); @@ -191,12 +193,12 @@ void KernelExplorer::Update() } // Memory Containers - if (u32 count = Emu.GetIdManager().get_count(SYS_MEM_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Memory Containers (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto& id : Emu.GetIdManager().get_IDs(SYS_MEM_OBJECT)) + for (const auto& id : Emu.GetIdManager().get_set()) { sprintf(name, "Memory Container: ID = 0x%x", id); m_tree->AppendItem(node, name); @@ -204,12 +206,12 @@ void KernelExplorer::Update() } // Event Flags - if (u32 count = Emu.GetIdManager().get_count(SYS_EVENT_FLAG_OBJECT)) + if (u32 count = Emu.GetIdManager().get_count()) { sprintf(name, "Event Flags (%d)", count); const auto& node = m_tree->AppendItem(root, name); - for (const auto& id : Emu.GetIdManager().get_IDs(SYS_EVENT_FLAG_OBJECT)) + for (const auto& id : Emu.GetIdManager().get_set()) { sprintf(name, "Event Flag: ID = 0x%x", id); m_tree->AppendItem(node, name);