core: Move IDM to FXO

This commit is contained in:
Eladash 2021-03-30 19:37:51 +03:00 committed by Ivan
parent bf1756448e
commit 4a9be0a8d2
3 changed files with 43 additions and 68 deletions

View file

@ -5,22 +5,15 @@
shared_mutex id_manager::g_mutex;
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)
{
// Try to emplace back
const u32 _next = base + step * ::size32(vec);
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();
}
@ -35,7 +28,7 @@ id_manager::id_map::pointer idm::allocate_id(const id_manager::id_key& info, u32
// 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));
g_id = id;
ptr->first = id_manager::id_key(id, info.type());
ptr->first = id_manager::id_key(id, type_id);
return ptr;
}
}
@ -43,25 +36,3 @@ id_manager::id_map::pointer idm::allocate_id(const id_manager::id_key& info, u32
// Out of IDs
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();
}
}

View file

@ -6,6 +6,12 @@
#include <memory>
#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
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.
@ -141,9 +158,6 @@ class idm
// Last allocated ID for constructors
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>
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)
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)
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");
@ -264,7 +280,7 @@ class idm
return nullptr;
}
auto& vec = g_map[get_type<T>()];
auto& vec = g_fxo->get<id_manager::id_map<T>>().vec;
if (index >= vec.size())
{
@ -289,20 +305,19 @@ class idm
// Allocate new ID and assign the object from the provider()
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");
// ID info
const id_manager::id_key info{get_type<T>(), get_type<Type>()};
// ID traits
using traits = id_manager::id_traits<Type>;
// Allocate new id
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
place->second = provider();
@ -317,18 +332,13 @@ class idm
}
public:
// Initialize object manager
static void init();
// Remove all objects
static void clear();
// Remove all objects of a type
template <typename T>
static inline void clear()
{
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)
@ -387,7 +397,7 @@ public:
// Access the ID record without locking (unsafe)
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);
}
@ -508,7 +518,7 @@ public:
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)
{
@ -534,7 +544,7 @@ public:
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()))
{
@ -643,9 +653,3 @@ public:
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;

View file

@ -138,7 +138,6 @@ void Emulator::Init(bool add_only)
}
}
idm::init();
g_fxo->reset();
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;
}
m_state = system_state::ready;
vm::init();
ppu_exec_object ppu_exec;
ppu_prx_object ppu_prx;
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)
{
// PS3 executable
m_state = system_state::ready;
GetCallbacks().on_ready();
vm::init();
if (argv.empty())
{
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<id_manager::id_map<lv2_obj>>();
g_fxo->init<id_manager::id_map<named_thread<ppu_thread>>>();
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)
{
SetForceBoot(true);
Stop();
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)
{
// PPU PRX (experimental)
m_state = system_state::ready;
GetCallbacks().on_ready();
vm::init();
g_fxo->init(false);
ppu_load_prx(ppu_prx, m_path);
}
else if (spu_exec.open(elf_file) == elf_error::ok)
{
// SPU executable (experimental)
m_state = system_state::ready;
GetCallbacks().on_ready();
vm::init();
g_fxo->init(false);
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_prx -> %s", ppu_prx.get_error());
sys_log.warning("** spu_exec -> %s", spu_exec.get_error());
SetForceBoot(true);
Stop();
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.");
lv2_obj::cleanup();
idm::clear();
sys_log.notice("Objects cleared...");