diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index a97c5a0914..ad0c7300c7 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1449,19 +1449,17 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no u64 data1 = addr; u64 data2 = 0; - if (cpu->id_type() == 1) + if (cpu->try_get()) { data2 = (SYS_MEMORY_PAGE_FAULT_TYPE_PPU_THREAD << 32) | cpu->id; } - else if (cpu->id_type() == 2) + else if (auto spu = cpu->try_get()) { - const auto& spu = static_cast(*cpu); - - const u64 type = spu.get_type() == spu_type::threaded ? + const u64 type = spu->get_type() == spu_type::threaded ? SYS_MEMORY_PAGE_FAULT_TYPE_SPU_THREAD : SYS_MEMORY_PAGE_FAULT_TYPE_RAW_SPU; - data2 = (type << 32) | spu.lv2_id; + data2 = (type << 32) | spu->lv2_id; } u64 data3; diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index f85b9c13dc..98ae1036d1 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -5,6 +5,10 @@ #include +template +concept derived_from = std::is_base_of_v && + std::is_convertible_v; + // Thread state flags enum class cpu_flag : u32 { @@ -107,6 +111,30 @@ public: return id >> 24; } + template T> + T* try_get() + { + if constexpr (std::is_same_v, cpu_thread>) + { + return this; + } + else + { + if (id_type() == (T::id_base >> 24)) + { + return static_cast(this); + } + + return nullptr; + } + } + + template T> + const T* try_get() const + { + return const_cast(this)->try_get(); + } + u32 get_pc() const; u32* get_pc2(); // Last PC before stepping for the debugger (may be null) @@ -244,15 +272,25 @@ public: // Send signal to the profiler(s) to flush results static void flush_profilers() noexcept; + template T = cpu_thread> + static inline T* get_current() noexcept + { + if (const auto cpu = g_tls_this_thread) + { + return cpu->try_get(); + } + + return nullptr; + } + private: static thread_local cpu_thread* g_tls_this_thread; - - friend cpu_thread* get_current_cpu_thread() noexcept; }; -inline cpu_thread* get_current_cpu_thread() noexcept +template T = cpu_thread> +inline T* get_current_cpu_thread() noexcept { - return cpu_thread::g_tls_this_thread; + return cpu_thread::get_current(); } class ppu_thread; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 890fc85a47..09f611423b 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1273,7 +1273,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_type() == 1) + if (auto cpu = get_current_cpu_thread()) { ppu_thread& context = static_cast(*cpu); @@ -1299,7 +1299,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_type() == 1) + if (auto cpu = get_current_cpu_thread()) { ppu_thread& context = static_cast(*cpu); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 3dc07ce8ed..3fbf766deb 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2041,10 +2041,10 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8* continue; } - const auto cpu = static_cast(get_current_cpu_thread()); + const auto cpu = get_current_cpu_thread(); alignas(64) u8 temp[128]; - u8* dst0 = cpu && cpu->id_type() != 1 && (eal & -128) == cpu->raddr ? temp : dst; + u8* dst0 = cpu && (eal & -128) == cpu->raddr ? temp : dst; if (dst0 == +temp && time0 != cpu->rtime) { diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 3770b612d1..1a0c8228b8 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -1143,7 +1143,7 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout) { const u64 start_time = get_guest_system_time(); - if (auto ppu = static_cast(thread.id_type() == 1 ? &thread : nullptr)) + if (auto ppu = thread.try_get()) { ppu_log.trace("sleep() - waiting (%zu)", g_pending.size()); diff --git a/rpcs3/Emu/GDB.cpp b/rpcs3/Emu/GDB.cpp index c7b9805265..a0b3a8401e 100644 --- a/rpcs3/Emu/GDB.cpp +++ b/rpcs3/Emu/GDB.cpp @@ -565,8 +565,8 @@ bool gdb_thread::cmd_read_register(gdb_cmd& cmd) return send_cmd_ack("E02"); } auto th = selected_thread.lock(); - if (th->id_type() == 1) { - auto ppu = static_cast*>(th.get()); + if (auto ppu = th->try_get>()) + { u32 rid = hex_to_u32(cmd.data); std::string result = get_reg(ppu, rid); if (result.empty()) { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index e60a97f823..b1d2f60d92 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -658,6 +658,8 @@ namespace rsx std::string dump_regs() const override; void cpu_wait(bs_t old) override; + static constexpr u32 id_base = 0x5555'5555; // See get_current_cpu_thread() + // Performance approximation counters struct { diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index f059a4c4d6..be0dd5783c 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1666,16 +1666,11 @@ s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* s logs::channel* channel = &sys_log; const char* func = "Unknown function"; - if (auto thread = get_current_cpu_thread()) + if (auto ppu = get_current_cpu_thread()) { - if (thread->id_type() == 1) + if (ppu->current_function) { - auto& ppu = static_cast(*thread); - - if (ppu.current_function) - { - func = ppu.current_function; - } + func = ppu->current_function; } }