1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 04:02:42 +01:00

IdManager improved

lv2_obj for kernel objects
Simple lookup (vector)
Another idm API refactoring
This commit is contained in:
Nekotekina 2017-01-29 19:50:18 +03:00
parent be8d8ded3f
commit b21fce4d6f
52 changed files with 812 additions and 765 deletions

View File

@ -5,7 +5,7 @@ IndentWidth: 1
AccessModifierOffset: -1 AccessModifierOffset: -1
PointerAlignment: Left PointerAlignment: Left
NamespaceIndentation: All NamespaceIndentation: All
ColumnLimit: 100 ColumnLimit: 200
BreakBeforeBraces: Allman BreakBeforeBraces: Allman
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
BreakBeforeBinaryOperators: false BreakBeforeBinaryOperators: false

View File

@ -278,7 +278,7 @@ void audio_config::on_task()
for (u64 key : keys) for (u64 key : keys)
{ {
if (auto&& queue = lv2_event_queue_t::find(key)) if (auto&& queue = lv2_event_queue::find(key))
{ {
if (queue->events() < queue->size) if (queue->events() < queue->size)
queue->push(lv2_lock, 0, 0, 0, 0); // TODO: check arguments queue->push(lv2_lock, 0, 0, 0, 0); // TODO: check arguments
@ -656,7 +656,7 @@ s32 cellAudioCreateNotifyEventQueue(vm::ptr<u32> id, vm::ptr<u64> key)
const u64 key_value = 0x80004d494f323221ull + k; const u64 key_value = 0x80004d494f323221ull + k;
// Create an event queue "bruteforcing" an available key // Create an event queue "bruteforcing" an available key
if (auto&& queue = lv2_event_queue_t::make(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0, key_value, 32)) if (auto&& queue = lv2_event_queue::make(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0, key_value, 32))
{ {
*id = queue->id; *id = queue->id;
*key = key_value; *key = key_value;

View File

@ -145,7 +145,7 @@ class ElementaryStream
public: public:
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec); ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec);

View File

@ -111,7 +111,7 @@ struct CellJpgDecSubHandle
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
u32 fd; u32 fd;
u64 fileSize; u64 fileSize;

View File

@ -323,7 +323,7 @@ class VpostInstance
public: public:
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
const bool to_rgba; const bool to_rgba;

View File

@ -20,7 +20,7 @@ struct trophy_context_t
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
const u32 id = idm::last_id(); const u32 id = idm::last_id();
@ -33,7 +33,7 @@ struct trophy_handle_t
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
const u32 id = idm::last_id(); const u32 id = idm::last_id();
}; };

View File

@ -11,7 +11,7 @@ struct HeapInfo
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
const std::string name; const std::string name;

View File

@ -13,7 +13,7 @@ s32 sys_lwcond_create(vm::ptr<sys_lwcond_t> lwcond, vm::ptr<sys_lwmutex_t> lwmut
{ {
sysPrxForUser.warning("sys_lwcond_create(lwcond=*0x%x, lwmutex=*0x%x, attr=*0x%x)", lwcond, lwmutex, attr); sysPrxForUser.warning("sys_lwcond_create(lwcond=*0x%x, lwmutex=*0x%x, attr=*0x%x)", lwcond, lwmutex, attr);
lwcond->lwcond_queue = idm::make<lv2_lwcond_t>(reinterpret_cast<u64&>(attr->name)); lwcond->lwcond_queue = idm::make<lv2_obj, lv2_lwcond>(reinterpret_cast<u64&>(attr->name));
lwcond->lwmutex = lwmutex; lwcond->lwmutex = lwmutex;
return CELL_OK; return CELL_OK;

View File

@ -34,7 +34,7 @@ s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attri
lwmutex->lock_var.store({ lwmutex_free, 0 }); lwmutex->lock_var.store({ lwmutex_free, 0 });
lwmutex->attribute = attr->recursive | attr->protocol; lwmutex->attribute = attr->recursive | attr->protocol;
lwmutex->recursive_count = 0; lwmutex->recursive_count = 0;
lwmutex->sleep_queue = idm::make<lv2_lwmutex_t>(protocol, reinterpret_cast<u64&>(attr->name)); lwmutex->sleep_queue = idm::make<lv2_obj, lv2_lwmutex>(protocol, reinterpret_cast<u64&>(attr->name));
return CELL_OK; return CELL_OK;
} }

View File

@ -13,7 +13,7 @@ struct memory_pool_t
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 32767; static const u32 id_count = 1023;
vm::ptr<void> chunk; vm::ptr<void> chunk;
u64 chunk_size; u64 chunk_size;

View File

@ -45,7 +45,7 @@ s32 sys_ppu_thread_create(vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio,
// Dirty hack for sound: confirm the creation of _mxr000 event queue // Dirty hack for sound: confirm the creation of _mxr000 event queue
if (threadname && std::memcmp(threadname.get_ptr(), "_cellsurMixerMain", 18) == 0) if (threadname && std::memcmp(threadname.get_ptr(), "_cellsurMixerMain", 18) == 0)
{ {
while (!idm::select<lv2_event_queue_t>([](u32, lv2_event_queue_t& eq) while (!idm::select<lv2_obj, lv2_event_queue>([](u32, lv2_event_queue& eq)
{ {
return eq.name == "_mxr000\0"_u64; return eq.name == "_mxr000\0"_u64;
})) }))

View File

@ -733,7 +733,7 @@ static void ppu_load_imports(const std::shared_ptr<ppu_linkage_info>& link, u32
} }
} }
std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object& elf) std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf)
{ {
std::vector<std::pair<u32, u32>> segments; std::vector<std::pair<u32, u32>> segments;
std::vector<std::pair<u32, u32>> sections; std::vector<std::pair<u32, u32>> sections;
@ -887,7 +887,7 @@ std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object& elf)
const auto link = fxm::get_always<ppu_linkage_info>(); const auto link = fxm::get_always<ppu_linkage_info>();
// Create new PRX object // Create new PRX object
auto prx = idm::make_ptr<lv2_prx_t>(); auto prx = idm::make_ptr<lv2_obj, lv2_prx>();
if (!elf.progs.empty() && elf.progs[0].p_paddr) if (!elf.progs.empty() && elf.progs[0].p_paddr)
{ {

View File

@ -22,7 +22,7 @@ class ppu_thread : public cpu_thread
public: public:
static const u32 id_base = 0x01000000; // TODO (used to determine thread type) static const u32 id_base = 0x01000000; // TODO (used to determine thread type)
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 65535; static const u32 id_count = 2048;
virtual std::string get_name() const override; virtual std::string get_name() const override;
virtual std::string dump() const override; virtual std::string dump() const override;

View File

@ -867,7 +867,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value)
LOG_TRACE(SPU, "sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag); LOG_TRACE(SPU, "sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag);
const auto eflag = idm::get<lv2_event_flag_t>(data); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(data);
if (!eflag) if (!eflag)
{ {
@ -908,7 +908,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value)
LOG_TRACE(SPU, "sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d))", data, value, flag); LOG_TRACE(SPU, "sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d))", data, value, flag);
const auto eflag = idm::get<lv2_event_flag_t>(data); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(data);
if (!eflag) if (!eflag)
{ {
@ -1179,7 +1179,7 @@ bool SPUThread::stop_and_signal(u32 code)
return ch_in_mbox.set_values(1, CELL_EINVAL), true; return ch_in_mbox.set_values(1, CELL_EINVAL), true;
} }
std::shared_ptr<lv2_event_queue_t> queue; std::shared_ptr<lv2_event_queue> queue;
for (auto& v : this->spuq) for (auto& v : this->spuq)
{ {

View File

@ -5,9 +5,9 @@
#include "Emu/Cell/SPUInterpreter.h" #include "Emu/Cell/SPUInterpreter.h"
#include "MFC.h" #include "MFC.h"
class lv2_event_queue_t; class lv2_event_queue;
struct lv2_spu_group_t; struct lv2_spu_group;
struct lv2_int_tag_t; struct lv2_int_tag;
// SPU Channels // SPU Channels
enum : u32 enum : u32
@ -343,7 +343,7 @@ struct spu_int_ctrl_t
atomic_t<u64> mask; atomic_t<u64> mask;
atomic_t<u64> stat; atomic_t<u64> stat;
std::shared_ptr<struct lv2_int_tag_t> tag; std::shared_ptr<struct lv2_int_tag> tag;
void set(u64 ints); void set(u64 ints);
@ -503,7 +503,7 @@ protected:
public: public:
static const u32 id_base = 0x02000000; // TODO (used to determine thread type) static const u32 id_base = 0x02000000; // TODO (used to determine thread type)
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 65535; static const u32 id_count = 2048;
SPUThread(const std::string& name, u32 index); SPUThread(const std::string& name, u32 index);
@ -544,10 +544,10 @@ public:
std::array<spu_int_ctrl_t, 3> int_ctrl; // SPU Class 0, 1, 2 Interrupt Management std::array<spu_int_ctrl_t, 3> int_ctrl; // SPU Class 0, 1, 2 Interrupt Management
std::weak_ptr<lv2_spu_group_t> tg; // SPU Thread Group std::weak_ptr<lv2_spu_group> tg; // SPU Thread Group
std::array<std::pair<u32, std::weak_ptr<lv2_event_queue_t>>, 32> spuq; // Event Queue Keys for SPU Thread std::array<std::pair<u32, std::weak_ptr<lv2_event_queue>>, 32> spuq; // Event Queue Keys for SPU Thread
std::weak_ptr<lv2_event_queue_t> spup[64]; // SPU Ports std::weak_ptr<lv2_event_queue> spup[64]; // SPU Ports
u32 pc = 0; // u32 pc = 0; //
const u32 index; // SPU index const u32 index; // SPU index

View File

@ -16,7 +16,7 @@ logs::channel sys_cond("sys_cond", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_cond_t::notify(lv2_lock_t, cpu_thread* thread) void lv2_cond::notify(lv2_lock_t, cpu_thread* thread)
{ {
if (mutex->owner) if (mutex->owner)
{ {
@ -36,7 +36,7 @@ s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribu
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_mutex_t>(mutex_id); const auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
if (!mutex) if (!mutex)
{ {
@ -54,7 +54,7 @@ s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribu
fmt::throw_exception("Unexpected cond_count" HERE); fmt::throw_exception("Unexpected cond_count" HERE);
} }
*cond_id = idm::make<lv2_cond_t>(mutex, attr->name_u64); *cond_id = idm::make<lv2_obj, lv2_cond>(mutex, attr->name_u64);
return CELL_OK; return CELL_OK;
} }
@ -65,7 +65,7 @@ s32 sys_cond_destroy(u32 cond_id)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_cond_t>(cond_id); const auto cond = idm::get<lv2_obj, lv2_cond>(cond_id);
if (!cond) if (!cond)
{ {
@ -82,7 +82,7 @@ s32 sys_cond_destroy(u32 cond_id)
fmt::throw_exception("Unexpected cond_count" HERE); fmt::throw_exception("Unexpected cond_count" HERE);
} }
idm::remove<lv2_cond_t>(cond_id); idm::remove<lv2_obj, lv2_cond>(cond_id);
return CELL_OK; return CELL_OK;
} }
@ -93,7 +93,7 @@ s32 sys_cond_signal(u32 cond_id)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_cond_t>(cond_id); const auto cond = idm::get<lv2_obj, lv2_cond>(cond_id);
if (!cond) if (!cond)
{ {
@ -116,7 +116,7 @@ s32 sys_cond_signal_all(u32 cond_id)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_cond_t>(cond_id); const auto cond = idm::get<lv2_obj, lv2_cond>(cond_id);
if (!cond) if (!cond)
{ {
@ -140,7 +140,7 @@ s32 sys_cond_signal_to(u32 cond_id, u32 thread_id)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_cond_t>(cond_id); const auto cond = idm::get<lv2_obj, lv2_cond>(cond_id);
if (!cond) if (!cond)
{ {
@ -173,7 +173,7 @@ s32 sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_cond_t>(cond_id); const auto cond = idm::get<lv2_obj, lv2_cond>(cond_id);
if (!cond) if (!cond)
{ {

View File

@ -2,7 +2,7 @@
#include "sys_sync.h" #include "sys_sync.h"
struct lv2_mutex_t; struct lv2_mutex;
struct sys_cond_attribute_t struct sys_cond_attribute_t
{ {
@ -17,18 +17,16 @@ struct sys_cond_attribute_t
}; };
}; };
struct lv2_cond_t struct lv2_cond final : lv2_obj
{ {
static const u32 id_base = 0x86000000; static const u32 id_base = 0x86000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name; const u64 name;
const std::shared_ptr<lv2_mutex_t> mutex; // associated mutex const std::shared_ptr<lv2_mutex> mutex; // associated mutex
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;
lv2_cond_t(const std::shared_ptr<lv2_mutex_t>& mutex, u64 name) lv2_cond(const std::shared_ptr<lv2_mutex>& mutex, u64 name)
: mutex(mutex) : mutex(mutex)
, name(name) , name(name)
{ {

View File

@ -14,17 +14,17 @@ namespace vm { using namespace ps3; }
logs::channel sys_event("sys_event", logs::level::notice); logs::channel sys_event("sys_event", logs::level::notice);
template<> DECLARE(ipc_manager<lv2_event_queue_t, u64>::g_ipc) {}; template<> DECLARE(ipc_manager<lv2_event_queue, u64>::g_ipc) {};
extern u64 get_system_time(); extern u64 get_system_time();
std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size) std::shared_ptr<lv2_event_queue> lv2_event_queue::make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
{ {
std::shared_ptr<lv2_event_queue_t> result; std::shared_ptr<lv2_event_queue> result;
auto make_expr = [&]() -> const std::shared_ptr<lv2_event_queue_t>& auto make_expr = [&]() -> const std::shared_ptr<lv2_event_queue>&
{ {
result = idm::make_ptr<lv2_event_queue_t>(protocol, type, name, ipc_key, size); result = idm::make_ptr<lv2_obj, lv2_event_queue>(protocol, type, name, ipc_key, size);
return result; return result;
}; };
@ -36,7 +36,7 @@ std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::make(u32 protocol, s32 typ
} }
// IPC queue // IPC queue
if (ipc_manager<lv2_event_queue_t, u64>::add(ipc_key, make_expr)) if (ipc_manager<lv2_event_queue, u64>::add(ipc_key, make_expr))
{ {
return result; return result;
} }
@ -44,7 +44,7 @@ std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::make(u32 protocol, s32 typ
return nullptr; return nullptr;
} }
std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::find(u64 ipc_key) std::shared_ptr<lv2_event_queue> lv2_event_queue::find(u64 ipc_key)
{ {
if (ipc_key == SYS_EVENT_QUEUE_LOCAL) if (ipc_key == SYS_EVENT_QUEUE_LOCAL)
{ {
@ -52,10 +52,10 @@ std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::find(u64 ipc_key)
return{}; return{};
} }
return ipc_manager<lv2_event_queue_t, u64>::get(ipc_key); return ipc_manager<lv2_event_queue, u64>::get(ipc_key);
} }
lv2_event_queue_t::lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size) lv2_event_queue::lv2_event_queue(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
: protocol(protocol) : protocol(protocol)
, type(type) , type(type)
, name(name) , name(name)
@ -65,7 +65,7 @@ lv2_event_queue_t::lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_k
{ {
} }
void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3) void lv2_event_queue::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3)
{ {
verify(HERE), m_sq.empty() || m_events.empty(); verify(HERE), m_sq.empty() || m_events.empty();
@ -105,7 +105,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
return m_sq.pop_front(); return m_sq.pop_front();
} }
lv2_event_queue_t::event_type lv2_event_queue_t::pop(lv2_lock_t) lv2_event_queue::event_type lv2_event_queue::pop(lv2_lock_t)
{ {
verify(HERE), m_events.size(); verify(HERE), m_events.size();
auto result = m_events.front(); auto result = m_events.front();
@ -138,7 +138,7 @@ s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attri
return CELL_EINVAL; return CELL_EINVAL;
} }
const auto queue = lv2_event_queue_t::make(protocol, type, reinterpret_cast<u64&>(attr->name), event_queue_key, size); const auto queue = lv2_event_queue::make(protocol, type, reinterpret_cast<u64&>(attr->name), event_queue_key, size);
if (!queue) if (!queue)
{ {
@ -156,7 +156,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
LV2_LOCK; LV2_LOCK;
const auto queue = idm::get<lv2_event_queue_t>(equeue_id); const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id);
if (!queue) if (!queue)
{ {
@ -174,7 +174,7 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
} }
// cleanup // cleanup
idm::remove<lv2_event_queue_t>(equeue_id); idm::remove<lv2_obj, lv2_event_queue>(equeue_id);
// signal all threads to return CELL_ECANCELED // signal all threads to return CELL_ECANCELED
for (auto& thread : queue->thread_queue(lv2_lock)) for (auto& thread : queue->thread_queue(lv2_lock))
@ -205,7 +205,7 @@ s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array,
LV2_LOCK; LV2_LOCK;
const auto queue = idm::get<lv2_event_queue_t>(equeue_id); const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id);
if (!queue) if (!queue)
{ {
@ -244,7 +244,7 @@ s32 sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_event_t>
LV2_LOCK; LV2_LOCK;
const auto queue = idm::get<lv2_event_queue_t>(equeue_id); const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id);
if (!queue) if (!queue)
{ {
@ -305,7 +305,7 @@ s32 sys_event_queue_drain(u32 equeue_id)
LV2_LOCK; LV2_LOCK;
const auto queue = idm::get<lv2_event_queue_t>(equeue_id); const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id);
if (!queue) if (!queue)
{ {
@ -327,7 +327,7 @@ s32 sys_event_port_create(vm::ptr<u32> eport_id, s32 port_type, u64 name)
return CELL_EINVAL; return CELL_EINVAL;
} }
*eport_id = idm::make<lv2_event_port_t>(port_type, name); *eport_id = idm::make<lv2_obj, lv2_event_port>(port_type, name);
return CELL_OK; return CELL_OK;
} }
@ -338,7 +338,7 @@ s32 sys_event_port_destroy(u32 eport_id)
LV2_LOCK; LV2_LOCK;
const auto port = idm::get<lv2_event_port_t>(eport_id); const auto port = idm::get<lv2_obj, lv2_event_port>(eport_id);
if (!port) if (!port)
{ {
@ -350,7 +350,7 @@ s32 sys_event_port_destroy(u32 eport_id)
return CELL_EISCONN; return CELL_EISCONN;
} }
idm::remove<lv2_event_port_t>(eport_id); idm::remove<lv2_obj, lv2_event_port>(eport_id);
return CELL_OK; return CELL_OK;
} }
@ -361,8 +361,8 @@ s32 sys_event_port_connect_local(u32 eport_id, u32 equeue_id)
LV2_LOCK; LV2_LOCK;
const auto port = idm::get<lv2_event_port_t>(eport_id); const auto port = idm::get<lv2_obj, lv2_event_port>(eport_id);
const auto queue = idm::get<lv2_event_queue_t>(equeue_id); const auto queue = idm::get<lv2_obj, lv2_event_queue>(equeue_id);
if (!port || !queue) if (!port || !queue)
{ {
@ -390,7 +390,7 @@ s32 sys_event_port_disconnect(u32 eport_id)
LV2_LOCK; LV2_LOCK;
const auto port = idm::get<lv2_event_port_t>(eport_id); const auto port = idm::get<lv2_obj, lv2_event_port>(eport_id);
if (!port) if (!port)
{ {
@ -417,7 +417,7 @@ s32 sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
LV2_LOCK; LV2_LOCK;
const auto port = idm::get<lv2_event_port_t>(eport_id); const auto port = idm::get<lv2_obj, lv2_event_port>(eport_id);
if (!port) if (!port)
{ {

View File

@ -65,7 +65,7 @@ struct sys_event_t
be_t<u64> data3; be_t<u64> data3;
}; };
class lv2_event_queue_t final class lv2_event_queue final : public lv2_obj
{ {
// Tuple elements: source, data1, data2, data3 // Tuple elements: source, data1, data2, data3
using event_type = std::tuple<u64, u64, u64, u64>; using event_type = std::tuple<u64, u64, u64, u64>;
@ -76,14 +76,12 @@ class lv2_event_queue_t final
public: public:
static const u32 id_base = 0x8d000000; static const u32 id_base = 0x8d000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
// Try to make an event queue with specified global key // Try to make an event queue with specified global key
static std::shared_ptr<lv2_event_queue_t> make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size); static std::shared_ptr<lv2_event_queue> make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
// Get event queue by its global key // Get event queue by its global key
static std::shared_ptr<lv2_event_queue_t> find(u64 ipc_key); static std::shared_ptr<lv2_event_queue> find(u64 ipc_key);
const u32 protocol; const u32 protocol;
const s32 type; const s32 type;
@ -92,7 +90,7 @@ public:
const s32 size; const s32 size;
const u32 id; const u32 id;
lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size); lv2_event_queue(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
// Send an event // Send an event
void push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3); void push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3);
@ -116,18 +114,16 @@ public:
auto& thread_queue(lv2_lock_t) { return m_sq; } auto& thread_queue(lv2_lock_t) { return m_sq; }
}; };
struct lv2_event_port_t struct lv2_event_port final : lv2_obj
{ {
static const u32 id_base = 0x0e000000; static const u32 id_base = 0x0e000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const s32 type; // port type, must be SYS_EVENT_PORT_LOCAL const s32 type; // port type, must be SYS_EVENT_PORT_LOCAL
const u64 name; // passed as event source (generated from id and process id if not set) const u64 name; // passed as event source (generated from id and process id if not set)
std::weak_ptr<lv2_event_queue_t> queue; // event queue this port is connected to std::weak_ptr<lv2_event_queue> queue; // event queue this port is connected to
lv2_event_port_t(s32 type, u64 name) lv2_event_port(s32 type, u64 name)
: type(type) : type(type)
, name(name) , name(name)
{ {

View File

@ -15,7 +15,7 @@ logs::channel sys_event_flag("sys_event_flag", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_event_flag_t::notify_all(lv2_lock_t) void lv2_event_flag::notify_all(lv2_lock_t)
{ {
auto pred = [this](cpu_thread* thread) -> bool auto pred = [this](cpu_thread* thread) -> bool
{ {
@ -74,7 +74,7 @@ s32 sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> a
return CELL_EINVAL; return CELL_EINVAL;
} }
*id = idm::make<lv2_event_flag_t>(init, protocol, type, attr->name_u64); *id = idm::make<lv2_obj, lv2_event_flag>(init, protocol, type, attr->name_u64);
return CELL_OK; return CELL_OK;
} }
@ -85,7 +85,7 @@ s32 sys_event_flag_destroy(u32 id)
LV2_LOCK; LV2_LOCK;
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {
@ -97,7 +97,7 @@ s32 sys_event_flag_destroy(u32 id)
return CELL_EBUSY; return CELL_EBUSY;
} }
idm::remove<lv2_event_flag_t>(id); idm::remove<lv2_obj, lv2_event_flag>(id);
return CELL_OK; return CELL_OK;
} }
@ -117,13 +117,13 @@ s32 sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm::ptr<u
if (result) *result = 0; // This is very annoying. if (result) *result = 0; // This is very annoying.
if (!lv2_event_flag_t::check_mode(mode)) if (!lv2_event_flag::check_mode(mode))
{ {
sys_event_flag.error("sys_event_flag_wait(): unknown mode (0x%x)", mode); sys_event_flag.error("sys_event_flag_wait(): unknown mode (0x%x)", mode);
return CELL_EINVAL; return CELL_EINVAL;
} }
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {
@ -193,13 +193,13 @@ s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result)
if (result) *result = 0; // This is very annoying. if (result) *result = 0; // This is very annoying.
if (!lv2_event_flag_t::check_mode(mode)) if (!lv2_event_flag::check_mode(mode))
{ {
sys_event_flag.error("sys_event_flag_trywait(): unknown mode (0x%x)", mode); sys_event_flag.error("sys_event_flag_trywait(): unknown mode (0x%x)", mode);
return CELL_EINVAL; return CELL_EINVAL;
} }
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {
@ -224,7 +224,7 @@ s32 sys_event_flag_set(u32 id, u64 bitptn)
LV2_LOCK; LV2_LOCK;
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {
@ -245,7 +245,7 @@ s32 sys_event_flag_clear(u32 id, u64 bitptn)
LV2_LOCK; LV2_LOCK;
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {
@ -268,7 +268,7 @@ s32 sys_event_flag_cancel(u32 id, vm::ptr<u32> num)
*num = 0; *num = 0;
} }
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {
@ -312,7 +312,7 @@ s32 sys_event_flag_get(u32 id, vm::ptr<u64> flags)
return CELL_EFAULT; return CELL_EFAULT;
} }
const auto eflag = idm::get<lv2_event_flag_t>(id); const auto eflag = idm::get<lv2_obj, lv2_event_flag>(id);
if (!eflag) if (!eflag)
{ {

View File

@ -29,11 +29,9 @@ struct sys_event_flag_attribute_t
}; };
}; };
struct lv2_event_flag_t struct lv2_event_flag final : lv2_obj
{ {
static const u32 id_base = 0x98000000; static const u32 id_base = 0x98000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol; const u32 protocol;
const s32 type; const s32 type;
@ -43,7 +41,7 @@ struct lv2_event_flag_t
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;
lv2_event_flag_t(u64 pattern, u32 protocol, s32 type, u64 name) lv2_event_flag(u64 pattern, u32 protocol, s32 type, u64 name)
: pattern(pattern) : pattern(pattern)
, protocol(protocol) , protocol(protocol)
, type(type) , type(type)

View File

@ -96,6 +96,8 @@ struct lv2_fs_mount_point;
struct lv2_fs_object struct lv2_fs_object
{ {
using id_type = lv2_fs_object;
static const u32 id_base = 3; static const u32 id_base = 3;
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 255 - id_base; static const u32 id_count = 255 - id_base;
@ -114,7 +116,7 @@ struct lv2_fs_object
static lv2_fs_mount_point* get_mp(const char* filename); static lv2_fs_mount_point* get_mp(const char* filename);
}; };
struct lv2_file : lv2_fs_object struct lv2_file final : lv2_fs_object
{ {
const fs::file file; const fs::file file;
const s32 mode; const s32 mode;
@ -135,7 +137,7 @@ struct lv2_file : lv2_fs_object
u64 op_write(vm::ps3::cptr<void> buf, u64 size); u64 op_write(vm::ps3::cptr<void> buf, u64 size);
}; };
struct lv2_dir : lv2_fs_object struct lv2_dir final : lv2_fs_object
{ {
const fs::dir dir; const fs::dir dir;

View File

@ -12,7 +12,7 @@ namespace vm { using namespace ps3; }
logs::channel sys_interrupt("sys_interrupt", logs::level::notice); logs::channel sys_interrupt("sys_interrupt", logs::level::notice);
lv2_int_serv_t::lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2) lv2_int_serv::lv2_int_serv(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2)
: thread(thread) : thread(thread)
, arg1(arg1) , arg1(arg1)
, arg2(arg2) , arg2(arg2)
@ -20,7 +20,7 @@ lv2_int_serv_t::lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 ar
{ {
} }
void lv2_int_serv_t::exec() void lv2_int_serv::exec()
{ {
thread->cmd_list thread->cmd_list
({ ({
@ -31,7 +31,7 @@ void lv2_int_serv_t::exec()
thread->notify(); thread->notify();
} }
void lv2_int_serv_t::join(ppu_thread& ppu, lv2_lock_t lv2_lock) void lv2_int_serv::join(ppu_thread& ppu, lv2_lock_t lv2_lock)
{ {
// Enqueue _sys_ppu_thread_exit call // Enqueue _sys_ppu_thread_exit call
thread->cmd_list thread->cmd_list
@ -52,7 +52,7 @@ void lv2_int_serv_t::join(ppu_thread& ppu, lv2_lock_t lv2_lock)
} }
// Cleanup // Cleanup
idm::remove<lv2_int_serv_t>(id); idm::remove<lv2_obj, lv2_int_serv>(id);
} }
s32 sys_interrupt_tag_destroy(u32 intrtag) s32 sys_interrupt_tag_destroy(u32 intrtag)
@ -61,7 +61,7 @@ s32 sys_interrupt_tag_destroy(u32 intrtag)
LV2_LOCK; LV2_LOCK;
const auto tag = idm::get<lv2_int_tag_t>(intrtag); const auto tag = idm::get<lv2_obj, lv2_int_tag>(intrtag);
if (!tag) if (!tag)
{ {
@ -73,7 +73,7 @@ s32 sys_interrupt_tag_destroy(u32 intrtag)
return CELL_EBUSY; return CELL_EBUSY;
} }
idm::remove<lv2_int_tag_t>(intrtag); idm::remove<lv2_obj, lv2_int_tag>(intrtag);
return CELL_OK; return CELL_OK;
} }
@ -85,7 +85,7 @@ s32 _sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u32 intrthread
LV2_LOCK; LV2_LOCK;
// Get interrupt tag // Get interrupt tag
const auto tag = idm::get<lv2_int_tag_t>(intrtag); const auto tag = idm::get<lv2_obj, lv2_int_tag>(intrtag);
if (!tag) if (!tag)
{ {
@ -113,7 +113,7 @@ s32 _sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u32 intrthread
return CELL_ESTAT; return CELL_ESTAT;
} }
tag->handler = idm::make_ptr<lv2_int_serv_t>(it, arg1, arg2); tag->handler = idm::make_ptr<lv2_obj, lv2_int_serv>(it, arg1, arg2);
it->run(); it->run();
@ -128,7 +128,7 @@ s32 _sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih, vm::ptr<u64> r13
LV2_LOCK; LV2_LOCK;
const auto handler = idm::get<lv2_int_serv_t>(ih); const auto handler = idm::get<lv2_obj, lv2_int_serv>(ih);
if (!handler) if (!handler)
{ {
@ -160,7 +160,7 @@ void sys_interrupt_thread_eoi(ppu_thread& ppu) // Low-level PPU function example
} }
} }
lv2_int_tag_t::lv2_int_tag_t() lv2_int_tag::lv2_int_tag()
: id(idm::last_id()) : id(idm::last_id())
{ {
} }

View File

@ -4,24 +4,20 @@
class ppu_thread; class ppu_thread;
struct lv2_int_tag_t struct lv2_int_tag final : lv2_obj
{ {
static const u32 id_base = 0x1000a; static const u32 id_base = 0x0a000000;
static const u32 id_step = 0x10000;
static const u32 id_count = 8192;
const u32 id; const u32 id;
std::shared_ptr<struct lv2_int_serv_t> handler; std::shared_ptr<struct lv2_int_serv> handler;
lv2_int_tag_t(); lv2_int_tag();
}; };
struct lv2_int_serv_t struct lv2_int_serv final : lv2_obj
{ {
static const u32 id_base = 0x0b000000; static const u32 id_base = 0x0b000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const std::shared_ptr<ppu_thread> thread; const std::shared_ptr<ppu_thread> thread;
@ -30,7 +26,7 @@ struct lv2_int_serv_t
const u64 arg1; const u64 arg1;
const u64 arg2; const u64 arg2;
lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2); lv2_int_serv(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2);
void exec(); void exec();
void join(ppu_thread& ppu, lv2_lock_t); void join(ppu_thread& ppu, lv2_lock_t);

View File

@ -14,7 +14,7 @@ logs::channel sys_lwcond("sys_lwcond", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_lwcond_t::notify(lv2_lock_t, cpu_thread* thread, const std::shared_ptr<lv2_lwmutex_t>& mutex, bool mode2) void lv2_lwcond::notify(lv2_lock_t, cpu_thread* thread, const std::shared_ptr<lv2_lwmutex>& mutex, bool mode2)
{ {
auto& ppu = static_cast<ppu_thread&>(*thread); auto& ppu = static_cast<ppu_thread&>(*thread);
@ -37,7 +37,7 @@ s32 _sys_lwcond_create(vm::ptr<u32> lwcond_id, u32 lwmutex_id, vm::ptr<sys_lwcon
{ {
sys_lwcond.warning("_sys_lwcond_create(lwcond_id=*0x%x, lwmutex_id=0x%x, control=*0x%x, name=0x%llx, arg5=0x%x)", lwcond_id, lwmutex_id, control, name, arg5); sys_lwcond.warning("_sys_lwcond_create(lwcond_id=*0x%x, lwmutex_id=0x%x, control=*0x%x, name=0x%llx, arg5=0x%x)", lwcond_id, lwmutex_id, control, name, arg5);
*lwcond_id = idm::make<lv2_lwcond_t>(name); *lwcond_id = idm::make<lv2_obj, lv2_lwcond>(name);
return CELL_OK; return CELL_OK;
} }
@ -48,7 +48,7 @@ s32 _sys_lwcond_destroy(u32 lwcond_id)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_lwcond_t>(lwcond_id); const auto cond = idm::get<lv2_obj, lv2_lwcond>(lwcond_id);
if (!cond) if (!cond)
{ {
@ -60,7 +60,7 @@ s32 _sys_lwcond_destroy(u32 lwcond_id)
return CELL_EBUSY; return CELL_EBUSY;
} }
idm::remove<lv2_lwcond_t>(lwcond_id); idm::remove<lv2_obj, lv2_lwcond>(lwcond_id);
return CELL_OK; return CELL_OK;
} }
@ -71,8 +71,8 @@ s32 _sys_lwcond_signal(u32 lwcond_id, u32 lwmutex_id, u32 ppu_thread_id, u32 mod
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_lwcond_t>(lwcond_id); const auto cond = idm::get<lv2_obj, lv2_lwcond>(lwcond_id);
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!cond || (lwmutex_id && !mutex)) if (!cond || (lwmutex_id && !mutex))
{ {
@ -124,8 +124,8 @@ s32 _sys_lwcond_signal_all(u32 lwcond_id, u32 lwmutex_id, u32 mode)
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_lwcond_t>(lwcond_id); const auto cond = idm::get<lv2_obj, lv2_lwcond>(lwcond_id);
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!cond || (lwmutex_id && !mutex)) if (!cond || (lwmutex_id && !mutex))
{ {
@ -162,8 +162,8 @@ s32 _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u64 t
LV2_LOCK; LV2_LOCK;
const auto cond = idm::get<lv2_lwcond_t>(lwcond_id); const auto cond = idm::get<lv2_obj, lv2_lwcond>(lwcond_id);
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!cond || !mutex) if (!cond || !mutex)
{ {

View File

@ -17,22 +17,20 @@ struct sys_lwcond_t
be_t<u32> lwcond_queue; // lwcond pseudo-id be_t<u32> lwcond_queue; // lwcond pseudo-id
}; };
struct lv2_lwcond_t struct lv2_lwcond final : lv2_obj
{ {
static const u32 id_base = 0x97000000; static const u32 id_base = 0x97000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name; const u64 name;
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;
lv2_lwcond_t(u64 name) lv2_lwcond(u64 name)
: name(name) : name(name)
{ {
} }
void notify(lv2_lock_t, cpu_thread* thread, const std::shared_ptr<lv2_lwmutex_t>& mutex, bool mode2); void notify(lv2_lock_t, cpu_thread* thread, const std::shared_ptr<lv2_lwmutex>& mutex, bool mode2);
}; };
// Aux // Aux

View File

@ -13,7 +13,7 @@ logs::channel sys_lwmutex("sys_lwmutex", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_lwmutex_t::unlock(lv2_lock_t) void lv2_lwmutex::unlock(lv2_lock_t)
{ {
if (signaled) if (signaled)
{ {
@ -48,7 +48,7 @@ s32 _sys_lwmutex_create(vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmut
fmt::throw_exception("Unknown arguments (arg4=0x%x, arg6=0x%x)" HERE, arg4, arg6); fmt::throw_exception("Unknown arguments (arg4=0x%x, arg6=0x%x)" HERE, arg4, arg6);
} }
*lwmutex_id = idm::make<lv2_lwmutex_t>(protocol, name); *lwmutex_id = idm::make<lv2_obj, lv2_lwmutex>(protocol, name);
return CELL_OK; return CELL_OK;
} }
@ -59,7 +59,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!mutex) if (!mutex)
{ {
@ -71,7 +71,7 @@ s32 _sys_lwmutex_destroy(u32 lwmutex_id)
return CELL_EBUSY; return CELL_EBUSY;
} }
idm::remove<lv2_lwmutex_t>(lwmutex_id); idm::remove<lv2_obj, lv2_lwmutex>(lwmutex_id);
return CELL_OK; return CELL_OK;
} }
@ -84,7 +84,7 @@ s32 _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!mutex) if (!mutex)
{ {
@ -131,7 +131,7 @@ s32 _sys_lwmutex_trylock(u32 lwmutex_id)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!mutex) if (!mutex)
{ {
@ -154,7 +154,7 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_lwmutex_t>(lwmutex_id); const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id);
if (!mutex) if (!mutex)
{ {

View File

@ -44,11 +44,9 @@ struct sys_lwmutex_t
be_t<u32> pad; be_t<u32> pad;
}; };
struct lv2_lwmutex_t struct lv2_lwmutex final : lv2_obj
{ {
static const u32 id_base = 0x95000000; static const u32 id_base = 0x95000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol; const u32 protocol;
const u64 name; const u64 name;
@ -58,7 +56,7 @@ struct lv2_lwmutex_t
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;
lv2_lwmutex_t(u32 protocol, u64 name) lv2_lwmutex(u32 protocol, u64 name)
: protocol(protocol) : protocol(protocol)
, name(name) , name(name)
{ {

View File

@ -103,7 +103,7 @@ error_code sys_mmapper_allocate_shared_memory(u64 unk, u32 size, u64 flags, vm::
} }
// Generate a new mem ID // Generate a new mem ID
*mem_id = idm::make<lv2_memory>(size, flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 : 0x10000, flags, dct); *mem_id = idm::make<lv2_obj, lv2_memory>(size, flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 : 0x10000, flags, dct);
return CELL_OK; return CELL_OK;
} }
@ -163,7 +163,7 @@ error_code sys_mmapper_allocate_shared_memory_from_container(u64 unk, u32 size,
} }
// Generate a new mem ID // Generate a new mem ID
*mem_id = idm::make<lv2_memory>(size, flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 : 0x10000, flags, ct.ptr); *mem_id = idm::make<lv2_obj, lv2_memory>(size, flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 : 0x10000, flags, ct.ptr);
return CELL_OK; return CELL_OK;
} }
@ -200,7 +200,7 @@ error_code sys_mmapper_free_shared_memory(u32 mem_id)
sys_mmapper.warning("sys_mmapper_free_shared_memory(mem_id=0x%x)", mem_id); sys_mmapper.warning("sys_mmapper_free_shared_memory(mem_id=0x%x)", mem_id);
// Conditionally remove memory ID // Conditionally remove memory ID
const auto mem = idm::withdraw<lv2_memory>(mem_id, [&](lv2_memory& mem) -> CellError const auto mem = idm::withdraw<lv2_obj, lv2_memory>(mem_id, [&](lv2_memory& mem) -> CellError
{ {
if (mem.addr.compare_and_swap_test(0, -1)) if (mem.addr.compare_and_swap_test(0, -1))
{ {
@ -237,7 +237,7 @@ error_code sys_mmapper_map_shared_memory(u32 addr, u32 mem_id, u64 flags)
return CELL_EINVAL; return CELL_EINVAL;
} }
const auto mem = idm::get<lv2_memory>(mem_id); const auto mem = idm::get<lv2_obj, lv2_memory>(mem_id);
if (!mem) if (!mem)
{ {
@ -276,7 +276,7 @@ error_code sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, vm:
return CELL_EINVAL; return CELL_EINVAL;
} }
const auto mem = idm::get<lv2_memory>(mem_id); const auto mem = idm::get<lv2_obj, lv2_memory>(mem_id);
if (!mem) if (!mem)
{ {
@ -312,7 +312,7 @@ error_code sys_mmapper_unmap_shared_memory(u32 addr, vm::ptr<u32> mem_id)
return CELL_EINVAL; return CELL_EINVAL;
} }
const auto mem = idm::select<lv2_memory>([&](u32 id, lv2_memory& mem) const auto mem = idm::select<lv2_obj, lv2_memory>([&](u32 id, lv2_memory& mem)
{ {
if (mem.addr == addr) if (mem.addr == addr)
{ {

View File

@ -1,12 +1,11 @@
#pragma once #pragma once
#include "sys_sync.h"
#include "sys_memory.h" #include "sys_memory.h"
struct lv2_memory struct lv2_memory : lv2_obj
{ {
static const u32 id_base = 0x08000000; static const u32 id_base = 0x08000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 size; // Memory size const u32 size; // Memory size
const u32 align; // Alignment required const u32 align; // Alignment required

View File

@ -13,7 +13,7 @@ logs::channel sys_mutex("sys_mutex", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_mutex_t::unlock(lv2_lock_t) void lv2_mutex::unlock(lv2_lock_t)
{ {
owner.reset(); owner.reset();
@ -58,7 +58,7 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
return CELL_EINVAL; return CELL_EINVAL;
} }
*mutex_id = idm::make<lv2_mutex_t>(recursive, protocol, attr->name_u64); *mutex_id = idm::make<lv2_obj, lv2_mutex>(recursive, protocol, attr->name_u64);
return CELL_OK; return CELL_OK;
} }
@ -69,7 +69,7 @@ s32 sys_mutex_destroy(u32 mutex_id)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_mutex_t>(mutex_id); const auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
if (!mutex) if (!mutex)
{ {
@ -86,7 +86,7 @@ s32 sys_mutex_destroy(u32 mutex_id)
return CELL_EPERM; return CELL_EPERM;
} }
idm::remove<lv2_mutex_t>(mutex_id); idm::remove<lv2_obj, lv2_mutex>(mutex_id);
return CELL_OK; return CELL_OK;
} }
@ -99,7 +99,7 @@ s32 sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_mutex_t>(mutex_id); const auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
if (!mutex) if (!mutex)
{ {
@ -171,7 +171,7 @@ s32 sys_mutex_trylock(ppu_thread& ppu, u32 mutex_id)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_mutex_t>(mutex_id); const auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
if (!mutex) if (!mutex)
{ {
@ -213,7 +213,7 @@ s32 sys_mutex_unlock(ppu_thread& ppu, u32 mutex_id)
LV2_LOCK; LV2_LOCK;
const auto mutex = idm::get<lv2_mutex_t>(mutex_id); const auto mutex = idm::get<lv2_obj, lv2_mutex>(mutex_id);
if (!mutex) if (!mutex)
{ {

View File

@ -19,11 +19,9 @@ struct sys_mutex_attribute_t
}; };
}; };
struct lv2_mutex_t struct lv2_mutex final : lv2_obj
{ {
static const u32 id_base = 0x85000000; static const u32 id_base = 0x85000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const bool recursive; const bool recursive;
const u32 protocol; const u32 protocol;
@ -35,7 +33,7 @@ struct lv2_mutex_t
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;
lv2_mutex_t(bool recursive, u32 protocol, u64 name) lv2_mutex(bool recursive, u32 protocol, u64 name)
: recursive(recursive) : recursive(recursive)
, protocol(protocol) , protocol(protocol)
, name(name) , name(name)

View File

@ -69,30 +69,36 @@ s32 sys_process_exit(s32 status)
return CELL_OK; return CELL_OK;
} }
template <typename T, typename Get>
u32 idm_get_count()
{
return idm::select<T, Get>([&](u32, Get&) {});
}
s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump) s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump)
{ {
sys_process.error("sys_process_get_number_of_object(object=0x%x, nump=*0x%x)", object, nump); sys_process.error("sys_process_get_number_of_object(object=0x%x, nump=*0x%x)", object, nump);
switch(object) switch(object)
{ {
case SYS_MEM_OBJECT: *nump = idm::get_count<lv2_memory>(); break; case SYS_MEM_OBJECT: *nump = idm_get_count<lv2_obj, lv2_memory>(); break;
case SYS_MUTEX_OBJECT: *nump = idm::get_count<lv2_mutex_t>(); break; case SYS_MUTEX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_mutex>(); break;
case SYS_COND_OBJECT: *nump = idm::get_count<lv2_cond_t>(); break; case SYS_COND_OBJECT: *nump = idm_get_count<lv2_obj, lv2_cond>(); break;
case SYS_RWLOCK_OBJECT: *nump = idm::get_count<lv2_rwlock_t>(); break; case SYS_RWLOCK_OBJECT: *nump = idm_get_count<lv2_obj, lv2_rwlock>(); break;
case SYS_INTR_TAG_OBJECT: *nump = idm::get_count<lv2_int_tag_t>(); break; case SYS_INTR_TAG_OBJECT: *nump = idm_get_count<lv2_obj, lv2_int_tag>(); break;
case SYS_INTR_SERVICE_HANDLE_OBJECT: *nump = idm::get_count<lv2_int_serv_t>(); break; case SYS_INTR_SERVICE_HANDLE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_int_serv>(); break;
case SYS_EVENT_QUEUE_OBJECT: *nump = idm::get_count<lv2_event_queue_t>(); break; case SYS_EVENT_QUEUE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_queue>(); break;
case SYS_EVENT_PORT_OBJECT: *nump = idm::get_count<lv2_event_port_t>(); break; case SYS_EVENT_PORT_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_port>(); break;
case SYS_TRACE_OBJECT: fmt::throw_exception("SYS_TRACE_OBJECT" HERE); case SYS_TRACE_OBJECT: fmt::throw_exception("SYS_TRACE_OBJECT" HERE);
case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE); case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE);
case SYS_PRX_OBJECT: *nump = idm::get_count<lv2_prx_t>(); break; case SYS_PRX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_prx>(); break;
case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE); case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE);
case SYS_LWMUTEX_OBJECT: *nump = idm::get_count<lv2_lwmutex_t>(); break; case SYS_LWMUTEX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_lwmutex>(); break;
case SYS_TIMER_OBJECT: *nump = idm::get_count<lv2_timer_t>(); break; case SYS_TIMER_OBJECT: *nump = idm_get_count<lv2_obj, lv2_timer>(); break;
case SYS_SEMAPHORE_OBJECT: *nump = idm::get_count<lv2_sema_t>(); break; case SYS_SEMAPHORE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_sema>(); break;
case SYS_FS_FD_OBJECT: *nump = idm::get_count<lv2_fs_object>(); break; case SYS_FS_FD_OBJECT: *nump = idm_get_count<lv2_fs_object, lv2_fs_object>(); break;
case SYS_LWCOND_OBJECT: *nump = idm::get_count<lv2_lwcond_t>(); break; case SYS_LWCOND_OBJECT: *nump = idm_get_count<lv2_obj, lv2_lwcond>(); break;
case SYS_EVENT_FLAG_OBJECT: *nump = idm::get_count<lv2_event_flag_t>(); break; case SYS_EVENT_FLAG_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_flag>(); break;
default: default:
{ {
@ -105,10 +111,10 @@ s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump)
#include <set> #include <set>
template<typename T> template <typename T, typename Get>
void idm_get_set(std::set<u32>& out) void idm_get_set(std::set<u32>& out)
{ {
idm::select<T>([&](u32 id, T&) idm::select<T, Get>([&](u32 id, Get&)
{ {
out.emplace(id); out.emplace(id);
}); });
@ -122,24 +128,24 @@ s32 sys_process_get_id(u32 object, vm::ptr<u32> buffer, u32 size, vm::ptr<u32> s
switch (object) switch (object)
{ {
case SYS_MEM_OBJECT: idm_get_set<lv2_memory>(objects); break; case SYS_MEM_OBJECT: idm_get_set<lv2_obj, lv2_memory>(objects); break;
case SYS_MUTEX_OBJECT: idm_get_set<lv2_mutex_t>(objects); break; case SYS_MUTEX_OBJECT: idm_get_set<lv2_obj, lv2_mutex>(objects); break;
case SYS_COND_OBJECT: idm_get_set<lv2_cond_t>(objects); break; case SYS_COND_OBJECT: idm_get_set<lv2_obj, lv2_cond>(objects); break;
case SYS_RWLOCK_OBJECT: idm_get_set<lv2_rwlock_t>(objects); break; case SYS_RWLOCK_OBJECT: idm_get_set<lv2_obj, lv2_rwlock>(objects); break;
case SYS_INTR_TAG_OBJECT: idm_get_set<lv2_int_tag_t>(objects); break; case SYS_INTR_TAG_OBJECT: idm_get_set<lv2_obj, lv2_int_tag>(objects); break;
case SYS_INTR_SERVICE_HANDLE_OBJECT: idm_get_set<lv2_int_serv_t>(objects); break; case SYS_INTR_SERVICE_HANDLE_OBJECT: idm_get_set<lv2_obj, lv2_int_serv>(objects); break;
case SYS_EVENT_QUEUE_OBJECT: idm_get_set<lv2_event_queue_t>(objects); break; case SYS_EVENT_QUEUE_OBJECT: idm_get_set<lv2_obj, lv2_event_queue>(objects); break;
case SYS_EVENT_PORT_OBJECT: idm_get_set<lv2_event_port_t>(objects); break; case SYS_EVENT_PORT_OBJECT: idm_get_set<lv2_obj, lv2_event_port>(objects); break;
case SYS_TRACE_OBJECT: fmt::throw_exception("SYS_TRACE_OBJECT" HERE); case SYS_TRACE_OBJECT: fmt::throw_exception("SYS_TRACE_OBJECT" HERE);
case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE); case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE);
case SYS_PRX_OBJECT: idm_get_set<lv2_prx_t>(objects); break; case SYS_PRX_OBJECT: idm_get_set<lv2_obj, lv2_prx>(objects); break;
case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE); case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE);
case SYS_LWMUTEX_OBJECT: idm_get_set<lv2_lwmutex_t>(objects); break; case SYS_LWMUTEX_OBJECT: idm_get_set<lv2_obj, lv2_lwmutex>(objects); break;
case SYS_TIMER_OBJECT: idm_get_set<lv2_timer_t>(objects); break; case SYS_TIMER_OBJECT: idm_get_set<lv2_obj, lv2_timer>(objects); break;
case SYS_SEMAPHORE_OBJECT: idm_get_set<lv2_sema_t>(objects); break; case SYS_SEMAPHORE_OBJECT: idm_get_set<lv2_obj, lv2_sema>(objects); break;
case SYS_FS_FD_OBJECT: idm_get_set<lv2_fs_object>(objects); break; case SYS_FS_FD_OBJECT: idm_get_set<lv2_fs_object, lv2_fs_object>(objects); break;
case SYS_LWCOND_OBJECT: idm_get_set<lv2_lwcond_t>(objects); break; case SYS_LWCOND_OBJECT: idm_get_set<lv2_obj, lv2_lwcond>(objects); break;
case SYS_EVENT_FLAG_OBJECT: idm_get_set<lv2_event_flag_t>(objects); break; case SYS_EVENT_FLAG_OBJECT: idm_get_set<lv2_obj, lv2_event_flag>(objects); break;
default: default:
{ {

View File

@ -10,7 +10,7 @@
namespace vm { using namespace ps3; } namespace vm { using namespace ps3; }
extern std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object&); extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&);
logs::channel sys_prx("sys_prx", logs::level::notice); logs::channel sys_prx("sys_prx", logs::level::notice);
@ -83,7 +83,7 @@ s32 sys_prx_start_module(s32 id, u64 flags, vm::ptr<sys_prx_start_module_option_
{ {
sys_prx.warning("sys_prx_start_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt); sys_prx.warning("sys_prx_start_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt);
const auto prx = idm::get<lv2_prx_t>(id); const auto prx = idm::get<lv2_obj, lv2_prx>(id);
if (!prx) if (!prx)
{ {
@ -103,7 +103,7 @@ s32 sys_prx_stop_module(s32 id, u64 flags, vm::ptr<sys_prx_stop_module_option_t>
{ {
sys_prx.warning("sys_prx_stop_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt); sys_prx.warning("sys_prx_stop_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt);
const auto prx = idm::get<lv2_prx_t>(id); const auto prx = idm::get<lv2_obj, lv2_prx>(id);
if (!prx) if (!prx)
{ {
@ -124,7 +124,7 @@ s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr<sys_prx_unload_module_optio
sys_prx.warning("sys_prx_unload_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt); sys_prx.warning("sys_prx_unload_module(id=0x%x, flags=0x%llx, pOpt=*0x%x)", id, flags, pOpt);
// Get the PRX, free the used memory and delete the object and its ID // Get the PRX, free the used memory and delete the object and its ID
const auto prx = idm::get<lv2_prx_t>(id); const auto prx = idm::get<lv2_obj, lv2_prx>(id);
if (!prx) if (!prx)
{ {
@ -134,7 +134,7 @@ s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr<sys_prx_unload_module_optio
//Memory.Free(prx->address); //Memory.Free(prx->address);
//s32 result = prx->exit ? prx->exit() : CELL_OK; //s32 result = prx->exit ? prx->exit() : CELL_OK;
idm::remove<lv2_prx_t>(id); idm::remove<lv2_obj, lv2_prx>(id);
return CELL_OK; return CELL_OK;
} }
@ -232,7 +232,7 @@ s32 sys_prx_stop()
return CELL_OK; return CELL_OK;
} }
lv2_prx_t::lv2_prx_t() lv2_prx::lv2_prx()
: id(idm::last_id()) : id(idm::last_id())
{ {
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Emu/Cell/PPUAnalyser.h" #include "Emu/Cell/PPUAnalyser.h"
#include "sys_sync.h"
// Return codes // Return codes
enum enum
@ -72,11 +73,9 @@ struct sys_prx_get_module_list_t
vm::ps3::bptr<s32> idlist; vm::ps3::bptr<s32> idlist;
}; };
struct lv2_prx_t struct lv2_prx final : lv2_obj
{ {
static const u32 id_base = 0x23000000; static const u32 id_base = 0x23000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 id; const u32 id;
@ -89,7 +88,7 @@ struct lv2_prx_t
vm::ps3::ptr<s32(int argc, vm::ps3::ptr<void> argv)> stop = vm::null; vm::ps3::ptr<s32(int argc, vm::ps3::ptr<void> argv)> stop = vm::null;
vm::ps3::ptr<s32()> exit = vm::null; vm::ps3::ptr<s32()> exit = vm::null;
lv2_prx_t(); lv2_prx();
}; };
// SysCalls // SysCalls

View File

@ -13,7 +13,7 @@ logs::channel sys_rwlock("sys_rwlock", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_rwlock_t::notify_all(lv2_lock_t) void lv2_rwlock::notify_all(lv2_lock_t)
{ {
// pick a new writer if possible; protocol is ignored in current implementation // pick a new writer if possible; protocol is ignored in current implementation
if (!readers && !writer && wsq.size()) if (!readers && !writer && wsq.size())
@ -61,7 +61,7 @@ s32 sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> a
return CELL_EINVAL; return CELL_EINVAL;
} }
*rw_lock_id = idm::make<lv2_rwlock_t>(protocol, attr->name_u64); *rw_lock_id = idm::make<lv2_obj, lv2_rwlock>(protocol, attr->name_u64);
return CELL_OK; return CELL_OK;
} }
@ -72,7 +72,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {
@ -84,7 +84,7 @@ s32 sys_rwlock_destroy(u32 rw_lock_id)
return CELL_EBUSY; return CELL_EBUSY;
} }
idm::remove<lv2_rwlock_t>(rw_lock_id); idm::remove<lv2_obj, lv2_rwlock>(rw_lock_id);
return CELL_OK; return CELL_OK;
} }
@ -97,7 +97,7 @@ s32 sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {
@ -152,7 +152,7 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {
@ -178,7 +178,7 @@ s32 sys_rwlock_runlock(u32 rw_lock_id)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {
@ -206,7 +206,7 @@ s32 sys_rwlock_wlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {
@ -275,7 +275,7 @@ s32 sys_rwlock_trywlock(ppu_thread& ppu, u32 rw_lock_id)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {
@ -303,7 +303,7 @@ s32 sys_rwlock_wunlock(ppu_thread& ppu, u32 rw_lock_id)
LV2_LOCK; LV2_LOCK;
const auto rwlock = idm::get<lv2_rwlock_t>(rw_lock_id); const auto rwlock = idm::get<lv2_obj, lv2_rwlock>(rw_lock_id);
if (!rwlock) if (!rwlock)
{ {

View File

@ -17,11 +17,9 @@ struct sys_rwlock_attribute_t
}; };
}; };
struct lv2_rwlock_t struct lv2_rwlock final : lv2_obj
{ {
static const u32 id_base = 0x88000000; static const u32 id_base = 0x88000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name; const u64 name;
const u32 protocol; const u32 protocol;
@ -32,7 +30,7 @@ struct lv2_rwlock_t
sleep_queue<cpu_thread> rsq; // threads trying to acquire readed lock sleep_queue<cpu_thread> rsq; // threads trying to acquire readed lock
sleep_queue<cpu_thread> wsq; // threads trying to acquire writer lock sleep_queue<cpu_thread> wsq; // threads trying to acquire writer lock
lv2_rwlock_t(u32 protocol, u64 name) lv2_rwlock(u32 protocol, u64 name)
: protocol(protocol) : protocol(protocol)
, name(name) , name(name)
{ {

View File

@ -42,7 +42,7 @@ s32 sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t>
return CELL_EINVAL; return CELL_EINVAL;
} }
*sem_id = idm::make<lv2_sema_t>(protocol, max_val, attr->name_u64, initial_val); *sem_id = idm::make<lv2_obj, lv2_sema>(protocol, max_val, attr->name_u64, initial_val);
return CELL_OK; return CELL_OK;
} }
@ -53,7 +53,7 @@ s32 sys_semaphore_destroy(u32 sem_id)
LV2_LOCK; LV2_LOCK;
const auto sem = idm::get<lv2_sema_t>(sem_id); const auto sem = idm::get<lv2_obj, lv2_sema>(sem_id);
if (!sem) if (!sem)
{ {
@ -65,7 +65,7 @@ s32 sys_semaphore_destroy(u32 sem_id)
return CELL_EBUSY; return CELL_EBUSY;
} }
idm::remove<lv2_sema_t>(sem_id); idm::remove<lv2_obj, lv2_sema>(sem_id);
return CELL_OK; return CELL_OK;
} }
@ -78,7 +78,7 @@ s32 sys_semaphore_wait(ppu_thread& ppu, u32 sem_id, u64 timeout)
LV2_LOCK; LV2_LOCK;
const auto sem = idm::get<lv2_sema_t>(sem_id); const auto sem = idm::get<lv2_obj, lv2_sema>(sem_id);
if (!sem) if (!sem)
{ {
@ -125,7 +125,7 @@ s32 sys_semaphore_trywait(u32 sem_id)
LV2_LOCK; LV2_LOCK;
const auto sem = idm::get<lv2_sema_t>(sem_id); const auto sem = idm::get<lv2_obj, lv2_sema>(sem_id);
if (!sem) if (!sem)
{ {
@ -148,7 +148,7 @@ s32 sys_semaphore_post(u32 sem_id, s32 count)
LV2_LOCK; LV2_LOCK;
const auto sem = idm::get<lv2_sema_t>(sem_id); const auto sem = idm::get<lv2_obj, lv2_sema>(sem_id);
if (!sem) if (!sem)
{ {
@ -197,7 +197,7 @@ s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<s32> count)
return CELL_EFAULT; return CELL_EFAULT;
} }
const auto sem = idm::get<lv2_sema_t>(sem_id); const auto sem = idm::get<lv2_obj, lv2_sema>(sem_id);
if (!sem) if (!sem)
{ {

View File

@ -17,11 +17,9 @@ struct sys_semaphore_attribute_t
}; };
}; };
struct lv2_sema_t struct lv2_sema final : lv2_obj
{ {
static const u32 id_base = 0x96000000; static const u32 id_base = 0x96000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol; const u32 protocol;
const s32 max; const s32 max;
@ -31,7 +29,7 @@ struct lv2_sema_t
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;
lv2_sema_t(u32 protocol, s32 max, u64 name, s32 value) lv2_sema(u32 protocol, s32 max, u64 name, s32 value)
: protocol(protocol) : protocol(protocol)
, max(max) , max(max)
, name(name) , name(name)

View File

@ -99,7 +99,7 @@ u32 spu_thread_initialize(u32 group_id, u32 spu_num, vm::ptr<sys_spu_image_t> im
spu->custom_task = task; spu->custom_task = task;
const auto group = idm::get<lv2_spu_group_t>(group_id); const auto group = idm::get<lv2_spu_group>(group_id);
spu->tg = group; spu->tg = group;
group->threads[spu_num] = spu; group->threads[spu_num] = spu;
@ -135,7 +135,7 @@ s32 sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group_id, u32 spu_num, vm
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(group_id); const auto group = idm::get<lv2_spu_group>(group_id);
if (!group) if (!group)
{ {
@ -225,7 +225,7 @@ s32 sys_spu_thread_group_create(vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<sys_
sys_spu.todo("Unsupported SPU Thread Group type (0x%x)", attr->type); sys_spu.todo("Unsupported SPU Thread Group type (0x%x)", attr->type);
} }
*id = idm::make<lv2_spu_group_t>(std::string(attr->name.get_ptr(), attr->nsize - 1), num, prio, attr->type, attr->ct); *id = idm::make<lv2_spu_group>(std::string(attr->name.get_ptr(), attr->nsize - 1), num, prio, attr->type, attr->ct);
return CELL_OK; return CELL_OK;
} }
@ -236,7 +236,7 @@ s32 sys_spu_thread_group_destroy(u32 id)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -260,7 +260,7 @@ s32 sys_spu_thread_group_destroy(u32 id)
} }
group->state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; // hack group->state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; // hack
idm::remove<lv2_spu_group_t>(id); idm::remove<lv2_spu_group>(id);
return CELL_OK; return CELL_OK;
} }
@ -271,7 +271,7 @@ s32 sys_spu_thread_group_start(u32 id)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -336,7 +336,7 @@ s32 sys_spu_thread_group_suspend(u32 id)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -389,7 +389,7 @@ s32 sys_spu_thread_group_resume(u32 id)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -436,7 +436,7 @@ s32 sys_spu_thread_group_yield(u32 id)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -466,7 +466,7 @@ s32 sys_spu_thread_group_terminate(u32 id, s32 value)
// seems the id can be either SPU Thread Group or SPU Thread // seems the id can be either SPU Thread Group or SPU Thread
const auto thread = idm::get<SPUThread>(id); const auto thread = idm::get<SPUThread>(id);
const auto group = thread ? thread->tg.lock() : idm::get<lv2_spu_group_t>(id); const auto group = thread ? thread->tg.lock() : idm::get<lv2_spu_group>(id);
if (!group && !thread) if (!group && !thread)
{ {
@ -522,7 +522,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -795,8 +795,8 @@ s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
const auto queue = idm::get<lv2_event_queue_t>(eq); const auto queue = idm::get<lv2_obj, lv2_event_queue>(eq);
if (!group || !queue) if (!group || !queue)
{ {
@ -851,7 +851,7 @@ s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -907,7 +907,7 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup)
LV2_LOCK; LV2_LOCK;
const auto thread = idm::get<SPUThread>(id); const auto thread = idm::get<SPUThread>(id);
const auto queue = idm::get<lv2_event_queue_t>(eq); const auto queue = idm::get<lv2_obj, lv2_event_queue>(eq);
if (!thread || !queue) if (!thread || !queue)
{ {
@ -970,7 +970,7 @@ s32 sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num)
LV2_LOCK; LV2_LOCK;
const auto thread = idm::get<SPUThread>(id); const auto thread = idm::get<SPUThread>(id);
const auto queue = idm::get<lv2_event_queue_t>(spuq); const auto queue = idm::get<lv2_obj, lv2_event_queue>(spuq);
if (!thread || !queue) if (!thread || !queue)
{ {
@ -1039,8 +1039,8 @@ s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, vm::
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
const auto queue = idm::get<lv2_event_queue_t>(eq); const auto queue = idm::get<lv2_obj, lv2_event_queue>(eq);
if (!group || !queue) if (!group || !queue)
{ {
@ -1110,7 +1110,7 @@ s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup)
LV2_LOCK; LV2_LOCK;
const auto group = idm::get<lv2_spu_group_t>(id); const auto group = idm::get<lv2_spu_group>(id);
if (!group) if (!group)
{ {
@ -1183,7 +1183,7 @@ s32 sys_raw_spu_destroy(ppu_thread& ppu, u32 id)
intr.tag->handler->join(ppu, lv2_lock); intr.tag->handler->join(ppu, lv2_lock);
} }
idm::remove<lv2_int_tag_t>(intr.tag->id); idm::remove<lv2_obj, lv2_int_tag>(intr.tag->id);
} }
} }
@ -1217,7 +1217,7 @@ s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr
return CELL_EAGAIN; return CELL_EAGAIN;
} }
int_ctrl.tag = idm::make_ptr<lv2_int_tag_t>(); int_ctrl.tag = idm::make_ptr<lv2_obj, lv2_int_tag>();
*intrtag = int_ctrl.tag->id; *intrtag = int_ctrl.tag->id;

View File

@ -137,11 +137,11 @@ enum : u32
class SPUThread; class SPUThread;
struct lv2_spu_group_t struct lv2_spu_group
{ {
static const u32 id_base = 1; // Wrong? static const u32 id_base = 1; // Wrong?
static const u32 id_step = 1; static const u32 id_step = 1;
static const u32 id_count = 8192; static const u32 id_count = 255;
const std::string name; const std::string name;
const u32 num; // SPU Number const u32 num; // SPU Number
@ -159,11 +159,11 @@ struct lv2_spu_group_t
atomic_t<u32> join_state; // flags used to detect exit cause atomic_t<u32> join_state; // flags used to detect exit cause
cond_variable cv; // used to signal waiting PPU thread cond_variable cv; // used to signal waiting PPU thread
std::weak_ptr<lv2_event_queue_t> ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events std::weak_ptr<lv2_event_queue> ep_run; // port for SYS_SPU_THREAD_GROUP_EVENT_RUN events
std::weak_ptr<lv2_event_queue_t> ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION std::weak_ptr<lv2_event_queue> ep_exception; // TODO: SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION
std::weak_ptr<lv2_event_queue_t> ep_sysmodule; // TODO: SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE std::weak_ptr<lv2_event_queue> ep_sysmodule; // TODO: SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE
lv2_spu_group_t(std::string name, u32 num, s32 prio, s32 type, u32 ct) lv2_spu_group(std::string name, u32 num, s32 prio, s32 type, u32 ct)
: name(name) : name(name)
, num(num) , num(num)
, prio(prio) , prio(prio)

View File

@ -45,6 +45,15 @@ enum
SYS_SYNC_NOT_ADAPTIVE = 0x2000, SYS_SYNC_NOT_ADAPTIVE = 0x2000,
}; };
// Base class for some kernel objects (shared set of 8192 objects).
struct lv2_obj
{
using id_type = lv2_obj;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
};
// Temporary implementation for LV2_UNLOCK (TODO: remove it) // Temporary implementation for LV2_UNLOCK (TODO: remove it)
struct lv2_lock_guard struct lv2_lock_guard
{ {

View File

@ -14,7 +14,7 @@ logs::channel sys_timer("sys_timer", logs::level::notice);
extern u64 get_system_time(); extern u64 get_system_time();
void lv2_timer_t::on_task() void lv2_timer::on_task()
{ {
//thread_lock lock(*this); //thread_lock lock(*this);
LV2_LOCK; LV2_LOCK;
@ -57,12 +57,12 @@ void lv2_timer_t::on_task()
} }
} }
std::string lv2_timer_t::get_name() const std::string lv2_timer::get_name() const
{ {
return fmt::format("Timer Thread[0x%x]", id); return fmt::format("Timer Thread[0x%x]", id);
} }
void lv2_timer_t::on_stop() void lv2_timer::on_stop()
{ {
// Signal thread using invalid state and join // Signal thread using invalid state and join
state = -1; state = -1;
@ -74,7 +74,7 @@ s32 sys_timer_create(vm::ptr<u32> timer_id)
{ {
sys_timer.warning("sys_timer_create(timer_id=*0x%x)", timer_id); sys_timer.warning("sys_timer_create(timer_id=*0x%x)", timer_id);
*timer_id = idm::make<lv2_timer_t>(); *timer_id = idm::make<lv2_obj, lv2_timer>();
return CELL_OK; return CELL_OK;
} }
@ -85,7 +85,7 @@ s32 sys_timer_destroy(u32 timer_id)
LV2_LOCK; LV2_LOCK;
const auto timer = idm::get<lv2_timer_t>(timer_id); const auto timer = idm::get<lv2_obj, lv2_timer>(timer_id);
if (!timer) if (!timer)
{ {
@ -97,7 +97,7 @@ s32 sys_timer_destroy(u32 timer_id)
return CELL_EISCONN; return CELL_EISCONN;
} }
idm::remove<lv2_timer_t>(timer_id); idm::remove<lv2_obj, lv2_timer>(timer_id);
return CELL_OK; return CELL_OK;
} }
@ -108,7 +108,7 @@ s32 sys_timer_get_information(u32 timer_id, vm::ptr<sys_timer_information_t> inf
LV2_LOCK; LV2_LOCK;
const auto timer = idm::get<lv2_timer_t>(timer_id); const auto timer = idm::get<lv2_obj, lv2_timer>(timer_id);
if (!timer) if (!timer)
{ {
@ -131,7 +131,7 @@ s32 _sys_timer_start(u32 timer_id, u64 base_time, u64 period)
LV2_LOCK; LV2_LOCK;
const auto timer = idm::get<lv2_timer_t>(timer_id); const auto timer = idm::get<lv2_obj, lv2_timer>(timer_id);
if (!timer) if (!timer)
{ {
@ -182,7 +182,7 @@ s32 sys_timer_stop(u32 timer_id)
LV2_LOCK; LV2_LOCK;
const auto timer = idm::get<lv2_timer_t>(timer_id); const auto timer = idm::get<lv2_obj, lv2_timer>(timer_id);
if (!timer) if (!timer)
{ {
@ -200,8 +200,8 @@ s32 sys_timer_connect_event_queue(u32 timer_id, u32 queue_id, u64 name, u64 data
LV2_LOCK; LV2_LOCK;
const auto timer = idm::get<lv2_timer_t>(timer_id); const auto timer = idm::get<lv2_obj, lv2_timer>(timer_id);
const auto queue = idm::get<lv2_event_queue_t>(queue_id); const auto queue = idm::get<lv2_obj, lv2_event_queue>(queue_id);
if (!timer || !queue) if (!timer || !queue)
{ {
@ -227,7 +227,7 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id)
LV2_LOCK; LV2_LOCK;
const auto timer = idm::get<lv2_timer_t>(timer_id); const auto timer = idm::get<lv2_obj, lv2_timer>(timer_id);
if (!timer) if (!timer)
{ {

View File

@ -17,14 +17,12 @@ struct sys_timer_information_t
be_t<u32> pad; be_t<u32> pad;
}; };
class lv2_timer_t final : public named_thread class lv2_timer final : public lv2_obj, public named_thread
{ {
void on_task() override; void on_task() override;
public: public:
static const u32 id_base = 0x11000000; static const u32 id_base = 0x11000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
std::string get_name() const override; std::string get_name() const override;
@ -34,7 +32,7 @@ public:
atomic_t<u32> state{ SYS_TIMER_STATE_RUN }; // Timer state atomic_t<u32> state{ SYS_TIMER_STATE_RUN }; // Timer state
std::weak_ptr<lv2_event_queue_t> port; // Event queue std::weak_ptr<lv2_event_queue> port; // Event queue
u64 source; // Event source u64 source; // Event source
u64 data1; // Event arg 1 u64 data1; // Event arg 1
u64 data2; // Event arg 2 u64 data2; // Event arg 2

View File

@ -7,136 +7,86 @@ thread_local DECLARE(idm::g_id);
DECLARE(idm::g_map); DECLARE(idm::g_map);
DECLARE(fxm::g_vec); DECLARE(fxm::g_vec);
std::vector<id_manager::typeinfo>& id_manager::typeinfo::access() id_manager::id_map::pointer idm::allocate_id(const id_manager::id_key& info, u32 base, u32 step, u32 count)
{ {
static std::vector<typeinfo> list; // Base type id is stored in value
auto& vec = g_map[info.value()];
return list;
}
u32 id_manager::typeinfo::add_type() // Preallocate memory
{ vec.reserve(count);
auto& list = access();
list.emplace_back(); if (vec.size() < count)
return ::size32(list) - 1;
}
id_manager::id_map::pointer idm::allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count)
{
auto& map = g_map[types.first];
// Assume next ID
u32 next = base;
if (std::size_t _count = map.size())
{ {
if (_count >= count) // Try to emplace back
{ const u32 _next = base + step * ::size32(vec);
return nullptr;
}
const u32 _next = next + step * count; if (_next >= base && _next < base + step * count)
if (_next > base && _next < base + step * count)
{ {
next = _next; g_id = _next;
vec.emplace_back(id_manager::id_key(_next, info.type(), info.on_stop()), nullptr);
return &vec.back();
} }
} }
// Check all IDs starting from "next id" (TODO) // Check all IDs starting from "next id" (TODO)
for (u32 i = 0; i < count; i++, next += step) for (u32 i = 0, next = base; i < count; i++, next += step)
{ {
// Get correct ID value const auto ptr = &vec[i];
if (next >= base + step * count)
{
next = base;
}
// Try to allocate ID storage // Look for free ID
const auto result = map.emplace(id_manager::id_key(next, types.second), nullptr); if (!ptr->second)
if (result.second)
{ {
// Acknowledge the ID
g_id = next; g_id = next;
ptr->first = id_manager::id_key(next, info.type(), info.on_stop());
return std::addressof(*result.first); return ptr;
} }
} }
// Nothing found // Out of IDs
return nullptr; return nullptr;
} }
id_manager::id_map::const_pointer idm::find_id(u32 type, u32 true_type, u32 id)
{
const auto& map = g_map[type];
const auto found = map.find(id);
if (found != map.end() && (type == true_type || found->first.type() == true_type))
{
return std::addressof(*found);
}
return nullptr;
}
std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 id)
{
auto& map = g_map[type];
const auto found = map.find(id);
std::shared_ptr<void> result;
if (found != map.end() && (type == true_type || found->first.type() == true_type))
{
result = std::move(found->second);
map.erase(found);
}
return result;
}
void idm::init() void idm::init()
{ {
g_map.resize(id_manager::typeinfo::get().size()); // Allocate
g_map.resize(id_manager::typeinfo::get_count());
} }
void idm::clear() void idm::clear()
{ {
// Call recorded finalization functions for all IDs // Call recorded finalization functions for all IDs
for (std::size_t i = 0; i < g_map.size(); i++) for (auto& map : g_map)
{ {
const auto on_stop = id_manager::typeinfo::get()[i].on_stop; for (auto& pair : map)
for (auto& id : g_map[i])
{ {
on_stop(id.second.get()); if (auto ptr = pair.second.get())
{
pair.first.on_stop()(ptr);
pair.second.reset();
pair.first = {};
}
} }
g_map[i].clear(); map.clear();
} }
} }
void fxm::init() void fxm::init()
{ {
g_vec.resize(id_manager::typeinfo::get().size(), {}); // Allocate
g_vec.resize(id_manager::typeinfo::get_count());
} }
void fxm::clear() void fxm::clear()
{ {
// Call recorded finalization functions for all IDs // Call recorded finalization functions for all IDs
for (std::size_t i = 0; i < g_vec.size(); i++) for (auto& pair : g_vec)
{ {
if (g_vec[i]) if (auto ptr = pair.second.get())
{ {
id_manager::typeinfo::get()[i].on_stop(g_vec[i].get()); pair.first(ptr);
pair.second.reset();
pair.first = nullptr;
} }
g_vec[i].reset();
} }
} }

View File

@ -5,39 +5,38 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <unordered_map>
// idm/fxm: helper namespace // Helper namespace
namespace id_manager namespace id_manager
{ {
// Common global mutex // Common global mutex
extern shared_mutex g_mutex; extern shared_mutex g_mutex;
// Optional ID traits // ID traits
template<typename T, typename = void> template <typename T, typename = void>
struct id_traits struct id_traits
{ {
static_assert(sizeof(T) == 0, "ID object must specify: id_base, id_step, id_count"); static_assert(sizeof(T) == 0, "ID object must specify: id_base, id_step, id_count");
static const u32 base = 1; // First ID (N = 0) static const u32 base = 1; // First ID (N = 0)
static const u32 step = 1; // Any ID: N * id_step + id_base static const u32 step = 1; // Any ID: N * id_step + id_base
static const u32 count = 65535; // Limit: N < id_count static const u32 count = 65535; // Limit: N < id_count
static const u32 invalid = 0; static const u32 invalid = 0;
}; };
template<typename T> template <typename T>
struct id_traits<T, void_t<decltype(&T::id_base), decltype(&T::id_step), decltype(&T::id_count)>> struct id_traits<T, void_t<decltype(&T::id_base), decltype(&T::id_step), decltype(&T::id_count)>>
{ {
static const u32 base = T::id_base; static const u32 base = T::id_base;
static const u32 step = T::id_step; static const u32 step = T::id_step;
static const u32 count = T::id_count; static const u32 count = T::id_count;
static const u32 invalid = base > 0 ? 0 : -1; static const u32 invalid = base > 0 ? 0 : -1;
static_assert(u64{step} * count + base < UINT32_MAX, "ID traits: invalid object range"); static_assert(u64{step} * count + base < UINT32_MAX, "ID traits: invalid object range");
}; };
// Optional object initialization function (called after ID registration) // Optional object initialization function (called after ID registration)
template<typename T, typename = void> template <typename T, typename = void>
struct on_init struct on_init
{ {
static inline void func(T*, const std::shared_ptr<void>&) static inline void func(T*, const std::shared_ptr<void>&)
@ -47,17 +46,17 @@ namespace id_manager
} }
}; };
template<typename T> template <typename T>
struct on_init<T, decltype(std::declval<T>().on_init(std::declval<const std::shared_ptr<void>&>()))> struct on_init<T, decltype(std::declval<T>().on_init(std::declval<const std::shared_ptr<void>&>()))>
{ {
static inline void func(T* ptr, const std::shared_ptr<void>&_ptr) static inline void func(T* ptr, const std::shared_ptr<void>& _ptr)
{ {
if (ptr) ptr->on_init(_ptr); if (ptr) ptr->on_init(_ptr);
} }
}; };
// Optional object finalization function (called after ID removal) // Optional object finalization function (called after ID removal)
template<typename T, typename = void> template <typename T, typename = void>
struct on_stop struct on_stop
{ {
static inline void func(T*) static inline void func(T*)
@ -67,7 +66,7 @@ namespace id_manager
} }
}; };
template<typename T> template <typename T>
struct on_stop<T, decltype(std::declval<T>().on_stop())> struct on_stop<T, decltype(std::declval<T>().on_stop())>
{ {
static inline void func(T* ptr) static inline void func(T* ptr)
@ -76,64 +75,82 @@ namespace id_manager
} }
}; };
// Correct usage testing
template <typename T, typename T2, typename = void>
struct id_verify : std::integral_constant<bool, std::is_base_of<T, T2>::value>
{
// If common case, T2 shall be derived from or equal to T
};
template <typename T, typename T2>
struct id_verify<T, T2, void_t<typename T2::id_type>> : std::integral_constant<bool, std::is_same<T, typename T2::id_type>::value>
{
// If T2 contains id_type type, T must be equal to it
};
class typeinfo class typeinfo
{ {
// Global variable for each registered type // Global variable for each registered type
template<typename T> template <typename T>
struct registered struct registered
{ {
static const u32 index; static const u32 index;
}; };
// Access global type list // Increment type counter
static std::vector<typeinfo>& access(); static u32 add_type(u32 i)
{
static atomic_t<u32> g_next{0};
// Add to the global list return g_next.fetch_add(i);
static u32 add_type(); }
public: public:
void(*on_stop)(void*) = nullptr;
// Get type index // Get type index
template<typename T> template <typename T>
static inline u32 get_index() static inline u32 get_index()
{ {
return registered<T>::index; return registered<T>::index;
} }
// Register functions // Get type count
template<typename T> static inline u32 get_count()
static inline void update()
{ {
access()[get_index<T>()].on_stop = [](void* ptr) { return id_manager::on_stop<T>::func(static_cast<T*>(ptr)); }; return add_type(0);
} }
// Read all registered types // Get type finalizer
static inline const auto& get() template <typename T>
static inline auto get_stop()
{ {
return access(); return [](void* ptr) -> void
{
return id_manager::on_stop<T>::func(static_cast<T*>(ptr));
};
} }
}; };
template<typename T> template <typename T>
const u32 typeinfo::registered<T>::index = typeinfo::add_type(); const u32 typeinfo::registered<T>::index = typeinfo::add_type(1);
// ID value with additional type stored // ID value with additional type stored
class id_key class id_key
{ {
u32 m_value; // ID value u32 m_value; // ID value
u32 m_type; // True object type u32 m_type; // True object type
void (*m_stop)(void*); // Finalizer
public: public:
id_key() = default; id_key() = default;
id_key(u32 value, u32 type = 0) id_key(u32 value, u32 type, void (*stop)(void*))
: m_value(value) : m_value(value)
, m_type(type) , m_type(type)
, m_stop(stop)
{ {
} }
u32 id() const u32 value() const
{ {
return m_value; return m_value;
} }
@ -143,21 +160,18 @@ namespace id_manager
return m_type; return m_type;
} }
auto on_stop() const
{
return m_stop;
}
operator u32() const operator u32() const
{ {
return m_value; return m_value;
} }
}; };
struct id_hash using id_map = std::vector<std::pair<id_key, std::shared_ptr<void>>>;
{
std::size_t operator()(const id_key& id) const
{
return id ^ (id >> 8);
}
};
using id_map = std::unordered_map<id_key, std::shared_ptr<void>, id_hash>;
} }
// 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.
@ -169,46 +183,52 @@ class idm
// Type Index -> ID -> Object. Use global since only one process is supported atm. // Type Index -> ID -> Object. Use global since only one process is supported atm.
static std::vector<id_manager::id_map> g_map; 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()
{ {
return id_manager::typeinfo::get_index<T>(); return id_manager::typeinfo::get_index<T>();
} }
template <typename T>
static constexpr u32 get_index(u32 id)
{
return (id - id_manager::id_traits<T>::base) / id_manager::id_traits<T>::step;
}
// Helper // Helper
template<typename F> template <typename F>
struct function_traits; struct function_traits;
template<typename F, typename R, typename A1, typename A2> template <typename F, typename R, typename A1, typename A2>
struct function_traits<R(F::*)(A1, A2&) const> struct function_traits<R (F::*)(A1, A2&) const>
{ {
using object_type = A2; using object_type = A2;
using result_type = R; using result_type = R;
}; };
template<typename F, typename R, typename A1, typename A2> template <typename F, typename R, typename A1, typename A2>
struct function_traits<R(F::*)(A1, A2&)> struct function_traits<R (F::*)(A1, A2&)>
{ {
using object_type = A2; using object_type = A2;
using result_type = R; using result_type = R;
}; };
template<typename F, typename A1, typename A2> template <typename F, typename A1, typename A2>
struct function_traits<void(F::*)(A1, A2&) const> struct function_traits<void (F::*)(A1, A2&) const>
{ {
using object_type = A2; using object_type = A2;
using void_type = void; using void_type = void;
}; };
template<typename F, typename A1, typename A2> template <typename F, typename A1, typename A2>
struct function_traits<void(F::*)(A1, A2&)> struct function_traits<void (F::*)(A1, A2&)>
{ {
using object_type = A2; using object_type = A2;
using void_type = void; using void_type = void;
}; };
// Helper // Helper
template<typename T, typename RT> template <typename T, typename RT>
struct return_pair struct return_pair
{ {
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
@ -225,7 +245,7 @@ class idm
} }
}; };
template<typename RT> template <typename RT>
struct return_pair<bool, RT> struct return_pair<bool, RT>
{ {
bool result; bool result;
@ -238,40 +258,54 @@ class idm
}; };
// 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(std::pair<u32, u32> types, u32 base, u32 step, u32 count); static id_manager::id_map::pointer allocate_id(const id_manager::id_key& info, u32 base, u32 step, u32 count);
// Remove ID and return the object (additionally check true_type if not equal) // Find ID (additionally check type if types are not equal)
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 id); template <typename T, typename Type>
static id_manager::id_map::pointer find_id(u32 id)
{
static_assert(id_manager::id_verify<T, Type>::value, "Invalid ID type combination");
// Get ID (additionally check true_type if not equal) const u32 index = get_index<Type>(id);
static id_manager::id_map::const_pointer find_id(u32 type, u32 true_type, u32 id);
auto& vec = g_map[get_type<T>()];
if (index >= vec.size() || index >= id_manager::id_traits<Type>::count)
{
return nullptr;
}
if (const auto ptr = &vec[index])
{
if (std::is_same<T, Type>::value || ptr->first.type() == get_type<Type>())
{
return ptr;
}
}
return nullptr;
}
// 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 id_manager::id_map::pointer create_id(F&& provider)
{ {
writer_lock lock(id_manager::g_mutex); static_assert(id_manager::id_verify<T, Type>::value, "Invalid ID type combination");
// Register destructors // ID info
id_manager::typeinfo::update<T>(); const id_manager::id_key info{get_type<T>(), get_type<Type>(), id_manager::typeinfo::get_stop<Type>()};
// Type IDs // ID traits
std::pair<u32, u32> types(get_type<T>(), get_type<Type>()); using traits = id_manager::id_traits<Type>;
// Allocate new id // Allocate new id
if (auto* place = allocate_id(types, id_manager::id_traits<T>::base, id_manager::id_traits<T>::step, id_manager::id_traits<T>::count)) writer_lock lock(id_manager::g_mutex);
if (auto* place = allocate_id(info, traits::base, traits::step, traits::count))
{ {
try // Get object, store it
{ place->second = provider();
// Get object, store it return place;
place->second = provider();
return place;
}
catch (...)
{
delete_id(types.first, types.first, place->first.id());
throw;
}
} }
return nullptr; return nullptr;
@ -284,84 +318,80 @@ public:
// Remove all objects // Remove all objects
static void clear(); static void clear();
// Get last ID // Get last ID (updated in create_id/allocate_id)
static inline u32 last_id() static inline u32 last_id()
{ {
return g_id; return g_id;
} }
// Add a new ID of specified type with specified constructor arguments (returns object or nullptr) // Add a new ID of specified type with specified constructor arguments (returns object or nullptr)
template<typename T, typename Make = T, typename... Args> template <typename T, typename Make = T, typename... Args>
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<Make>> make_ptr(Args&&... args) static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<Make>> make_ptr(Args&&... args)
{ {
if (auto pair = create_id<T, Make>([&] { return std::make_shared<Make>(std::forward<Args>(args)...); })) if (auto pair = create_id<T, Make>([&] { return std::make_shared<Make>(std::forward<Args>(args)...); }))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<Make>::func(static_cast<Make*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); return {pair->second, static_cast<Make*>(pair->second.get())};
return{ pair->second, static_cast<Make*>(pair->second.get()) };
} }
return nullptr; return nullptr;
} }
// Add a new ID of specified type with specified constructor arguments (returns id) // Add a new ID of specified type with specified constructor arguments (returns id)
template<typename T, typename Make = T, typename... Args> template <typename T, typename Make = T, typename... Args>
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, u32> make(Args&&... args) static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, u32> make(Args&&... args)
{ {
if (auto pair = create_id<T, Make>([&] { return std::make_shared<Make>(std::forward<Args>(args)...); })) if (auto pair = create_id<T, Make>([&] { return std::make_shared<Make>(std::forward<Args>(args)...); }))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<Make>::func(static_cast<Make*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); return pair->first;
return pair->first.id();
} }
return id_manager::id_traits<T>::invalid; return id_manager::id_traits<Make>::invalid;
} }
// Add a new ID for an existing object provided (returns new id) // Add a new ID for an existing object provided (returns new id)
template<typename T, typename Made = T> template <typename T, typename Made = T>
static inline u32 import_existing(const std::shared_ptr<T>& ptr) static inline u32 import_existing(const std::shared_ptr<T>& ptr)
{ {
if (auto pair = create_id<T, Made>([&] { return ptr; })) if (auto pair = create_id<T, Made>([&] { return ptr; }))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<Made>::func(static_cast<Made*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); return pair->first;
return pair->first.id();
} }
return id_manager::id_traits<T>::invalid; return id_manager::id_traits<Made>::invalid;
} }
// Add a new ID for an object returned by provider() // Add a new ID for an object returned by provider()
template<typename T, typename Made = T, typename F, typename = std::result_of_t<F()>> template <typename T, typename Made = T, typename F, typename = std::result_of_t<F()>>
static inline std::shared_ptr<Made> import(F&& provider) static inline std::shared_ptr<Made> import(F&& provider)
{ {
if (auto pair = create_id<T, Made>(std::forward<F>(provider))) if (auto pair = create_id<T, Made>(std::forward<F>(provider)))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<Made>::func(static_cast<Made*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); return {pair->second, static_cast<Made*>(pair->second.get())};
return { pair->second, static_cast<Made*>(pair->second.get()) };
} }
return nullptr; return nullptr;
} }
// Check the ID // Check the ID
template<typename T, typename Get = T> template <typename T, typename Get = T>
static inline explicit_bool_t check(u32 id) static inline explicit_bool_t check(u32 id)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
return find_id(get_type<T>(), get_type<Get>(), id) != nullptr; return find_id<T, Get>(id) != nullptr;
} }
// Check the ID, access object under shared lock // Check the ID, access object under shared lock
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline explicit_bool_t check(u32 id, F&& func, int = 0) static inline explicit_bool_t check(u32 id, F&& func, int = 0)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
@ -373,12 +403,12 @@ public:
} }
// Check the ID, access object under reader lock, propagate return value // Check the ID, access object under reader lock, propagate return value
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline return_pair<bool, FRT> check(u32 id, F&& func) static inline return_pair<bool, FRT> check(u32 id, F&& func)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
@ -389,30 +419,30 @@ public:
} }
// Get the object // Get the object
template<typename T, typename Get = T, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>> template <typename T, typename Get = T>
static inline std::shared_ptr<Made> get(u32 id) static inline std::shared_ptr<Get> get(u32 id)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
return nullptr; return nullptr;
} }
return {found->second, static_cast<Made*>(found->second.get())}; return {found->second, static_cast<Get*>(found->second.get())};
} }
// Get the object, access object under reader lock // Get the object, access object under reader lock
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func, int = 0) static inline auto get(u32 id, F&& func, int = 0)
{ {
using result_type = std::shared_ptr<Get>; using result_type = std::shared_ptr<Get>;
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
@ -427,14 +457,14 @@ public:
} }
// Get the object, access object under reader lock, propagate return value // Get the object, access object under reader lock, propagate return value
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func) static inline auto get(u32 id, F&& func)
{ {
using result_type = return_pair<Get, FRT>; using result_type = return_pair<Get, FRT>;
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
@ -446,42 +476,52 @@ public:
return result_type{{found->second, ptr}, func(*ptr)}; return result_type{{found->second, ptr}, func(*ptr)};
} }
// Access all objects of specified types under reader lock (use lambda or callable object), return the number of objects processed // Access all objects of specified type. Returns the number of objects processed.
template<typename... Types, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::void_type> template <typename T, typename Get = T, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::void_type>
static inline u32 select(F&& func, int = 0) static inline u32 select(F&& func, int = 0)
{ {
static_assert(id_manager::id_verify<T, Get>::value, "Invalid ID type combination");
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
u32 result = 0; u32 result = 0;
for (u32 type : { get_type<Types>()... }) for (auto& id : g_map[get_type<T>()])
{ {
for (auto& id : g_map[type]) if (id.second)
{ {
func(id.first.id(), *static_cast<typename function_traits<FT>::object_type*>(id.second.get())); if (std::is_same<T, Get>::value || id.first.type() == get_type<Get>())
result++; {
func(id.first, *static_cast<typename function_traits<FT>::object_type*>(id.second.get()));
result++;
}
} }
} }
return result; return result;
} }
// Access all objects of specified types under reader lock (use lambda or callable object), if return value evaluates to true, stop and return the object and the value // Access all objects of specified type. If function result evaluates to true, stop and return the object and the value.
template<typename... Types, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::result_type> template <typename T, typename Get = T, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::result_type>
static inline auto select(F&& func) static inline auto select(F&& func)
{ {
static_assert(id_manager::id_verify<T, Get>::value, "Invalid ID type combination");
using object_type = typename function_traits<FT>::object_type; using object_type = typename function_traits<FT>::object_type;
using result_type = return_pair<object_type, FRT>; using result_type = return_pair<object_type, FRT>;
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
for (u32 type : { get_type<Types>()... }) for (auto& id : g_map[get_type<T>()])
{ {
for (auto& id : g_map[type]) if (auto ptr = static_cast<object_type*>(id.second.get()))
{ {
if (FRT result = func(id.first.id(), *static_cast<object_type*>(id.second.get()))) if (std::is_same<T, Get>::value || id.first.type() == get_type<Get>())
{ {
return result_type{{id.second, static_cast<object_type*>(id.second.get())}, std::move(result)}; if (FRT result = func(id.first, *ptr))
{
return result_type{{id.second, ptr}, std::move(result)};
}
} }
} }
} }
@ -489,58 +529,52 @@ public:
return result_type{nullptr}; return result_type{nullptr};
} }
// Get count of objects // Remove the ID
template<typename T, typename Get = void> template <typename T, typename Get = T>
static inline u32 get_count() static inline explicit_bool_t remove(u32 id)
{ {
reader_lock lock(id_manager::g_mutex); std::shared_ptr<void> ptr;
if (std::is_void<Get>::value)
{ {
return ::size32(g_map[get_type<T>()]); writer_lock lock(id_manager::g_mutex);
}
u32 result = 0; if (const auto found = find_id<T, Get>(id))
for (auto& id : g_map[get_type<T>()])
{
if (id.first.type() == get_type<Get>())
{ {
result++; ptr = std::move(found->second);
}
else
{
return false;
} }
} }
return result; id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
} return true;
// Remove the ID
template<typename T, typename Get = T>
static inline explicit_bool_t remove(u32 id)
{
if (auto ptr = (writer_lock{id_manager::g_mutex}, delete_id(get_type<T>(), get_type<Get>(), id)))
{
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
return true;
}
return false;
} }
// Remove the ID and return the object // Remove the ID and return the object
template<typename T, typename Get = T> template <typename T, typename Get = T>
static inline std::shared_ptr<Get> withdraw(u32 id) static inline std::shared_ptr<Get> withdraw(u32 id)
{ {
if (auto ptr = (writer_lock{id_manager::g_mutex}, delete_id(get_type<T>(), get_type<Get>(), id))) std::shared_ptr<void> ptr;
{ {
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); writer_lock lock(id_manager::g_mutex);
return {ptr, static_cast<Get*>(ptr.get())};
if (const auto found = find_id<T, Get>(id))
{
ptr = std::move(found->second);
}
else
{
return nullptr;
}
} }
return nullptr; id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
return {ptr, static_cast<Get*>(ptr.get())};
} }
// Remove the ID after accessing the object under writer lock, return the object and propagate return value // Remove the ID after accessing the object under writer lock, return the object and propagate return value
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func, int = 0) static inline auto withdraw(u32 id, F&& func, int = 0)
{ {
using result_type = std::shared_ptr<Get>; using result_type = std::shared_ptr<Get>;
@ -549,25 +583,24 @@ public:
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); if (const auto found = find_id<T, Get>(id))
{
func(*static_cast<Get*>(found->second.get()));
if (UNLIKELY(found == nullptr)) ptr = std::move(found->second);
}
else
{ {
return result_type{nullptr}; return result_type{nullptr};
} }
func(*static_cast<Get*>(found->second.get()));
ptr = delete_id(get_type<T>(), get_type<Get>(), id);
} }
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
return result_type{ptr, static_cast<Get*>(ptr.get())}; return result_type{ptr, static_cast<Get*>(ptr.get())};
} }
// Conditionally remove the ID (if return value evaluates to false) after accessing the object under writer lock, return the object and propagate return value // Conditionally remove the ID (if return value evaluates to false) after accessing the object under writer lock, return the object and propagate return value
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func) static inline auto withdraw(u32 id, F&& func)
{ {
using result_type = return_pair<Get, FRT>; using result_type = return_pair<Get, FRT>;
@ -577,27 +610,26 @@ public:
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); if (const auto found = find_id<T, Get>(id))
{
const auto _ptr = static_cast<Get*>(found->second.get());
if (UNLIKELY(found == nullptr)) ret = func(*_ptr);
if (ret)
{
return result_type{{found->second, _ptr}, std::move(ret)};
}
ptr = std::move(found->second);
}
else
{ {
return result_type{nullptr}; return result_type{nullptr};
} }
const auto _ptr = static_cast<Get*>(found->second.get());
ret = func(*_ptr);
if (ret)
{
return result_type{{found->second, _ptr}, std::move(ret)};
}
ptr = delete_id(get_type<T>(), get_type<Get>(), id);
} }
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
return result_type{{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)}; return result_type{{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)};
} }
}; };
@ -606,9 +638,9 @@ public:
class fxm class fxm
{ {
// Type Index -> Object. Use global since only one process is supported atm. // Type Index -> Object. Use global since only one process is supported atm.
static std::vector<std::shared_ptr<void>> g_vec; static std::vector<std::pair<void(*)(void*), std::shared_ptr<void>>> g_vec;
template<typename T> template <typename T>
static inline u32 get_type() static inline u32 get_type()
{ {
return id_manager::typeinfo::get_index<T>(); return id_manager::typeinfo::get_index<T>();
@ -622,47 +654,48 @@ public:
static void clear(); static void clear();
// Create the object (returns nullptr if it already exists) // Create the object (returns nullptr if it already exists)
template<typename T, typename Make = T, typename... Args> template <typename T, typename Make = T, typename... Args>
static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make(Args&&... args) static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make(Args&&... args)
{ {
id_manager::typeinfo::update<T>();
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
if (!g_vec[get_type<T>()]) auto& pair = g_vec[get_type<T>()];
if (!pair.second)
{ {
ptr = std::make_shared<Make>(std::forward<Args>(args)...); ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_vec[get_type<T>()] = ptr; pair.first = id_manager::typeinfo::get_stop<T>();
pair.second = ptr;
}
else
{
return nullptr;
} }
} }
if (ptr) id_manager::on_init<T>::func(ptr.get(), ptr);
{
id_manager::on_init<T>::func(ptr.get(), ptr);
id_manager::on_stop<T>::func(nullptr);
}
return ptr; return ptr;
} }
// Create the object unconditionally (old object will be removed if it exists) // Create the object unconditionally (old object will be removed if it exists)
template<typename T, typename Make = T, typename... Args> template <typename T, typename Make = T, typename... Args>
static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make_always(Args&&... args) static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make_always(Args&&... args)
{ {
id_manager::typeinfo::update<T>();
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
std::shared_ptr<void> old; std::shared_ptr<void> old;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
old = std::move(g_vec[get_type<T>()]); auto& pair = g_vec[get_type<T>()];
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_vec[get_type<T>()] = ptr; ptr = std::make_shared<Make>(std::forward<Args>(args)...);
old = std::move(pair.second);
pair.first = id_manager::typeinfo::get_stop<T>();
pair.second = ptr;
} }
if (old) if (old)
@ -675,47 +708,48 @@ public:
} }
// Emplace the object returned by provider() and return it if no object exists // Emplace the object returned by provider() and return it if no object exists
template<typename T, typename F> template <typename T, typename F>
static auto import(F&& provider) -> decltype(static_cast<std::shared_ptr<T>>(provider())) static auto import(F&& provider) -> decltype(static_cast<std::shared_ptr<T>>(provider()))
{ {
id_manager::typeinfo::update<T>();
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
if (!g_vec[get_type<T>()]) auto& pair = g_vec[get_type<T>()];
if (!pair.second)
{ {
ptr = provider(); ptr = provider();
g_vec[get_type<T>()] = ptr; pair.first = id_manager::typeinfo::get_stop<T>();
pair.second = ptr;
}
else
{
return nullptr;
} }
} }
if (ptr) id_manager::on_init<T>::func(ptr.get(), ptr);
{
id_manager::on_init<T>::func(ptr.get(), ptr);
id_manager::on_stop<T>::func(nullptr);
}
return ptr; return ptr;
} }
// Emplace the object return by provider() (old object will be removed if it exists) // Emplace the object return by provider() (old object will be removed if it exists)
template<typename T, typename F> template <typename T, typename F>
static auto import_always(F&& provider) -> decltype(static_cast<std::shared_ptr<T>>(provider())) static auto import_always(F&& provider) -> decltype(static_cast<std::shared_ptr<T>>(provider()))
{ {
id_manager::typeinfo::update<T>();
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
std::shared_ptr<void> old; std::shared_ptr<void> old;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
old = std::move(g_vec[get_type<T>()]); auto& pair = g_vec[get_type<T>()];
ptr = provider();
g_vec[get_type<T>()] = ptr; ptr = provider();
old = std::move(pair.second);
pair.first = id_manager::typeinfo::get_stop<T>();
pair.second = ptr;
} }
if (old) if (old)
@ -728,62 +762,62 @@ public:
} }
// Get the object unconditionally (create an object if it doesn't exist) // Get the object unconditionally (create an object if it doesn't exist)
template<typename T, typename Make = T, typename... Args> template <typename T, typename Make = T, typename... Args>
static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> get_always(Args&&... args) static std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> get_always(Args&&... args)
{ {
id_manager::typeinfo::update<T>();
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
if (auto& value = g_vec[get_type<T>()]) auto& pair = g_vec[get_type<T>()];
if (auto& old = pair.second)
{ {
return{ value, static_cast<T*>(value.get()) }; return {old, static_cast<T*>(old.get())};
} }
else else
{ {
ptr = std::make_shared<Make>(std::forward<Args>(args)...); ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_vec[get_type<T>()] = ptr; pair.first = id_manager::typeinfo::get_stop<T>();
pair.second = ptr;
} }
} }
id_manager::on_init<T>::func(ptr.get(), ptr); id_manager::on_init<T>::func(ptr.get(), ptr);
id_manager::on_stop<T>::func(nullptr);
return ptr; return ptr;
} }
// Check whether the object exists // Check whether the object exists
template<typename T> template <typename T, typename Get = T>
static inline explicit_bool_t check() static inline explicit_bool_t check()
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
return g_vec[get_type<T>()].operator bool(); return g_vec[get_type<T>()].second != nullptr;
} }
// Get the object (returns nullptr if it doesn't exist) // Get the object (returns nullptr if it doesn't exist)
template<typename T> template <typename T>
static inline std::shared_ptr<T> get() static inline std::shared_ptr<T> get()
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
auto& ptr = g_vec[get_type<T>()]; auto& ptr = g_vec[get_type<T>()].second;
return{ ptr, static_cast<T*>(ptr.get()) }; return {ptr, static_cast<T*>(ptr.get())};
} }
// Delete the object // Delete the object
template<typename T> template <typename T>
static inline explicit_bool_t remove() static inline explicit_bool_t remove()
{ {
std::shared_ptr<void> ptr; std::shared_ptr<void> ptr;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
ptr = std::move(g_vec[get_type<T>()]); ptr = std::move(g_vec[get_type<T>()].second);
} }
if (ptr) if (ptr)
{ {
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
@ -793,20 +827,20 @@ public:
} }
// Delete the object and return it // Delete the object and return it
template<typename T> template <typename T>
static inline std::shared_ptr<T> withdraw() static inline std::shared_ptr<T> withdraw()
{ {
std::shared_ptr<void> ptr; std::shared_ptr<void> ptr;
{ {
writer_lock lock(id_manager::g_mutex); writer_lock lock(id_manager::g_mutex);
ptr = std::move(g_vec[get_type<T>()]); ptr = std::move(g_vec[get_type<T>()].second);
} }
if (ptr) if (ptr)
{ {
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
} }
return{ ptr, static_cast<T*>(ptr.get()) }; return {ptr, static_cast<T*>(ptr.get())};
} }
}; };

