mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-22 03:40:30 +00:00
IdManager improved
This commit is contained in:
parent
6c189511af
commit
591a6c8671
@ -839,34 +839,6 @@ struct multicast<T, Value, void>
|
||||
}
|
||||
};
|
||||
|
||||
// Tagged ID type
|
||||
template <typename T = void, typename ID = u32>
|
||||
class id_value
|
||||
{
|
||||
// Initial value
|
||||
mutable ID m_value{static_cast<ID>(-1)};
|
||||
|
||||
// Allow access for ID manager
|
||||
friend class idm;
|
||||
|
||||
// Update ID
|
||||
void operator=(const ID& value) const
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr id_value()
|
||||
{
|
||||
}
|
||||
|
||||
// Get the value
|
||||
operator ID() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
};
|
||||
|
||||
// Error code type (return type), implements error reporting. Could be a template.
|
||||
struct error_code
|
||||
{
|
||||
@ -921,14 +893,3 @@ constexpr FORCE_INLINE error_code::not_an_error not_an_error(const T& value)
|
||||
{
|
||||
return static_cast<error_code::not_an_error>(static_cast<s32>(value));
|
||||
}
|
||||
|
||||
template <typename T, typename ID>
|
||||
struct fmt_unveil<id_value<T, ID>>
|
||||
{
|
||||
using type = typename fmt_unveil<ID>::type;
|
||||
|
||||
static inline auto get(const id_value<T, ID>& value)
|
||||
{
|
||||
return fmt_unveil<ID>::get(value);
|
||||
}
|
||||
};
|
||||
|
@ -93,7 +93,8 @@ cpu_thread::~cpu_thread()
|
||||
{
|
||||
}
|
||||
|
||||
cpu_thread::cpu_thread()
|
||||
cpu_thread::cpu_thread(u32 id)
|
||||
: id(id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -31,9 +31,9 @@ public:
|
||||
virtual void on_stop() override;
|
||||
virtual ~cpu_thread() override;
|
||||
|
||||
const id_value<> id{};
|
||||
const u32 id;
|
||||
|
||||
cpu_thread();
|
||||
cpu_thread(u32 id);
|
||||
|
||||
// Public thread state
|
||||
atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop};
|
||||
@ -50,6 +50,12 @@ public:
|
||||
// Set cpu_flag::signal
|
||||
void set_signal();
|
||||
|
||||
// Check thread type
|
||||
u32 id_type()
|
||||
{
|
||||
return id >> 24;
|
||||
}
|
||||
|
||||
// Print CPU state
|
||||
virtual std::string dump() const;
|
||||
|
||||
|
@ -143,10 +143,14 @@ class ElementaryStream
|
||||
bool is_full(u32 space);
|
||||
|
||||
public:
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec);
|
||||
|
||||
Demuxer* dmux;
|
||||
const id_value<> id{};
|
||||
const u32 id = idm::last_id();
|
||||
const u32 memAddr;
|
||||
const u32 memSize;
|
||||
const u32 fidMajor;
|
||||
|
@ -109,6 +109,10 @@ struct CellJpgDecDataOutInfo
|
||||
// Custom structs
|
||||
struct CellJpgDecSubHandle
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
u32 fd;
|
||||
u64 fileSize;
|
||||
CellJpgDecInfo info;
|
||||
|
@ -321,6 +321,10 @@ struct CellVpostPictureInfo
|
||||
class VpostInstance
|
||||
{
|
||||
public:
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const bool to_rgba;
|
||||
|
||||
VpostInstance(bool rgba)
|
||||
|
@ -16,7 +16,11 @@ logs::channel sceNpTrophy("sceNpTrophy", logs::level::notice);
|
||||
|
||||
struct trophy_context_t
|
||||
{
|
||||
const id_value<> id{};
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const u32 id = idm::last_id();
|
||||
|
||||
std::string trp_name;
|
||||
fs::file trp_stream;
|
||||
@ -25,7 +29,11 @@ struct trophy_context_t
|
||||
|
||||
struct trophy_handle_t
|
||||
{
|
||||
const id_value<> id{};
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const u32 id = idm::last_id();
|
||||
};
|
||||
|
||||
// Functions
|
||||
|
@ -9,6 +9,10 @@ extern logs::channel sysPrxForUser;
|
||||
|
||||
struct HeapInfo
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const std::string name;
|
||||
|
||||
HeapInfo(const char* name)
|
||||
|
@ -11,6 +11,10 @@ using sys_mempool_t = u32;
|
||||
|
||||
struct memory_pool_t
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
vm::ptr<void> chunk;
|
||||
u64 chunk_size;
|
||||
u64 block_size;
|
||||
|
@ -86,10 +86,9 @@ int inet_pton(int af, const char *src, char *dst)
|
||||
// We map host sockets to sequential IDs to return as descriptors because syscalls expect socket IDs to be under 1024.
|
||||
struct sys_net_socket final
|
||||
{
|
||||
using id_base = sys_net_socket;
|
||||
|
||||
static constexpr u32 id_min = 0; // Minimal valid socket number is 0 (not 1).
|
||||
static constexpr u32 id_max = 1023;
|
||||
static const u32 id_base = 0;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 1024;
|
||||
|
||||
sys_net::socket_t s = -1;
|
||||
|
||||
|
@ -253,7 +253,7 @@ ppu_thread::~ppu_thread()
|
||||
}
|
||||
|
||||
ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack)
|
||||
: cpu_thread()
|
||||
: cpu_thread(idm::last_id())
|
||||
, prio(prio)
|
||||
, stack_size(std::max<u32>(stack, 0x4000))
|
||||
, stack_addr(vm::alloc(stack_size, vm::stack))
|
||||
@ -404,7 +404,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
|
||||
|
||||
u32 ppu_thread::stack_push(u32 size, u32 align_v)
|
||||
{
|
||||
if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min)
|
||||
if (auto cpu = get_current_cpu_thread()) if (cpu->id_type() == 1)
|
||||
{
|
||||
ppu_thread& context = static_cast<ppu_thread&>(*cpu);
|
||||
|
||||
@ -430,7 +430,7 @@ u32 ppu_thread::stack_push(u32 size, u32 align_v)
|
||||
|
||||
void ppu_thread::stack_pop_verbose(u32 addr, u32 size) noexcept
|
||||
{
|
||||
if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min)
|
||||
if (auto cpu = get_current_cpu_thread()) if (cpu->id_type() == 1)
|
||||
{
|
||||
ppu_thread& context = static_cast<ppu_thread&>(*cpu);
|
||||
|
||||
|
@ -20,10 +20,9 @@ enum class ppu_cmd : u32
|
||||
class ppu_thread : public cpu_thread
|
||||
{
|
||||
public:
|
||||
using id_base = ppu_thread;
|
||||
|
||||
static constexpr u32 id_min = 0x70000000; // TODO (used to determine thread type)
|
||||
static constexpr u32 id_max = 0x7fffffff;
|
||||
static const u32 id_base = 0x01000000; // TODO (used to determine thread type)
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 65535;
|
||||
|
||||
virtual std::string get_name() const override;
|
||||
virtual std::string dump() const override;
|
||||
|
@ -7,12 +7,9 @@ class RawSPUThread final : public SPUThread
|
||||
void cpu_task() override;
|
||||
|
||||
public:
|
||||
/* IdManager setups */
|
||||
|
||||
using id_base = RawSPUThread;
|
||||
|
||||
static constexpr u32 id_min = 0;
|
||||
static constexpr u32 id_max = 4;
|
||||
static const u32 id_base = 0;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 5;
|
||||
|
||||
void on_init(const std::shared_ptr<void>&) override;
|
||||
|
||||
|
@ -238,7 +238,7 @@ SPUThread::~SPUThread()
|
||||
}
|
||||
|
||||
SPUThread::SPUThread(const std::string& name)
|
||||
: cpu_thread()
|
||||
: cpu_thread(idm::last_id())
|
||||
, m_name(name)
|
||||
, index(0)
|
||||
, offset(0)
|
||||
@ -246,7 +246,7 @@ SPUThread::SPUThread(const std::string& name)
|
||||
}
|
||||
|
||||
SPUThread::SPUThread(const std::string& name, u32 index)
|
||||
: cpu_thread()
|
||||
: cpu_thread(idm::last_id())
|
||||
, m_name(name)
|
||||
, index(index)
|
||||
, offset(verify("SPU LS" HERE, vm::alloc(0x40000, vm::main)))
|
||||
|
@ -501,6 +501,10 @@ protected:
|
||||
SPUThread(const std::string& name);
|
||||
|
||||
public:
|
||||
static const u32 id_base = 0x02000000; // TODO (used to determine thread type)
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 65535;
|
||||
|
||||
SPUThread(const std::string& name, u32 index);
|
||||
|
||||
std::array<v128, 128> gpr; // General-Purpose Registers
|
||||
|
@ -19,6 +19,10 @@ struct sys_cond_attribute_t
|
||||
|
||||
struct lv2_cond_t
|
||||
{
|
||||
static const u32 id_base = 0x86000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u64 name;
|
||||
const std::shared_ptr<lv2_mutex_t> mutex; // associated mutex
|
||||
|
||||
|
@ -18,20 +18,25 @@ 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)
|
||||
{
|
||||
auto queue = std::make_shared<lv2_event_queue_t>(protocol, type, name, ipc_key, size);
|
||||
std::shared_ptr<lv2_event_queue_t> result;
|
||||
|
||||
auto make_expr = [&] { return idm::import<lv2_event_queue_t>([&] { return queue; }); };
|
||||
auto make_expr = [&]() -> const std::shared_ptr<lv2_event_queue_t>&
|
||||
{
|
||||
result = idm::make_ptr<lv2_event_queue_t>(protocol, type, name, ipc_key, size);
|
||||
return result;
|
||||
};
|
||||
|
||||
if (ipc_key == SYS_EVENT_QUEUE_LOCAL)
|
||||
{
|
||||
// Not an IPC queue
|
||||
return make_expr();
|
||||
make_expr();
|
||||
return result;
|
||||
}
|
||||
|
||||
// IPC queue
|
||||
if (ipc_manager<lv2_event_queue_t, u64>::add(ipc_key, make_expr))
|
||||
{
|
||||
return queue;
|
||||
return result;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -48,6 +53,16 @@ std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::find(u64 ipc_key)
|
||||
return ipc_manager<lv2_event_queue_t, u64>::get(ipc_key);
|
||||
}
|
||||
|
||||
lv2_event_queue_t::lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
|
||||
: protocol(protocol)
|
||||
, type(type)
|
||||
, name(name)
|
||||
, ipc_key(ipc_key)
|
||||
, size(size)
|
||||
, id(idm::last_id())
|
||||
{
|
||||
}
|
||||
|
||||
void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3)
|
||||
{
|
||||
verify(HERE), m_sq.empty() || m_events.empty();
|
||||
@ -61,7 +76,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
|
||||
// notify waiter; protocol is ignored in current implementation
|
||||
auto& thread = m_sq.front();
|
||||
|
||||
if (type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min)
|
||||
if (type == SYS_PPU_QUEUE && thread->id_type() == 1)
|
||||
{
|
||||
// store event data in registers
|
||||
auto& ppu = static_cast<ppu_thread&>(*thread);
|
||||
@ -71,7 +86,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
|
||||
ppu.gpr[6] = data2;
|
||||
ppu.gpr[7] = data3;
|
||||
}
|
||||
else if (type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min)
|
||||
else if (type == SYS_SPU_QUEUE && thread->id_type() != 1)
|
||||
{
|
||||
// store event data in In_MBox
|
||||
auto& spu = static_cast<SPUThread&>(*thread);
|
||||
@ -162,11 +177,11 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
|
||||
// signal all threads to return CELL_ECANCELED
|
||||
for (auto& thread : queue->thread_queue(lv2_lock))
|
||||
{
|
||||
if (queue->type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min)
|
||||
if (queue->type == SYS_PPU_QUEUE && thread->id_type() == 1)
|
||||
{
|
||||
static_cast<ppu_thread&>(*thread).gpr[3] = 1;
|
||||
}
|
||||
else if (queue->type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min)
|
||||
else if (queue->type == SYS_SPU_QUEUE && thread->id_type() != 1)
|
||||
{
|
||||
static_cast<SPUThread&>(*thread).ch_in_mbox.set_values(1, CELL_ECANCELED);
|
||||
}
|
||||
|
@ -73,6 +73,10 @@ class lv2_event_queue_t final
|
||||
sleep_queue<cpu_thread> m_sq;
|
||||
|
||||
public:
|
||||
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
|
||||
static std::shared_ptr<lv2_event_queue_t> make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
|
||||
|
||||
@ -84,17 +88,9 @@ public:
|
||||
const u64 name;
|
||||
const u64 ipc_key;
|
||||
const s32 size;
|
||||
const u32 id;
|
||||
|
||||
const id_value<> id{};
|
||||
|
||||
lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
|
||||
: protocol(protocol)
|
||||
, type(type)
|
||||
, name(name)
|
||||
, ipc_key(ipc_key)
|
||||
, size(size)
|
||||
{
|
||||
}
|
||||
lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
|
||||
|
||||
// Send an event
|
||||
void push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3);
|
||||
@ -120,6 +116,10 @@ public:
|
||||
|
||||
struct lv2_event_port_t
|
||||
{
|
||||
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 u64 name; // passed as event source (generated from id and process id if not set)
|
||||
|
||||
|
@ -31,6 +31,10 @@ struct sys_event_flag_attribute_t
|
||||
|
||||
struct lv2_event_flag_t
|
||||
{
|
||||
static const u32 id_base = 0x98000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u32 protocol;
|
||||
const s32 type;
|
||||
const u64 name;
|
||||
|
@ -96,19 +96,18 @@ struct lv2_fs_mount_point;
|
||||
|
||||
struct lv2_fs_object
|
||||
{
|
||||
// ID Manager setups
|
||||
using id_base = lv2_fs_object;
|
||||
static const u32 id_base = 3;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 255 - id_base;
|
||||
|
||||
static constexpr u32 id_min = 3;
|
||||
static constexpr u32 id_max = 255;
|
||||
|
||||
const id_value<> id{};
|
||||
const u32 id;
|
||||
|
||||
// Mount Point
|
||||
const std::add_pointer_t<lv2_fs_mount_point> mp;
|
||||
|
||||
lv2_fs_object(lv2_fs_mount_point* mp)
|
||||
: mp(mp)
|
||||
, id(idm::last_id())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,14 @@
|
||||
|
||||
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)
|
||||
: thread(thread)
|
||||
, arg1(arg1)
|
||||
, arg2(arg2)
|
||||
, id(idm::last_id())
|
||||
{
|
||||
}
|
||||
|
||||
void lv2_int_serv_t::exec()
|
||||
{
|
||||
thread->cmd_list
|
||||
@ -149,3 +157,8 @@ void sys_interrupt_thread_eoi(ppu_thread& ppu) // Low-level PPU function example
|
||||
throw cpu_flag::ret;
|
||||
}
|
||||
}
|
||||
|
||||
lv2_int_tag_t::lv2_int_tag_t()
|
||||
: id(idm::last_id())
|
||||
{
|
||||
}
|
||||
|
@ -6,26 +6,31 @@ class ppu_thread;
|
||||
|
||||
struct lv2_int_tag_t
|
||||
{
|
||||
const id_value<> id{};
|
||||
static const u32 id_base = 0x1000a;
|
||||
static const u32 id_step = 0x10000;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u32 id;
|
||||
|
||||
std::shared_ptr<struct lv2_int_serv_t> handler;
|
||||
|
||||
lv2_int_tag_t();
|
||||
};
|
||||
|
||||
struct lv2_int_serv_t
|
||||
{
|
||||
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 id_value<> id{};
|
||||
const u32 id;
|
||||
|
||||
const u64 arg1;
|
||||
const u64 arg2;
|
||||
|
||||
lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2)
|
||||
: thread(thread)
|
||||
, arg1(arg1)
|
||||
, arg2(arg2)
|
||||
{
|
||||
}
|
||||
lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2);
|
||||
|
||||
void exec();
|
||||
void join(ppu_thread& ppu, lv2_lock_t);
|
||||
|
@ -19,6 +19,10 @@ struct sys_lwcond_t
|
||||
|
||||
struct lv2_lwcond_t
|
||||
{
|
||||
static const u32 id_base = 0x97000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u64 name;
|
||||
|
||||
sleep_queue<cpu_thread> sq;
|
||||
|
@ -46,6 +46,10 @@ struct sys_lwmutex_t
|
||||
|
||||
struct lv2_lwmutex_t
|
||||
{
|
||||
static const u32 id_base = 0x95000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u32 protocol;
|
||||
const u64 name;
|
||||
|
||||
|
@ -46,6 +46,10 @@ struct sys_page_attr_t
|
||||
|
||||
struct lv2_memory_container
|
||||
{
|
||||
static const u32 id_base = 0x1; // Wrong?
|
||||
static const u32 id_step = 0x1;
|
||||
static const u32 id_count = 16;
|
||||
|
||||
const u32 size = 0x10000000; // Amount of "physical" memory in this container
|
||||
|
||||
atomic_t<u32> used{}; // Amount of "physical" memory currently used
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
struct lv2_memory
|
||||
{
|
||||
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 align; // Alignment required
|
||||
const u64 flags;
|
||||
|
@ -21,6 +21,10 @@ struct sys_mutex_attribute_t
|
||||
|
||||
struct lv2_mutex_t
|
||||
{
|
||||
static const u32 id_base = 0x85000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const bool recursive;
|
||||
const u32 protocol;
|
||||
const u64 name;
|
||||
|
@ -229,3 +229,8 @@ s32 sys_prx_stop()
|
||||
sys_prx.todo("sys_prx_stop()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
lv2_prx_t::lv2_prx_t()
|
||||
: id(idm::last_id())
|
||||
{
|
||||
}
|
||||
|
@ -76,7 +76,11 @@ struct sys_prx_get_module_list_t
|
||||
|
||||
struct lv2_prx_t
|
||||
{
|
||||
const id_value<> id{};
|
||||
static const u32 id_base = 0x23000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u32 id;
|
||||
|
||||
bool is_started = false;
|
||||
|
||||
@ -86,6 +90,8 @@ struct lv2_prx_t
|
||||
vm::ptr<s32(int argc, vm::ptr<void> argv)> start = vm::null;
|
||||
vm::ptr<s32(int argc, vm::ptr<void> argv)> stop = vm::null;
|
||||
vm::ptr<s32()> exit = vm::null;
|
||||
|
||||
lv2_prx_t();
|
||||
};
|
||||
|
||||
// SysCalls
|
||||
|
@ -19,6 +19,10 @@ struct sys_rwlock_attribute_t
|
||||
|
||||
struct lv2_rwlock_t
|
||||
{
|
||||
static const u32 id_base = 0x88000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u64 name;
|
||||
const u32 protocol;
|
||||
|
||||
|
@ -19,6 +19,10 @@ struct sys_semaphore_attribute_t
|
||||
|
||||
struct lv2_sema_t
|
||||
{
|
||||
static const u32 id_base = 0x96000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const u32 protocol;
|
||||
const s32 max;
|
||||
const u64 name;
|
||||
|
@ -139,6 +139,10 @@ class SPUThread;
|
||||
|
||||
struct lv2_spu_group_t
|
||||
{
|
||||
static const u32 id_base = 1; // Wrong?
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
const std::string name;
|
||||
const u32 num; // SPU Number
|
||||
const s32 type; // SPU Thread Group Type
|
||||
|
@ -24,11 +24,15 @@ class lv2_timer_t final : public named_thread
|
||||
void on_task() override;
|
||||
|
||||
public:
|
||||
static const u32 id_base = 0x11000000;
|
||||
static const u32 id_step = 0x100;
|
||||
static const u32 id_count = 8192;
|
||||
|
||||
std::string get_name() const override;
|
||||
|
||||
void on_stop() override;
|
||||
|
||||
const id_value<> id{};
|
||||
const u32 id = idm::last_id();
|
||||
|
||||
atomic_t<u32> state{ SYS_TIMER_STATE_RUN }; // Timer state
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
#include "IdManager.h"
|
||||
|
||||
DECLARE(idm::g_map);
|
||||
DECLARE(idm::g_id);
|
||||
DECLARE(idm::g_mutex);
|
||||
shared_mutex id_manager::g_mutex;
|
||||
|
||||
DECLARE(fxm::g_map);
|
||||
DECLARE(fxm::g_mutex);
|
||||
thread_local DECLARE(idm::g_id);
|
||||
DECLARE(idm::g_map);
|
||||
DECLARE(fxm::g_vec);
|
||||
|
||||
std::vector<id_manager::typeinfo>& id_manager::typeinfo::access()
|
||||
{
|
||||
@ -24,20 +23,40 @@ u32 id_manager::typeinfo::add_type()
|
||||
return ::size32(list) - 1;
|
||||
}
|
||||
|
||||
id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 type, u32 min, u32 max)
|
||||
id_manager::id_map::pointer idm::allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count)
|
||||
{
|
||||
// Check all IDs starting from "next id"
|
||||
for (u32 i = 0; i <= max - min; i++)
|
||||
auto& map = g_map[types.first];
|
||||
|
||||
// Assume next ID
|
||||
u32 next = base;
|
||||
|
||||
if (std::size_t _count = map.size())
|
||||
{
|
||||
// Fix current ID (wrap around)
|
||||
if (g_id[tag] < min || g_id[tag] > max) g_id[tag] = min;
|
||||
|
||||
// Get ID
|
||||
const auto r = g_map[tag].emplace(id_manager::id_key{g_id[tag]++, type}, nullptr);
|
||||
|
||||
if (r.second)
|
||||
if (_count >= count)
|
||||
{
|
||||
return &*r.first;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const u32 _next = map.rbegin()->first.id() + step;
|
||||
|
||||
if (_next > base && _next < base + step * count)
|
||||
{
|
||||
next = _next;
|
||||
}
|
||||
}
|
||||
|
||||
// Check all IDs starting from "next id" (TODO)
|
||||
for (next; next < base + step * count; next += step)
|
||||
{
|
||||
// Get ID
|
||||
const auto result = map.emplace(id_manager::id_key(next, types.second), nullptr);
|
||||
|
||||
if (result.second)
|
||||
{
|
||||
// Acknowledge the ID
|
||||
g_id = next;
|
||||
|
||||
return std::addressof(*result.first);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,47 +64,61 @@ id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 type, u32 min, u32 max
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<void> idm::deallocate_id(u32 tag, u32 id)
|
||||
id_manager::id_map::pointer idm::find_id(u32 type, u32 id)
|
||||
{
|
||||
const auto found = g_map[tag].find(id);
|
||||
auto& map = g_map[type];
|
||||
|
||||
if (found == g_map[tag].end()) return nullptr;
|
||||
const auto found = map.find(id);
|
||||
|
||||
auto ptr = std::move(found->second);
|
||||
|
||||
g_map[tag].erase(found);
|
||||
|
||||
return ptr;
|
||||
return found == map.end() ? nullptr : std::addressof(*found);
|
||||
}
|
||||
|
||||
id_manager::id_map::pointer idm::find_id(u32 type, u32 true_type, u32 id)
|
||||
{
|
||||
const auto found = g_map[type].find(id);
|
||||
auto& map = g_map[type];
|
||||
|
||||
if (found == g_map[type].end()) return nullptr;
|
||||
const auto found = map.find(id);
|
||||
|
||||
if (true_type != get_type<void>() && found->first.type() != true_type) return nullptr;
|
||||
|
||||
return &*found;
|
||||
return found == map.end() || found->first.type() != true_type ? nullptr : std::addressof(*found);
|
||||
}
|
||||
|
||||
std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 tag, u32 id)
|
||||
std::shared_ptr<void> idm::delete_id(u32 type, u32 id)
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
auto& map = g_map[type];
|
||||
|
||||
if (!find_id(type, true_type, id)) return nullptr; // ???
|
||||
const auto found = map.find(id);
|
||||
|
||||
auto&& ptr = deallocate_id(tag, id);
|
||||
std::shared_ptr<void> result;
|
||||
|
||||
g_map[type].erase(id);
|
||||
if (found != map.end())
|
||||
{
|
||||
result = std::move(found->second);
|
||||
map.erase(found);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
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() && found->first.type() == true_type)
|
||||
{
|
||||
result = std::move(found->second);
|
||||
map.erase(found);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void idm::init()
|
||||
{
|
||||
g_map.resize(id_manager::typeinfo::get().size(), {});
|
||||
g_id.resize(id_manager::typeinfo::get().size(), 0);
|
||||
g_map.resize(id_manager::typeinfo::get().size());
|
||||
}
|
||||
|
||||
void idm::clear()
|
||||
@ -101,32 +134,24 @@ void idm::clear()
|
||||
}
|
||||
|
||||
g_map[i].clear();
|
||||
g_id[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<void> fxm::remove(u32 type)
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
|
||||
return std::move(g_map[type]);
|
||||
}
|
||||
|
||||
void fxm::init()
|
||||
{
|
||||
g_map.resize(id_manager::typeinfo::get().size(), {});
|
||||
g_vec.resize(id_manager::typeinfo::get().size(), {});
|
||||
}
|
||||
|
||||
void fxm::clear()
|
||||
{
|
||||
// Call recorded finalization functions for all IDs
|
||||
for (std::size_t i = 0; i < g_map.size(); i++)
|
||||
for (std::size_t i = 0; i < g_vec.size(); i++)
|
||||
{
|
||||
if (g_map[i])
|
||||
if (g_vec[i])
|
||||
{
|
||||
id_manager::typeinfo::get()[i].on_stop(g_map[i].get());
|
||||
id_manager::typeinfo::get()[i].on_stop(g_vec[i].get());
|
||||
}
|
||||
|
||||
g_map[i].reset();
|
||||
g_vec[i].reset();
|
||||
}
|
||||
}
|
||||
|
@ -5,28 +5,35 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
||||
// Mostly helper namespace
|
||||
// idm/fxm: helper namespace
|
||||
namespace id_manager
|
||||
{
|
||||
// Common global mutex
|
||||
extern shared_mutex g_mutex;
|
||||
|
||||
// Optional ID traits
|
||||
template<typename T, typename = void>
|
||||
struct id_traits
|
||||
{
|
||||
using tag = void;
|
||||
static_assert(sizeof(T) == 0, "ID object must specify: id_base, id_step, id_count");
|
||||
|
||||
static constexpr u32 min = 1;
|
||||
static constexpr u32 max = 0x7fffffff;
|
||||
static const u32 base = 1; // First ID (N = 0)
|
||||
static const u32 step = 1; // Any ID: N * id_step + id_base
|
||||
static const u32 count = 65535; // Limit: N < id_count
|
||||
static const u32 invalid = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct id_traits<T, void_t<typename T::id_base, decltype(&T::id_min), decltype(&T::id_max)>>
|
||||
struct id_traits<T, void_t<decltype(&T::id_base), decltype(&T::id_step), decltype(&T::id_count)>>
|
||||
{
|
||||
using tag = typename T::id_base;
|
||||
static const u32 base = T::id_base;
|
||||
static const u32 step = T::id_step;
|
||||
static const u32 count = T::id_count;
|
||||
static const u32 invalid = base > 0 ? 0 : -1;
|
||||
|
||||
static constexpr u32 min = T::id_min;
|
||||
static constexpr u32 max = T::id_max;
|
||||
static_assert(u64{step} * count + base < UINT32_MAX, "ID traits: invalid object range");
|
||||
};
|
||||
|
||||
// Optional object initialization function (called after ID registration)
|
||||
@ -136,69 +143,30 @@ namespace id_manager
|
||||
return m_type;
|
||||
}
|
||||
|
||||
bool operator ==(const id_key& rhs) const
|
||||
operator u32() const
|
||||
{
|
||||
return m_value == rhs.m_value;
|
||||
}
|
||||
|
||||
bool operator !=(const id_key& rhs) const
|
||||
{
|
||||
return m_value != rhs.m_value;
|
||||
return m_value;
|
||||
}
|
||||
};
|
||||
|
||||
// Custom hasher for ID values
|
||||
struct id_hash final
|
||||
{
|
||||
std::size_t operator ()(const id_key& key) const
|
||||
{
|
||||
return key.id();
|
||||
}
|
||||
};
|
||||
|
||||
using id_map = std::unordered_map<id_key, std::shared_ptr<void>, id_hash>;
|
||||
using id_map = std::map<id_key, std::shared_ptr<void>>;
|
||||
}
|
||||
|
||||
// Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs.
|
||||
class idm
|
||||
{
|
||||
// Rules for ID allocation:
|
||||
// 0) Individual ID counter may be specified for each type by defining 'using id_base = ...;'
|
||||
// 1) If no id_base specified, void is assumed.
|
||||
// 2) g_id[id_base] indicates next ID allocated in g_map.
|
||||
// 3) g_map[id_base] contains the additional copy of object pointer.
|
||||
|
||||
static shared_mutex g_mutex;
|
||||
// Last allocated ID for constructors
|
||||
static thread_local u32 g_id;
|
||||
|
||||
// Type Index -> ID -> Object. Use global since only one process is supported atm.
|
||||
static std::vector<id_manager::id_map> g_map;
|
||||
|
||||
// Next ID for each category
|
||||
static std::vector<u32> g_id;
|
||||
|
||||
template<typename T>
|
||||
static inline u32 get_type()
|
||||
{
|
||||
return id_manager::typeinfo::get_index<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline u32 get_tag()
|
||||
{
|
||||
return get_type<typename id_manager::id_traits<T>::tag>();
|
||||
}
|
||||
|
||||
// Update optional ID storage
|
||||
template<typename T>
|
||||
static inline auto set_id_value(T* ptr, u32 id) -> decltype(static_cast<void>(std::declval<T&>().id))
|
||||
{
|
||||
ptr->id = id;
|
||||
}
|
||||
|
||||
static inline void set_id_value(...)
|
||||
{
|
||||
}
|
||||
|
||||
// Helper
|
||||
template<typename F>
|
||||
struct function_traits;
|
||||
@ -262,35 +230,44 @@ class idm
|
||||
};
|
||||
|
||||
// Prepare new ID (returns nullptr if out of resources)
|
||||
static id_manager::id_map::pointer allocate_id(u32 tag, u32 type, u32 min, u32 max);
|
||||
static id_manager::id_map::pointer allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count);
|
||||
|
||||
// Deallocate ID, returns object
|
||||
static std::shared_ptr<void> deallocate_id(u32 tag, u32 id);
|
||||
// Remove ID and return the object
|
||||
static std::shared_ptr<void> delete_id(u32 type, u32 id);
|
||||
|
||||
// Remove ID and return the object (check type)
|
||||
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 id);
|
||||
|
||||
// Get ID
|
||||
static id_manager::id_map::pointer find_id(u32 type, u32 id);
|
||||
|
||||
// Get ID (check type)
|
||||
static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
|
||||
|
||||
// Allocate new ID and assign the object from the provider()
|
||||
template<typename T, typename Set, typename F>
|
||||
template<typename T, typename Type, typename F>
|
||||
static id_manager::id_map::pointer create_id(F&& provider)
|
||||
{
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
// Register destructors
|
||||
id_manager::typeinfo::update<T>();
|
||||
id_manager::typeinfo::update<typename id_manager::id_traits<T>::tag>();
|
||||
|
||||
writer_lock lock(g_mutex);
|
||||
// Type IDs
|
||||
std::pair<u32, u32> types(get_type<T>(), get_type<Type>());
|
||||
|
||||
if (auto place = allocate_id(get_tag<T>(), get_type<Set>(), id_manager::id_traits<T>::min, id_manager::id_traits<T>::max))
|
||||
// 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))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get object, store it
|
||||
place->second = provider();
|
||||
|
||||
// Update ID value if required
|
||||
set_id_value(static_cast<T*>(place->second.get()), place->first.id());
|
||||
|
||||
return &*g_map[get_type<T>()].emplace(*place).first;
|
||||
return place;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
deallocate_id(get_tag<T>(), place->first.id());
|
||||
delete_id(types.first, place->first.id());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -298,12 +275,6 @@ class idm
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get ID (internal)
|
||||
static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
|
||||
|
||||
// Remove ID and return the object
|
||||
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 tag, u32 id);
|
||||
|
||||
public:
|
||||
// Initialize object manager
|
||||
static void init();
|
||||
@ -311,6 +282,12 @@ public:
|
||||
// Remove all objects
|
||||
static void clear();
|
||||
|
||||
// Get last ID
|
||||
static inline u32 last_id()
|
||||
{
|
||||
return g_id;
|
||||
}
|
||||
|
||||
// Add a new ID of specified type with specified constructor arguments (returns object or nullptr)
|
||||
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)
|
||||
@ -336,7 +313,7 @@ public:
|
||||
return pair->first.id();
|
||||
}
|
||||
|
||||
fmt::throw_exception("Out of IDs ('%s')" HERE, typeid(T).name());
|
||||
return id_manager::id_traits<T>::invalid;
|
||||
}
|
||||
|
||||
// Add a new ID for an existing object provided (returns new id)
|
||||
@ -350,7 +327,7 @@ public:
|
||||
return pair->first.id();
|
||||
}
|
||||
|
||||
fmt::throw_exception("Out of IDs ('%s')" HERE, typeid(T).name());
|
||||
return id_manager::id_traits<T>::invalid;
|
||||
}
|
||||
|
||||
// Add a new ID for an object returned by provider()
|
||||
@ -368,21 +345,19 @@ public:
|
||||
}
|
||||
|
||||
// Check the ID
|
||||
template<typename T, typename Get = void>
|
||||
template<typename T, typename Get = T>
|
||||
static inline explicit_bool_t check(u32 id)
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
return find_id(get_type<T>(), get_type<Get>(), id) != nullptr;
|
||||
}
|
||||
|
||||
// Check the ID, access object under shared lock
|
||||
template<typename T, typename Get = void, 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)
|
||||
{
|
||||
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -391,17 +366,15 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
func(*static_cast<pointer_type*>(found->second.get()));
|
||||
func(*static_cast<Get*>(found->second.get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the ID, access object under reader lock, propagate return value
|
||||
template<typename T, typename Get = void, 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)
|
||||
{
|
||||
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -410,14 +383,14 @@ public:
|
||||
return {false};
|
||||
}
|
||||
|
||||
return {true, func(*static_cast<pointer_type*>(found->second.get()))};
|
||||
return {true, func(*static_cast<Get*>(found->second.get()))};
|
||||
}
|
||||
|
||||
// Get the object
|
||||
template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
|
||||
template<typename T, typename Get = T, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
|
||||
static inline std::shared_ptr<Made> get(u32 id)
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -430,13 +403,12 @@ public:
|
||||
}
|
||||
|
||||
// Get the object, access object under reader lock
|
||||
template<typename T, typename Get = void, 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)
|
||||
{
|
||||
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
|
||||
using result_type = std::shared_ptr<pointer_type>;
|
||||
using result_type = std::shared_ptr<Get>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -445,7 +417,7 @@ public:
|
||||
return result_type{nullptr};
|
||||
}
|
||||
|
||||
const auto ptr = static_cast<pointer_type*>(found->second.get());
|
||||
const auto ptr = static_cast<Get*>(found->second.get());
|
||||
|
||||
func(*ptr);
|
||||
|
||||
@ -453,13 +425,12 @@ public:
|
||||
}
|
||||
|
||||
// Get the object, access object under reader lock, propagate return value
|
||||
template<typename T, typename Get = void, 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)
|
||||
{
|
||||
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
|
||||
using result_type = return_pair<pointer_type, FRT>;
|
||||
using result_type = return_pair<Get, FRT>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -468,7 +439,7 @@ public:
|
||||
return result_type{nullptr};
|
||||
}
|
||||
|
||||
const auto ptr = static_cast<pointer_type*>(found->second.get());
|
||||
const auto ptr = static_cast<Get*>(found->second.get());
|
||||
|
||||
return result_type{{found->second, ptr}, func(*ptr)};
|
||||
}
|
||||
@ -477,7 +448,7 @@ public:
|
||||
template<typename... Types, 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)
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
u32 result = 0;
|
||||
|
||||
@ -500,7 +471,7 @@ public:
|
||||
using object_type = typename function_traits<FT>::object_type;
|
||||
using result_type = return_pair<object_type, FRT>;
|
||||
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
for (u32 type : { get_type<Types>()... })
|
||||
{
|
||||
@ -517,10 +488,10 @@ public:
|
||||
}
|
||||
|
||||
// Get count of objects
|
||||
template<typename T, typename Get = void>
|
||||
template<typename T, typename Get = T>
|
||||
static inline u32 get_count()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
if (std::is_void<Get>::value)
|
||||
{
|
||||
@ -541,10 +512,10 @@ public:
|
||||
}
|
||||
|
||||
// Remove the ID
|
||||
template<typename T, typename Get = void>
|
||||
template<typename T, typename Get = T>
|
||||
static inline explicit_bool_t remove(u32 id)
|
||||
{
|
||||
auto ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id);
|
||||
auto ptr = delete_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
if (LIKELY(ptr))
|
||||
{
|
||||
@ -555,29 +526,28 @@ public:
|
||||
}
|
||||
|
||||
// Remove the ID and return the object
|
||||
template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
|
||||
static inline std::shared_ptr<Made> withdraw(u32 id)
|
||||
template<typename T, typename Get = T>
|
||||
static inline std::shared_ptr<Get> withdraw(u32 id)
|
||||
{
|
||||
auto ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id);
|
||||
auto ptr = delete_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
if (LIKELY(ptr))
|
||||
{
|
||||
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
|
||||
}
|
||||
|
||||
return {ptr, static_cast<Made*>(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
|
||||
template<typename T, typename Get = void, 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 withdraw(u32 id, F&& func, int = 0)
|
||||
{
|
||||
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
|
||||
using result_type = std::shared_ptr<pointer_type>;
|
||||
using result_type = std::shared_ptr<Get>;
|
||||
|
||||
std::shared_ptr<void> ptr;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -586,29 +556,28 @@ public:
|
||||
return result_type{nullptr};
|
||||
}
|
||||
|
||||
func(*static_cast<pointer_type*>(found->second.get()));
|
||||
func(*static_cast<Get*>(found->second.get()));
|
||||
|
||||
ptr = deallocate_id(get_tag<T>(), id);
|
||||
ptr = delete_id(get_type<T>(), id);
|
||||
|
||||
g_map[get_type<T>()].erase(id);
|
||||
}
|
||||
|
||||
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
|
||||
|
||||
return result_type{ptr, static_cast<pointer_type*>(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
|
||||
template<typename T, typename Get = void, 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 withdraw(u32 id, F&& func)
|
||||
{
|
||||
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
|
||||
using result_type = return_pair<pointer_type, FRT>;
|
||||
using result_type = return_pair<Get, FRT>;
|
||||
|
||||
std::shared_ptr<void> ptr;
|
||||
FRT ret;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
|
||||
|
||||
@ -617,7 +586,7 @@ public:
|
||||
return result_type{nullptr};
|
||||
}
|
||||
|
||||
const auto _ptr = static_cast<pointer_type*>(found->second.get());
|
||||
const auto _ptr = static_cast<Get*>(found->second.get());
|
||||
|
||||
ret = func(*_ptr);
|
||||
|
||||
@ -626,14 +595,14 @@ public:
|
||||
return result_type{{found->second, _ptr}, std::move(ret)};
|
||||
}
|
||||
|
||||
ptr = deallocate_id(get_tag<T>(), id);
|
||||
ptr = delete_id(get_type<T>(), id);
|
||||
|
||||
g_map[get_type<T>()].erase(id);
|
||||
}
|
||||
|
||||
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
|
||||
|
||||
return result_type{{ptr, static_cast<pointer_type*>(ptr.get())}, std::move(ret)};
|
||||
return result_type{{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)};
|
||||
}
|
||||
};
|
||||
|
||||
@ -641,9 +610,7 @@ public:
|
||||
class fxm
|
||||
{
|
||||
// Type Index -> Object. Use global since only one process is supported atm.
|
||||
static std::vector<std::shared_ptr<void>> g_map;
|
||||
|
||||
static shared_mutex g_mutex;
|
||||
static std::vector<std::shared_ptr<void>> g_vec;
|
||||
|
||||
template<typename T>
|
||||
static inline u32 get_type()
|
||||
@ -651,8 +618,6 @@ class fxm
|
||||
return id_manager::typeinfo::get_index<T>();
|
||||
}
|
||||
|
||||
static std::shared_ptr<void> remove(u32 type);
|
||||
|
||||
public:
|
||||
// Initialize object manager
|
||||
static void init();
|
||||
@ -668,13 +633,13 @@ public:
|
||||
|
||||
std::shared_ptr<T> ptr;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
if (!g_map[get_type<T>()])
|
||||
if (!g_vec[get_type<T>()])
|
||||
{
|
||||
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
|
||||
|
||||
g_map[get_type<T>()] = ptr;
|
||||
g_vec[get_type<T>()] = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -696,12 +661,12 @@ public:
|
||||
std::shared_ptr<T> ptr;
|
||||
std::shared_ptr<void> old;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
old = std::move(g_map[get_type<T>()]);
|
||||
old = std::move(g_vec[get_type<T>()]);
|
||||
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
|
||||
|
||||
g_map[get_type<T>()] = ptr;
|
||||
g_vec[get_type<T>()] = ptr;
|
||||
}
|
||||
|
||||
if (old)
|
||||
@ -721,13 +686,13 @@ public:
|
||||
|
||||
std::shared_ptr<T> ptr;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
if (!g_map[get_type<T>()])
|
||||
if (!g_vec[get_type<T>()])
|
||||
{
|
||||
ptr = provider();
|
||||
|
||||
g_map[get_type<T>()] = ptr;
|
||||
g_vec[get_type<T>()] = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,12 +714,12 @@ public:
|
||||
std::shared_ptr<T> ptr;
|
||||
std::shared_ptr<void> old;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
old = std::move(g_map[get_type<T>()]);
|
||||
old = std::move(g_vec[get_type<T>()]);
|
||||
ptr = provider();
|
||||
|
||||
g_map[get_type<T>()] = ptr;
|
||||
g_vec[get_type<T>()] = ptr;
|
||||
}
|
||||
|
||||
if (old)
|
||||
@ -774,9 +739,9 @@ public:
|
||||
|
||||
std::shared_ptr<T> ptr;
|
||||
{
|
||||
writer_lock lock(g_mutex);
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
|
||||
if (auto& value = g_map[get_type<T>()])
|
||||
if (auto& value = g_vec[get_type<T>()])
|
||||
{
|
||||
return{ value, static_cast<T*>(value.get()) };
|
||||
}
|
||||
@ -784,7 +749,7 @@ public:
|
||||
{
|
||||
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
|
||||
|
||||
g_map[get_type<T>()] = ptr;
|
||||
g_vec[get_type<T>()] = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -797,18 +762,18 @@ public:
|
||||
template<typename T>
|
||||
static inline explicit_bool_t check()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
return g_map[get_type<T>()].operator bool();
|
||||
return g_vec[get_type<T>()].operator bool();
|
||||
}
|
||||
|
||||
// Get the object (returns nullptr if it doesn't exist)
|
||||
template<typename T>
|
||||
static inline std::shared_ptr<T> get()
|
||||
{
|
||||
reader_lock lock(g_mutex);
|
||||
reader_lock lock(id_manager::g_mutex);
|
||||
|
||||
auto& ptr = g_map[get_type<T>()];
|
||||
auto& ptr = g_vec[get_type<T>()];
|
||||
|
||||
return{ ptr, static_cast<T*>(ptr.get()) };
|
||||
}
|
||||
@ -817,7 +782,11 @@ public:
|
||||
template<typename T>
|
||||
static inline explicit_bool_t remove()
|
||||
{
|
||||
auto ptr = remove(get_type<T>());
|
||||
std::shared_ptr<void> ptr;
|
||||
{
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
ptr = std::move(g_vec[get_type<T>()]);
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
@ -831,7 +800,11 @@ public:
|
||||
template<typename T>
|
||||
static inline std::shared_ptr<T> withdraw()
|
||||
{
|
||||
auto ptr = remove(get_type<T>());
|
||||
std::shared_ptr<void> ptr;
|
||||
{
|
||||
writer_lock lock(id_manager::g_mutex);
|
||||
ptr = std::move(g_vec[get_type<T>()]);
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "ARMv7Thread.h"
|
||||
@ -94,7 +95,7 @@ ARMv7Thread::~ARMv7Thread()
|
||||
}
|
||||
|
||||
ARMv7Thread::ARMv7Thread(const std::string& name, u32 prio, u32 stack)
|
||||
: cpu_thread()
|
||||
: cpu_thread(idm::last_id())
|
||||
, m_name(name)
|
||||
, prio(prio)
|
||||
, stack_addr(vm::alloc(stack, vm::main))
|
||||
|
@ -14,6 +14,10 @@ enum ARMv7InstructionSet
|
||||
class ARMv7Thread final : public cpu_thread
|
||||
{
|
||||
public:
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 2;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
virtual std::string get_name() const override;
|
||||
virtual std::string dump() const override;
|
||||
virtual void cpu_task() override;
|
||||
|
@ -808,6 +808,10 @@ s32 sceKernelWaitMultipleEventsCB(vm::ptr<SceKernelWaitEvent> pWaitEventList, s3
|
||||
|
||||
struct psp2_event_flag final
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
struct alignas(8) ctrl_t
|
||||
{
|
||||
u32 waiters;
|
||||
|
@ -496,6 +496,10 @@ struct SceKernelSemaInfo
|
||||
|
||||
struct psp2_semaphore
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const std::string name; // IPC Name
|
||||
|
||||
atomic_t<u32> ref{}; // IPC Ref Counter
|
||||
@ -536,6 +540,10 @@ struct SceKernelMutexInfo
|
||||
|
||||
struct psp2_mutex
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const std::string name; // IPC Name
|
||||
|
||||
atomic_t<u32> ref{}; // IPC Ref Counter
|
||||
@ -596,6 +604,10 @@ struct SceKernelCondInfo
|
||||
|
||||
struct psp2_cond
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32767;
|
||||
|
||||
const std::string name; // IPC Name
|
||||
|
||||
atomic_t<u32> ref{}; // IPC Ref Counter
|
||||
|
@ -481,7 +481,7 @@ s32 error_code::error_report(const fmt_type_info* sup, u64 arg)
|
||||
|
||||
if (auto thread = get_current_cpu_thread())
|
||||
{
|
||||
if (g_system == system_type::ps3 && thread->id >= ppu_thread::id_min)
|
||||
if (g_system == system_type::ps3 && thread->id_type() == 1)
|
||||
{
|
||||
if (auto func = static_cast<ppu_thread*>(thread)->last_function)
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_t
|
||||
s_panel_margin_x->Add(s_panel_margin_y);
|
||||
s_panel_margin_x->AddSpacer(12);
|
||||
|
||||
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast<SPUThread&>(*cpu).offset : 0;
|
||||
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
|
||||
|
||||
this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview));
|
||||
t2_instr->SetValue(wxString::Format("%08x", vm::ps3::read32(cpu_offset + pc).value()));
|
||||
|
@ -25,7 +25,7 @@ u32 InterpreterDisAsmFrame::GetPc() const
|
||||
{
|
||||
switch (g_system)
|
||||
{
|
||||
case system_type::ps3: return cpu->id >= ppu_thread::id_min ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc;
|
||||
case system_type::ps3: return cpu->id_type() == 1 ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc;
|
||||
case system_type::psv: return static_cast<ARMv7Thread*>(cpu)->PC;
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
|
||||
{
|
||||
case system_type::ps3:
|
||||
{
|
||||
if (cpu->id >= ppu_thread::id_min)
|
||||
if (cpu->id_type() == 1)
|
||||
{
|
||||
m_disasm = std::make_unique<PPUDisAsm>(CPUDisAsm_InterpreterMode);
|
||||
}
|
||||
@ -250,7 +250,7 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast<SPUThread&>(*cpu).offset : 0;
|
||||
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
|
||||
m_disasm->offset = (u8*)vm::base(cpu_offset);
|
||||
for (uint i = 0, count = 4; i<m_item_count; ++i, m_pc += count)
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
|
||||
{
|
||||
case system_type::ps3:
|
||||
{
|
||||
if (_cpu->id >= ppu_thread::id_min)
|
||||
if (_cpu->id_type() == 1)
|
||||
{
|
||||
for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("GPR[%d]", i));
|
||||
for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("FPR[%d]", i));
|
||||
@ -89,7 +89,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
|
||||
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
|
||||
std::string value = fmt::ToUTF8(t2_value->GetValue());
|
||||
|
||||
if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min)
|
||||
if (g_system == system_type::ps3 && cpu->id_type() == 1)
|
||||
{
|
||||
auto& ppu = *static_cast<ppu_thread*>(cpu);
|
||||
|
||||
@ -134,7 +134,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
|
||||
{
|
||||
}
|
||||
}
|
||||
else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min)
|
||||
else if (g_system == system_type::ps3 && cpu->id_type() != 1)
|
||||
{
|
||||
auto& spu = *static_cast<SPUThread*>(cpu);
|
||||
|
||||
@ -169,7 +169,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
|
||||
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
|
||||
std::string str;
|
||||
|
||||
if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min)
|
||||
if (g_system == system_type::ps3 && cpu->id_type() == 1)
|
||||
{
|
||||
auto& ppu = *static_cast<ppu_thread*>(cpu);
|
||||
|
||||
@ -185,7 +185,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
|
||||
if (reg == "LR") str = fmt::format("%016llx", ppu.lr);
|
||||
if (reg == "CTR") str = fmt::format("%016llx", ppu.ctr);
|
||||
}
|
||||
else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min)
|
||||
else if (g_system == system_type::ps3 && cpu->id_type() != 1)
|
||||
{
|
||||
auto& spu = *static_cast<SPUThread*>(cpu);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user