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:
parent
be8d8ded3f
commit
b21fce4d6f
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}))
|
}))
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
{
|
{
|
||||||
|
@ -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())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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>;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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...");
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user