View File

@ -16,7 +16,7 @@ class ARMv7Thread final : public cpu_thread
public: public:
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 2; static const u32 id_step = 2;
static const u32 id_count = 32767; static const u32 id_count = 4096;
virtual std::string get_name() const override; virtual std::string get_name() const override;
virtual std::string dump() const override; virtual std::string dump() const override;

View File

@ -809,8 +809,8 @@ s32 sceKernelWaitMultipleEventsCB(vm::ptr<SceKernelWaitEvent> pWaitEventList, s3
struct psp2_event_flag final struct psp2_event_flag final
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 2;
static const u32 id_count = 32767; static const u32 id_count = 8192;
using ipc = ipc_manager<psp2_event_flag, std::string>; using ipc = ipc_manager<psp2_event_flag, std::string>;

View File

@ -497,8 +497,8 @@ struct SceKernelSemaInfo
struct psp2_semaphore struct psp2_semaphore
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 2;
static const u32 id_count = 32767; static const u32 id_count = 8192;
const std::string name; // IPC Name const std::string name; // IPC Name
@ -541,8 +541,8 @@ struct SceKernelMutexInfo
struct psp2_mutex struct psp2_mutex
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 2;
static const u32 id_count = 32767; static const u32 id_count = 8192;
const std::string name; // IPC Name const std::string name; // IPC Name
@ -605,8 +605,8 @@ struct SceKernelCondInfo
struct psp2_cond struct psp2_cond
{ {
static const u32 id_base = 1; static const u32 id_base = 1;
static const u32 id_step = 1; static const u32 id_step = 2;
static const u32 id_count = 32767; static const u32 id_count = 8192;
const std::string name; // IPC Name const std::string name; // IPC Name

View File

@ -49,7 +49,7 @@ extern u64 get_system_time();
extern void ppu_load_exec(const ppu_exec_object&); extern void ppu_load_exec(const ppu_exec_object&);
extern void spu_load_exec(const spu_exec_object&); extern void spu_load_exec(const spu_exec_object&);
extern void arm_load_exec(const arm_exec_object&); extern void arm_load_exec(const arm_exec_object&);
extern std::shared_ptr<struct lv2_prx_t> ppu_load_prx(const ppu_prx_object&); extern std::shared_ptr<struct lv2_prx> ppu_load_prx(const ppu_prx_object&);
fs::file g_tty; fs::file g_tty;
@ -346,10 +346,15 @@ void Emulator::Run()
m_pause_amend_time = 0; m_pause_amend_time = 0;
m_status = Running; m_status = Running;
idm::select<ppu_thread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.run(); cpu.run();
}); };
idm::select<ppu_thread>(on_select);
idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select);
SendDbgCommand(DID_STARTED_EMU); SendDbgCommand(DID_STARTED_EMU);
} }
@ -374,10 +379,15 @@ bool Emulator::Pause()
SendDbgCommand(DID_PAUSE_EMU); SendDbgCommand(DID_PAUSE_EMU);
idm::select<ppu_thread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.state += cpu_flag::dbg_global_pause; cpu.state += cpu_flag::dbg_global_pause;
}); };
idm::select<ppu_thread>(on_select);
idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select);
SendDbgCommand(DID_PAUSED_EMU); SendDbgCommand(DID_PAUSED_EMU);
@ -411,11 +421,16 @@ void Emulator::Resume()
{ {
LV2_LOCK; LV2_LOCK;
idm::select<ppu_thread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.state -= cpu_flag::dbg_global_pause; cpu.state -= cpu_flag::dbg_global_pause;
cpu.notify(); cpu.notify();
}); };
idm::select<ppu_thread>(on_select);
idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select);
} }
rpcs3::on_resume()(); rpcs3::on_resume()();
@ -438,12 +453,16 @@ void Emulator::Stop()
{ {
LV2_LOCK; LV2_LOCK;
idm::select<ppu_thread, SPUThread, RawSPUThread, ARMv7Thread>([](u32, cpu_thread& cpu) auto on_select = [](u32, cpu_thread& cpu)
{ {
cpu.state += cpu_flag::dbg_global_stop; cpu.state += cpu_flag::dbg_global_stop;
cpu.get()->set_exception(std::make_exception_ptr(EmulationStopped())); cpu.get()->set_exception(std::make_exception_ptr(EmulationStopped()));
cpu.notify(); };
});
idm::select<ppu_thread>(on_select);
idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select);
} }
LOG_NOTICE(GENERAL, "All threads signaled..."); LOG_NOTICE(GENERAL, "All threads signaled...");

