mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
core: Move IDM to FXO
This commit is contained in:
parent
bf1756448e
commit
4a9be0a8d2
3 changed files with 43 additions and 68 deletions
|
@ -5,22 +5,15 @@
|
||||||
shared_mutex id_manager::g_mutex;
|
shared_mutex id_manager::g_mutex;
|
||||||
|
|
||||||
thread_local DECLARE(idm::g_id);
|
thread_local DECLARE(idm::g_id);
|
||||||
DECLARE(idm::g_map);
|
|
||||||
|
|
||||||
id_manager::id_map::pointer idm::allocate_id(const id_manager::id_key& info, u32 base, u32 step, u32 count, std::pair<u32, u32> invl_range)
|
idm::map_data* idm::allocate_id(std::vector<map_data>& vec, u32 type_id, u32 base, u32 step, u32 count, std::pair<u32, u32> invl_range)
|
||||||
{
|
{
|
||||||
// Base type id is stored in value
|
|
||||||
auto& vec = g_map[info.value()];
|
|
||||||
|
|
||||||
// Preallocate memory
|
|
||||||
vec.reserve(count);
|
|
||||||
|
|
||||||
if (vec.size() < count)
|
if (vec.size() < count)
|
||||||
{
|
{
|
||||||
// Try to emplace back
|
// Try to emplace back
|
||||||
const u32 _next = base + step * ::size32(vec);
|
const u32 _next = base + step * ::size32(vec);
|
||||||
g_id = _next;
|
g_id = _next;
|
||||||
vec.emplace_back(id_manager::id_key(_next, info.type()), nullptr);
|
vec.emplace_back(id_manager::id_key(_next, type_id), nullptr);
|
||||||
return &vec.back();
|
return &vec.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +28,7 @@ id_manager::id_map::pointer idm::allocate_id(const id_manager::id_key& info, u32
|
||||||
// Incremenet ID invalidation counter
|
// Incremenet ID invalidation counter
|
||||||
const u32 id = next | ((ptr->first + (1u << invl_range.first)) & (invl_range.second ? (((1u << invl_range.second) - 1) << invl_range.first) : 0));
|
const u32 id = next | ((ptr->first + (1u << invl_range.first)) & (invl_range.second ? (((1u << invl_range.second) - 1) << invl_range.first) : 0));
|
||||||
g_id = id;
|
g_id = id;
|
||||||
ptr->first = id_manager::id_key(id, info.type());
|
ptr->first = id_manager::id_key(id, type_id);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,25 +36,3 @@ id_manager::id_map::pointer idm::allocate_id(const id_manager::id_key& info, u32
|
||||||
// Out of IDs
|
// Out of IDs
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idm::init()
|
|
||||||
{
|
|
||||||
// Allocate
|
|
||||||
g_map.resize(id_manager::typeinfo::get_count());
|
|
||||||
idm::clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void idm::clear()
|
|
||||||
{
|
|
||||||
// Call recorded finalization functions for all IDs
|
|
||||||
for (auto& map : g_map)
|
|
||||||
{
|
|
||||||
for (auto& pair : map)
|
|
||||||
{
|
|
||||||
pair.second.reset();
|
|
||||||
pair.first = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
map.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "util/fixed_typemap.hpp"
|
||||||
|
|
||||||
|
extern stx::manual_typemap<void, 0x20'00000, 128> g_fixed_typemap;
|
||||||
|
|
||||||
|
constexpr auto* g_fxo = &g_fixed_typemap;
|
||||||
|
|
||||||
// Helper namespace
|
// Helper namespace
|
||||||
namespace id_manager
|
namespace id_manager
|
||||||
{
|
{
|
||||||
|
@ -132,7 +138,18 @@ namespace id_manager
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using id_map = std::vector<std::pair<id_key, std::shared_ptr<void>>>;
|
template <typename T>
|
||||||
|
struct id_map
|
||||||
|
{
|
||||||
|
std::vector<std::pair<id_key, std::shared_ptr<void>>> vec;
|
||||||
|
shared_mutex mutex; // TODO: Use this instead of global mutex
|
||||||
|
|
||||||
|
id_map()
|
||||||
|
{
|
||||||
|
// Preallocate memory
|
||||||
|
vec.reserve(T::id_count);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs.
|
// Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs.
|
||||||
|
@ -141,9 +158,6 @@ class idm
|
||||||
// Last allocated ID for constructors
|
// Last allocated ID for constructors
|
||||||
static thread_local u32 g_id;
|
static thread_local u32 g_id;
|
||||||
|
|
||||||
// Type Index -> ID -> Object. Use global since only one process is supported atm.
|
|
||||||
static std::vector<id_manager::id_map> g_map;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline u32 get_type()
|
static inline u32 get_type()
|
||||||
{
|
{
|
||||||
|
@ -248,12 +262,14 @@ class idm
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using map_data = std::pair<id_manager::id_key, std::shared_ptr<void>>;
|
||||||
|
|
||||||
// Prepare new ID (returns nullptr if out of resources)
|
// Prepare new ID (returns nullptr if out of resources)
|
||||||
static id_manager::id_map::pointer allocate_id(const id_manager::id_key& info, u32 base, u32 step, u32 count, std::pair<u32, u32> invl_range);
|
static map_data* allocate_id(std::vector<map_data>& vec, u32 type_id, u32 base, u32 step, u32 count, std::pair<u32, u32> invl_range);
|
||||||
|
|
||||||
// Find ID (additionally check type if types are not equal)
|
// Find ID (additionally check type if types are not equal)
|
||||||
template <typename T, typename Type>
|
template <typename T, typename Type>
|
||||||
static id_manager::id_map::pointer find_id(u32 id)
|
static map_data* find_id(u32 id)
|
||||||
{
|
{
|
||||||
static_assert(id_manager::id_verify<T, Type>::value, "Invalid ID type combination");
|
static_assert(id_manager::id_verify<T, Type>::value, "Invalid ID type combination");
|
||||||
|
|
||||||
|
@ -264,7 +280,7 @@ class idm
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& vec = g_map[get_type<T>()];
|
auto& vec = g_fxo->get<id_manager::id_map<T>>().vec;
|
||||||
|
|
||||||
if (index >= vec.size())
|
if (index >= vec.size())
|
||||||
{
|
{
|
||||||
|
@ -289,20 +305,19 @@ class idm
|
||||||
|
|
||||||
// Allocate new ID and assign the object from the provider()
|
// Allocate new ID and assign the object from the provider()
|
||||||
template <typename T, typename Type, typename F>
|
template <typename T, typename Type, typename F>
|
||||||
static id_manager::id_map::pointer create_id(F&& provider)
|
static map_data* create_id(F&& provider)
|
||||||
{
|
{
|
||||||
static_assert(id_manager::id_verify<T, Type>::value, "Invalid ID type combination");
|
static_assert(id_manager::id_verify<T, Type>::value, "Invalid ID type combination");
|
||||||
|
|
||||||
// ID info
|
|
||||||
const id_manager::id_key info{get_type<T>(), get_type<Type>()};
|
|
||||||
|
|
||||||
// ID traits
|
// ID traits
|
||||||
using traits = id_manager::id_traits<Type>;
|
using traits = id_manager::id_traits<Type>;
|
||||||
|
|
||||||
// Allocate new id
|
// Allocate new id
|
||||||
std::lock_guard lock(id_manager::g_mutex);
|
std::lock_guard lock(id_manager::g_mutex);
|
||||||
|
|
||||||
if (auto* place = allocate_id(info, traits::base, traits::step, traits::count, traits::invl_range))
|
auto& map = g_fxo->get<id_manager::id_map<T>>();
|
||||||
|
|
||||||
|
if (auto* place = allocate_id(map.vec, get_type<Type>(), traits::base, traits::step, traits::count, traits::invl_range))
|
||||||
{
|
{
|
||||||
// Get object, store it
|
// Get object, store it
|
||||||
place->second = provider();
|
place->second = provider();
|
||||||
|
@ -317,18 +332,13 @@ class idm
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Initialize object manager
|
|
||||||
static void init();
|
|
||||||
|
|
||||||
// Remove all objects
|
|
||||||
static void clear();
|
|
||||||
|
|
||||||
// Remove all objects of a type
|
// Remove all objects of a type
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline void clear()
|
static inline void clear()
|
||||||
{
|
{
|
||||||
std::lock_guard lock(id_manager::g_mutex);
|
std::lock_guard lock(id_manager::g_mutex);
|
||||||
g_map[id_manager::typeinfo::get_index<T>()].clear();
|
g_fxo->get<id_manager::id_map<T>>().vec.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get last ID (updated in create_id/allocate_id)
|
// Get last ID (updated in create_id/allocate_id)
|
||||||
|
@ -387,7 +397,7 @@ public:
|
||||||
|
|
||||||
// Access the ID record without locking (unsafe)
|
// Access the ID record without locking (unsafe)
|
||||||
template <typename T, typename Get = T>
|
template <typename T, typename Get = T>
|
||||||
static inline id_manager::id_map::pointer find_unlocked(u32 id)
|
static inline map_data* find_unlocked(u32 id)
|
||||||
{
|
{
|
||||||
return find_id<T, Get>(id);
|
return find_id<T, Get>(id);
|
||||||
}
|
}
|
||||||
|
@ -508,7 +518,7 @@ public:
|
||||||
|
|
||||||
u32 result = 0;
|
u32 result = 0;
|
||||||
|
|
||||||
for (auto& id : g_map[get_type<T>()])
|
for (auto& id : g_fxo->get<id_manager::id_map<T>>().vec)
|
||||||
{
|
{
|
||||||
if (id.second)
|
if (id.second)
|
||||||
{
|
{
|
||||||
|
@ -534,7 +544,7 @@ public:
|
||||||
|
|
||||||
reader_lock lock(id_manager::g_mutex);
|
reader_lock lock(id_manager::g_mutex);
|
||||||
|
|
||||||
for (auto& id : g_map[get_type<T>()])
|
for (auto& id : g_fxo->get<id_manager::id_map<T>>().vec)
|
||||||
{
|
{
|
||||||
if (auto ptr = static_cast<object_type*>(id.second.get()))
|
if (auto ptr = static_cast<object_type*>(id.second.get()))
|
||||||
{
|
{
|
||||||
|
@ -643,9 +653,3 @@ public:
|
||||||
return {nullptr};
|
return {nullptr};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "util/fixed_typemap.hpp"
|
|
||||||
|
|
||||||
extern stx::manual_typemap<void, 0x20'00000, 128> g_fixed_typemap;
|
|
||||||
|
|
||||||
constexpr auto* g_fxo = &g_fixed_typemap;
|
|
||||||
|
|
|
@ -138,7 +138,6 @@ void Emulator::Init(bool add_only)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idm::init();
|
|
||||||
g_fxo->reset();
|
g_fxo->reset();
|
||||||
g_fxo->need<named_thread<progress_dialog_server>>();
|
g_fxo->need<named_thread<progress_dialog_server>>();
|
||||||
|
|
||||||
|
@ -1620,6 +1619,9 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
return game_boot_result::decryption_error;
|
return game_boot_result::decryption_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_state = system_state::ready;
|
||||||
|
vm::init();
|
||||||
|
|
||||||
ppu_exec_object ppu_exec;
|
ppu_exec_object ppu_exec;
|
||||||
ppu_prx_object ppu_prx;
|
ppu_prx_object ppu_prx;
|
||||||
spu_exec_object spu_exec;
|
spu_exec_object spu_exec;
|
||||||
|
@ -1627,11 +1629,8 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
if (ppu_exec.open(elf_file) == elf_error::ok)
|
if (ppu_exec.open(elf_file) == elf_error::ok)
|
||||||
{
|
{
|
||||||
// PS3 executable
|
// PS3 executable
|
||||||
m_state = system_state::ready;
|
|
||||||
GetCallbacks().on_ready();
|
GetCallbacks().on_ready();
|
||||||
|
|
||||||
vm::init();
|
|
||||||
|
|
||||||
if (argv.empty())
|
if (argv.empty())
|
||||||
{
|
{
|
||||||
argv.resize(1);
|
argv.resize(1);
|
||||||
|
@ -1669,6 +1668,8 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
g_fxo->init<ppu_module>();
|
g_fxo->init<ppu_module>();
|
||||||
|
g_fxo->init<id_manager::id_map<lv2_obj>>();
|
||||||
|
g_fxo->init<id_manager::id_map<named_thread<ppu_thread>>>();
|
||||||
|
|
||||||
if (ppu_load_exec(ppu_exec))
|
if (ppu_load_exec(ppu_exec))
|
||||||
{
|
{
|
||||||
|
@ -1688,6 +1689,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
|
|
||||||
if (ppu_exec != elf_error::ok)
|
if (ppu_exec != elf_error::ok)
|
||||||
{
|
{
|
||||||
|
SetForceBoot(true);
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
sys_log.error("Invalid or unsupported PPU executable format: %s", elf_path);
|
sys_log.error("Invalid or unsupported PPU executable format: %s", elf_path);
|
||||||
|
@ -1698,18 +1700,14 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
else if (ppu_prx.open(elf_file) == elf_error::ok)
|
else if (ppu_prx.open(elf_file) == elf_error::ok)
|
||||||
{
|
{
|
||||||
// PPU PRX (experimental)
|
// PPU PRX (experimental)
|
||||||
m_state = system_state::ready;
|
|
||||||
GetCallbacks().on_ready();
|
GetCallbacks().on_ready();
|
||||||
vm::init();
|
|
||||||
g_fxo->init(false);
|
g_fxo->init(false);
|
||||||
ppu_load_prx(ppu_prx, m_path);
|
ppu_load_prx(ppu_prx, m_path);
|
||||||
}
|
}
|
||||||
else if (spu_exec.open(elf_file) == elf_error::ok)
|
else if (spu_exec.open(elf_file) == elf_error::ok)
|
||||||
{
|
{
|
||||||
// SPU executable (experimental)
|
// SPU executable (experimental)
|
||||||
m_state = system_state::ready;
|
|
||||||
GetCallbacks().on_ready();
|
GetCallbacks().on_ready();
|
||||||
vm::init();
|
|
||||||
g_fxo->init(false);
|
g_fxo->init(false);
|
||||||
spu_load_exec(spu_exec);
|
spu_load_exec(spu_exec);
|
||||||
}
|
}
|
||||||
|
@ -1720,6 +1718,9 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
sys_log.warning("** ppu_exec -> %s", ppu_exec.get_error());
|
sys_log.warning("** ppu_exec -> %s", ppu_exec.get_error());
|
||||||
sys_log.warning("** ppu_prx -> %s", ppu_prx.get_error());
|
sys_log.warning("** ppu_prx -> %s", ppu_prx.get_error());
|
||||||
sys_log.warning("** spu_exec -> %s", spu_exec.get_error());
|
sys_log.warning("** spu_exec -> %s", spu_exec.get_error());
|
||||||
|
|
||||||
|
SetForceBoot(true);
|
||||||
|
Stop();
|
||||||
return game_boot_result::invalid_file_or_folder;
|
return game_boot_result::invalid_file_or_folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1973,7 +1974,6 @@ void Emulator::Stop(bool restart)
|
||||||
sys_log.notice("All threads have been stopped.");
|
sys_log.notice("All threads have been stopped.");
|
||||||
|
|
||||||
lv2_obj::cleanup();
|
lv2_obj::cleanup();
|
||||||
idm::clear();
|
|
||||||
|
|
||||||
sys_log.notice("Objects cleared...");
|
sys_log.notice("Objects cleared...");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue