From ad79711d1875e354533a48c741a4445b9b098819 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 9 Jan 2026 01:41:15 +0000 Subject: [PATCH] [core/hle/kernel] coalesce TLS from KernelCore to reduce query times Signed-off-by: lizzie --- src/core/hle/kernel/kernel.cpp | 64 +++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1889ed9938..b7c4a522cf 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -50,13 +50,26 @@ namespace Kernel { +// Can only be used by a single implementation PER THREAD +static thread_local struct ThreadLocalData { + std::optional raw_thread; + KThread* current_thread = nullptr; + KThread* thread = nullptr; + u8 host_thread_id = UINT8_MAX; + bool is_phantom_mode_for_singlecore = false; + bool lock = false; +} static_tls_data = {}; + struct KernelCore::Impl { static constexpr size_t ApplicationMemoryBlockSlabHeapSize = 20000; static constexpr size_t SystemMemoryBlockSlabHeapSize = 10000; static constexpr size_t BlockInfoSlabHeapSize = 4000; static constexpr size_t ReservedDynamicPageCount = 64; - explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_} {} + explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_}, tls_data{static_tls_data} { + ASSERT(tls_data.lock == false); + tls_data.lock = true; + } void SetMulticore(bool is_multi) { is_multicore = is_multi; @@ -69,8 +82,6 @@ struct KernelCore::Impl { global_object_list_container = std::make_unique(kernel); global_scheduler_context = std::make_unique(kernel); - is_phantom_mode_for_singlecore = false; - // Derive the initial memory layout from the emulated board Init::InitializeSlabResourceCounts(kernel); DeriveInitialMemoryLayout(); @@ -356,33 +367,34 @@ struct KernelCore::Impl { application_process->Open(); } - static inline thread_local u8 host_thread_id = UINT8_MAX; - /// Sets the host thread ID for the caller. u32 SetHostThreadId(std::size_t core_id) { // This should only be called during core init. - ASSERT(host_thread_id == UINT8_MAX); + ASSERT(tls_data.host_thread_id == UINT8_MAX); // The first four slots are reserved for CPU core threads ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); - host_thread_id = static_cast(core_id); - return host_thread_id; + tls_data.host_thread_id = u8(core_id); + return tls_data.host_thread_id; } /// Gets the host thread ID for the caller u32 GetHostThreadId() const { - return host_thread_id; + return tls_data.host_thread_id; } // Gets the dummy KThread for the caller, allocating a new one if this is the first time KThread* GetHostDummyThread(KThread* existing_thread) { - const auto initialize{[](KThread* thread) { - ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); - return thread; - }}; - thread_local KThread raw_thread{system.Kernel()}; - thread_local KThread* thread = existing_thread ? existing_thread : initialize(&raw_thread); - return thread; + if (tls_data.thread == nullptr) { + auto const initialize{[](KThread* thread) { + ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); + return thread; + }}; + tls_data.raw_thread.emplace(system.Kernel()); + tls_data.thread = existing_thread ? existing_thread : initialize(&*tls_data.raw_thread); + ASSERT(tls_data.thread != nullptr); + } + return tls_data.thread; } /// Registers a CPU core thread by allocating a host thread ID for it @@ -407,32 +419,26 @@ struct KernelCore::Impl { return this_id; } - static inline thread_local bool is_phantom_mode_for_singlecore{false}; - + // Forces singlecore bool IsPhantomModeForSingleCore() const { - return is_phantom_mode_for_singlecore; + return tls_data.is_phantom_mode_for_singlecore; } - void SetIsPhantomModeForSingleCore(bool value) { ASSERT(!is_multicore); - is_phantom_mode_for_singlecore = value; + tls_data.is_phantom_mode_for_singlecore = value; } bool IsShuttingDown() const { return is_shutting_down.load(std::memory_order_relaxed); } - static inline thread_local KThread* current_thread{nullptr}; - KThread* GetCurrentEmuThread() { - if (!current_thread) { - current_thread = GetHostDummyThread(nullptr); - } - return current_thread; + auto *ct = tls_data.current_thread; // Must read to avoid uneeded %fs: reloads + return ct ? ct : (tls_data.current_thread = GetHostDummyThread(nullptr)); } void SetCurrentEmuThread(KThread* thread) { - current_thread = thread; + tls_data.current_thread = thread; } void DeriveInitialMemoryLayout() { @@ -845,6 +851,8 @@ struct KernelCore::Impl { // System context Core::System& system; + // You must use references otherwise atexit() will be spammed everywhere :) + ThreadLocalData& tls_data; }; KernelCore::KernelCore(Core::System& system) : impl{std::make_unique(system, *this)} {}