View File

@ -122,10 +122,15 @@ void InterpreterDisAsmFrame::UpdateUnitList()
m_choice_units->Freeze(); m_choice_units->Freeze();
m_choice_units->Clear(); m_choice_units->Clear();
idm::select<ppu_thread, SPUThread, RawSPUThread, ARMv7Thread>([&](u32, cpu_thread& cpu) const auto on_select = [&](u32, cpu_thread& cpu)
{ {
m_choice_units->Append(cpu.get_name(), &cpu); m_choice_units->Append(cpu.get_name(), &cpu);
}); };
idm::select<ppu_thread>(on_select);
idm::select<ARMv7Thread>(on_select);
idm::select<RawSPUThread>(on_select);
idm::select<SPUThread>(on_select);
m_choice_units->Thaw(); m_choice_units->Thaw();
} }

View File

@ -19,6 +19,10 @@
#include "Emu/Cell/lv2/sys_memory.h" #include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/Cell/lv2/sys_mmapper.h" #include "Emu/Cell/lv2/sys_mmapper.h"
#include "Emu/Cell/lv2/sys_spu.h" #include "Emu/Cell/lv2/sys_spu.h"
#include "Emu/Cell/lv2/sys_interrupt.h"
#include "Emu/Cell/lv2/sys_timer.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "Emu/Cell/lv2/sys_fs.h"
#include "KernelExplorer.h" #include "KernelExplorer.h"
@ -57,7 +61,15 @@ KernelExplorer::KernelExplorer(wxWindow* parent)
void KernelExplorer::Update() void KernelExplorer::Update()
{ {
m_tree->DeleteAllItems(); m_tree->DeleteAllItems();
const u32 total_memory_usage = vm::get(vm::user_space)->used();
const auto vm_block = vm::get(vm::user_space);
if (!vm_block)
{
return;
}
const u32 total_memory_usage = vm_block->used();
const auto& root = m_tree->AddRoot(fmt::format("Process, ID = 0x00000001, Total Memory Usage = 0x%x (%0.2f MB)", total_memory_usage, (float)total_memory_usage / (1024 * 1024))); const auto& root = m_tree->AddRoot(fmt::format("Process, ID = 0x00000001, Total Memory Usage = 0x%x (%0.2f MB)", total_memory_usage, (float)total_memory_usage / (1024 * 1024)));
@ -67,11 +79,11 @@ void KernelExplorer::Update()
char string[8]; char string[8];
name64(u64 data) name64(u64 data)
: u64_data(data & 0x00ffffffffffffffull) : u64_data(data & 0x00ffffffffffffffull)
{ {
} }
const char* operator &() const const char* operator+() const
{ {
return string; return string;
} }
@ -79,167 +91,203 @@ void KernelExplorer::Update()
// TODO: FileSystem // TODO: FileSystem
// Semaphores struct lv2_obj_rec
if (const u32 count = idm::get_count<lv2_sema_t>())
{ {
const auto& node = m_tree->AppendItem(root, fmt::format("Semaphores (%zu)", count)); wxTreeItemId node;
u32 count{0};
idm::select<lv2_sema_t>([&](u32 id, lv2_sema_t& sema) lv2_obj_rec() = default;
lv2_obj_rec(wxTreeItemId node)
: node(node)
{ {
m_tree->AppendItem(node, fmt::format("Semaphore: ID = 0x%08x '%s', Count = %d, Max Count = %d, Waiters = %#zu", id, }
&name64(sema.name), sema.value.load(), sema.max, sema.sq.size())); };
});
}
// Mutexes std::vector<lv2_obj_rec> lv2_types(256);
if (const u32 count = idm::get_count<lv2_mutex_t>()) lv2_types[SYS_MEM_OBJECT] = m_tree->AppendItem(root, "Memory");
lv2_types[SYS_MUTEX_OBJECT] = m_tree->AppendItem(root, "Mutexes");
lv2_types[SYS_COND_OBJECT] = m_tree->AppendItem(root, "Condition Variables");
lv2_types[SYS_RWLOCK_OBJECT] = m_tree->AppendItem(root, "Reader Writer Locks");
lv2_types[SYS_INTR_TAG_OBJECT] = m_tree->AppendItem(root, "Interrupt Tags");
lv2_types[SYS_INTR_SERVICE_HANDLE_OBJECT] = m_tree->AppendItem(root, "Interrupt Service Handles");
lv2_types[SYS_EVENT_QUEUE_OBJECT] = m_tree->AppendItem(root, "Event Queues");
lv2_types[SYS_EVENT_PORT_OBJECT] = m_tree->AppendItem(root, "Event Ports");
lv2_types[SYS_TRACE_OBJECT] = m_tree->AppendItem(root, "Traces");
lv2_types[SYS_SPUIMAGE_OBJECT] = m_tree->AppendItem(root, "SPU Images");
lv2_types[SYS_PRX_OBJECT] = m_tree->AppendItem(root, "Modules");
lv2_types[SYS_SPUPORT_OBJECT] = m_tree->AppendItem(root, "SPU Ports");
lv2_types[SYS_LWMUTEX_OBJECT] = m_tree->AppendItem(root, "Light Weight Mutexes");
lv2_types[SYS_TIMER_OBJECT] = m_tree->AppendItem(root, "Timers");
lv2_types[SYS_SEMAPHORE_OBJECT] = m_tree->AppendItem(root, "Semaphores");
lv2_types[SYS_LWCOND_OBJECT] = m_tree->AppendItem(root, "Light Weight Condition Variables");
lv2_types[SYS_EVENT_FLAG_OBJECT] = m_tree->AppendItem(root, "Event Flags");
idm::select<lv2_obj>([&](u32 id, lv2_obj& obj)
{ {
const auto& node = m_tree->AppendItem(root, fmt::format("Mutexes (%zu)", count)); lv2_types[id >> 24].count++;
idm::select<lv2_mutex_t>([&](u32 id, lv2_mutex_t& mutex) if (auto& node = lv2_types[id >> 24].node) switch (id >> 24)
{ {
m_tree->AppendItem(node, fmt::format("Mutex: ID = 0x%08x '%s'", id, case SYS_MEM_OBJECT:
&name64(mutex.name)));
});
}
// Lightweight Mutexes
if (const u32 count = idm::get_count<lv2_lwmutex_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Mutexes (%zu)", count));
idm::select<lv2_lwmutex_t>([&](u32 id, lv2_lwmutex_t& lwm)
{ {
m_tree->AppendItem(node, fmt::format("LWMutex: ID = 0x%08x '%s'", id, auto& mem = static_cast<lv2_memory&>(obj);
&name64(lwm.name))); m_tree->AppendItem(node, fmt::format("Memory: ID = 0x%08x", id));
}); break;
} }
case SYS_MUTEX_OBJECT:
// Condition Variables
if (const u32 count = idm::get_count<lv2_cond_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Condition Variables (%zu)", count));
idm::select<lv2_cond_t>([&](u32 id, lv2_cond_t& cond)
{ {
m_tree->AppendItem(node, fmt::format("Cond: ID = 0x%08x '%s'", id, auto& mutex = static_cast<lv2_mutex&>(obj);
&name64(cond.name))); m_tree->AppendItem(node, fmt::format("Mutex: ID = 0x%08x \"%s\"", id, +name64(mutex.name)));
}); break;
} }
case SYS_COND_OBJECT:
// Lightweight Condition Variables
if (const u32 count = idm::get_count<lv2_lwcond_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Condition Variables (%zu)", count));
idm::select<lv2_lwcond_t>([&](u32 id, lv2_lwcond_t& lwc)
{ {
m_tree->AppendItem(node, fmt::format("LWCond: ID = 0x%08x '%s'", id, auto& cond = static_cast<lv2_cond&>(obj);
&name64(lwc.name))); m_tree->AppendItem(node, fmt::format("Cond: ID = 0x%08x \"%s\"", id, +name64(cond.name)));
}); break;
} }
case SYS_RWLOCK_OBJECT:
// Event Queues
if (const u32 count = idm::get_count<lv2_event_queue_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Event Queues (%zu)", count));
idm::select<lv2_event_queue_t>([&](u32 id, lv2_event_queue_t& eq)
{ {
m_tree->AppendItem(node, fmt::format("Event Queue: ID = 0x%08x '%s', %s, Key = %#llx, Events = %zu/%d, Waiters = %zu", id, auto& rw = static_cast<lv2_rwlock&>(obj);
&name64(eq.name), eq.type == SYS_SPU_QUEUE ? "SPU" : "PPU", eq.ipc_key, eq.events(), eq.size, eq.waiters())); m_tree->AppendItem(node, fmt::format("RW Lock: ID = 0x%08x", id));
}); break;
} }
case SYS_INTR_TAG_OBJECT:
// Event Ports
if (const u32 count = idm::get_count<lv2_event_port_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Event Ports (%zu)", count));
idm::select<lv2_event_port_t>([&](u32 id, lv2_event_port_t& ep)
{ {
m_tree->AppendItem(node, fmt::format("Event Port: ID = 0x%08x, Name = %#llx", id, auto& tag = static_cast<lv2_int_tag&>(obj);
ep.name)); m_tree->AppendItem(node, fmt::format("Intr Tag: ID = 0x%08x", id));
}); break;
} }
case SYS_INTR_SERVICE_HANDLE_OBJECT:
// Event Flags
if (const u32 count = idm::get_count<lv2_event_flag_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Event Flags (%zu)", count));
idm::select<lv2_event_flag_t>([&](u32 id, lv2_event_flag_t& ef)
{ {
m_tree->AppendItem(node, fmt::format("Event Flag: ID = 0x%08x '%s', Type = 0x%x, Pattern = 0x%llx", id, auto& serv = static_cast<lv2_int_serv&>(obj);
&name64(ef.name), ef.type, ef.pattern.load())); m_tree->AppendItem(node, fmt::format("Intr Svc: ID = 0x%08x", id));
}); break;
} }
case SYS_EVENT_QUEUE_OBJECT:
// Reader/writer Locks
if (const u32 count = idm::get_count<lv2_rwlock_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Reader/writer Locks (%zu)", count));
idm::select<lv2_rwlock_t>([&](u32 id, lv2_rwlock_t&)
{ {
m_tree->AppendItem(node, fmt::format("RWLock: ID = 0x%08x", id)); auto& eq = static_cast<lv2_event_queue&>(obj);
}); m_tree->AppendItem(node, fmt::format("Event Queue: ID = 0x%08x \"%s\", %s, Key = %#llx, Events = %zu/%d, Waiters = %zu", id, +name64(eq.name),
} eq.type == SYS_SPU_QUEUE ? "SPU" : "PPU", eq.ipc_key, eq.events(), eq.size, eq.waiters()));
break;
// PRX Libraries }
if (const u32 count = idm::get_count<lv2_prx_t>()) case SYS_EVENT_PORT_OBJECT:
{
const auto& node = m_tree->AppendItem(root, fmt::format("PRX Libraries (%zu)", count));
idm::select<lv2_prx_t>([&](u32 id, lv2_prx_t&)
{ {
auto& ep = static_cast<lv2_event_port&>(obj);
m_tree->AppendItem(node, fmt::format("Event Port: ID = 0x%08x, Name = %#llx", id, ep.name));
break;
}
case SYS_TRACE_OBJECT:
{
m_tree->AppendItem(node, fmt::format("Trace: ID = 0x%08x", id));
break;
}
case SYS_SPUIMAGE_OBJECT:
{
m_tree->AppendItem(node, fmt::format("SPU Image: ID = 0x%08x", id));
break;
}
case SYS_PRX_OBJECT:
{
auto& prx = static_cast<lv2_prx&>(obj);
m_tree->AppendItem(node, fmt::format("PRX: ID = 0x%08x", id)); m_tree->AppendItem(node, fmt::format("PRX: ID = 0x%08x", id));
}); break;
} }
case SYS_SPUPORT_OBJECT:
// Memory Containers
if (const u32 count = idm::get_count<lv2_memory_container>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Containers (%zu)", count));
idm::select<lv2_memory_container>([&](u32 id, lv2_memory_container&)
{ {
m_tree->AppendItem(node, fmt::format("Memory Container: ID = 0x%08x", id)); m_tree->AppendItem(node, fmt::format("SPU Port: ID = 0x%08x", id));
}); break;
} }
case SYS_LWMUTEX_OBJECT:
// Memory Objects
if (const u32 count = idm::get_count<lv2_memory>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Objects (%zu)", count));
idm::select<lv2_memory>([&](u32 id, lv2_memory&)
{ {
m_tree->AppendItem(node, fmt::format("Memory Object: ID = 0x%08x", id)); auto& lwm = static_cast<lv2_lwmutex&>(obj);
}); m_tree->AppendItem(node, fmt::format("LWMutex: ID = 0x%08x \"%s\"", id, +name64(lwm.name)));
} break;
}
// PPU Threads case SYS_TIMER_OBJECT:
if (const u32 count = idm::get_count<ppu_thread>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("PPU Threads (%zu)", count));
idm::select<ppu_thread>([&](u32 id, ppu_thread& ppu)
{ {
m_tree->AppendItem(node, fmt::format("PPU Thread: ID = 0x%08x '%s'", id, ppu.get_name())); auto& timer = static_cast<lv2_timer&>(obj);
}); m_tree->AppendItem(node, fmt::format("Timer: ID = 0x%08x", id));
} break;
}
// SPU Thread Groups case SYS_SEMAPHORE_OBJECT:
if (const u32 count = idm::get_count<lv2_spu_group_t>())
{
const auto& node = m_tree->AppendItem(root, fmt::format("SPU Thread Groups (%d)", count));
idm::select<lv2_spu_group_t>([&](u32 id, lv2_spu_group_t& tg)
{ {
m_tree->AppendItem(node, fmt::format("SPU Thread Group: ID = 0x%08x '%s'", id, auto& sema = static_cast<lv2_sema&>(obj);
tg.name.c_str())); m_tree->AppendItem(node, fmt::format("Semaphore: ID = 0x%08x \"%s\", Count = %d, Max Count = %d, Waiters = %#zu", id, +name64(sema.name),
}); sema.value.load(), sema.max, sema.sq.size()));
break;
}
case SYS_LWCOND_OBJECT:
{
auto& lwc = static_cast<lv2_cond&>(obj);
m_tree->AppendItem(node, fmt::format("LWCond: ID = 0x%08x \"%s\"", id, +name64(lwc.name)));
break;
}
case SYS_EVENT_FLAG_OBJECT:
{
auto& ef = static_cast<lv2_event_flag&>(obj);
m_tree->AppendItem(node, fmt::format("Event Flag: ID = 0x%08x \"%s\", Type = 0x%x, Pattern = 0x%llx", id, +name64(ef.name), ef.type, ef.pattern.load()));
break;
}
default:
{
m_tree->AppendItem(node, fmt::format("Unknown object: ID = 0x%08x", id));
}
}
});
lv2_types.emplace_back(m_tree->AppendItem(root, "Memory Containers"));
idm::select<lv2_memory_container>([&](u32 id, lv2_memory_container&)
{
lv2_types.back().count++;
m_tree->AppendItem(lv2_types.back().node, fmt::format("Memory Container: ID = 0x%08x", id));
});
lv2_types.emplace_back(m_tree->AppendItem(root, "PPU Threads"));
idm::select<ppu_thread>([&](u32 id, ppu_thread& ppu)
{
lv2_types.back().count++;
m_tree->AppendItem(lv2_types.back().node, fmt::format("PPU Thread: ID = 0x%08x '%s'", id, ppu.get_name()));
});
lv2_types.emplace_back(m_tree->AppendItem(root, "SPU Threads"));
idm::select<SPUThread>([&](u32 id, SPUThread& spu)
{
lv2_types.back().count++;
m_tree->AppendItem(lv2_types.back().node, fmt::format("SPU Thread: ID = 0x%08x '%s'", id, spu.get_name()));
});
lv2_types.emplace_back(m_tree->AppendItem(root, "SPU Thread Groups"));
idm::select<lv2_spu_group>([&](u32 id, lv2_spu_group& tg)
{
lv2_types.back().count++;
m_tree->AppendItem(lv2_types.back().node, fmt::format("SPU Thread Group: ID = 0x%08x '%s'", id, tg.name.c_str()));
});
lv2_types.emplace_back(m_tree->AppendItem(root, "File Descriptors"));
idm::select<lv2_fs_object>([&](u32 id, lv2_fs_object& fo)
{
lv2_types.back().count++;
m_tree->AppendItem(lv2_types.back().node, fmt::format("FD: ID = 0x%08x '%s'", id));
});
for (auto&& entry : lv2_types)
{
if (entry.node && entry.count)
{
// Append object count
m_tree->SetItemText(entry.node, m_tree->GetItemText(entry.node) + fmt::format(" (%zu)", entry.count));
}
else if (entry.node)
{
// Delete node otherwise
m_tree->Delete(entry.node);
}
} }
// RawSPU Threads (TODO) // RawSPU Threads (TODO)