From b83dd97762e402e046baa786fd572329ae7a3385 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 24 Aug 2026 18:13:29 -0700 Subject: [PATCH] FEXCore/Context: Removes InitialRIP/RSP from CreateThread We actually never use this anymore, we instead always pass zero for both, and then rely on the thread inheritance model or setting the values manually. Now that we expose visibility of the InternalThreadState to the frontend they just access it directly. Just a smidge of cleanup, NFC. --- FEXCore/Source/Interface/Context/Context.h | 16 ++++++++-------- FEXCore/Source/Interface/Core/CodeCache.cpp | 2 +- FEXCore/Source/Interface/Core/Core.cpp | 6 +----- FEXCore/include/FEXCore/Core/Context.h | 5 +---- Source/Tools/CodeSizeValidation/Main.cpp | 2 +- Source/Tools/FEXInterpreter/AOT/AOTGenerator.cpp | 2 +- Source/Tools/FEXInterpreter/FEXInterpreter.cpp | 2 +- Source/Tools/FEXOfflineCompiler/Main.cpp | 2 +- .../LinuxSyscalls/Syscalls/Thread.cpp | 4 ++-- .../LinuxSyscalls/ThreadManager.cpp | 6 +++--- .../LinuxEmulation/LinuxSyscalls/ThreadManager.h | 4 ++-- .../TestHarnessRunner/TestHarnessRunner.cpp | 5 +++-- Source/Windows/ARM64EC/Module.cpp | 2 +- Source/Windows/WOW64/Module.cpp | 2 +- 14 files changed, 27 insertions(+), 33 deletions(-) diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index 166b0ee8c..df8e8716a 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -155,32 +155,32 @@ public: void SetXMMRegistersFromState(FEXCore::Core::InternalThreadState* Thread, const __uint128_t* XMM_Low, const __uint128_t* YMM_High) override; /** - * @brief Used to create FEX thread objects in preparation for creating a true OS thread. Does set a TID or PID. + * @brief Used to create FEX thread objects in preparation for creating a true OS thread. * - * @param InitialRIP The starting RIP of this thread - * @param StackPointer The starting RSP of this thread * @param NewThreadState The initial thread state to setup for our state, if inheriting. * * @return The InternalThreadState object that tracks all of the emulated thread's state * * Usecases: * Parent thread Creation: - * - Thread = CreateThread(InitialRIP, InitialStack, nullptr, 0); + * - Thread = CreateThread(); + * - Thread->CurrentFrame->State.rip = InitialRIP; + * - Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP] = InitialStack; * - CTX->ExecuteThread(Thread); * OS thread Creation: - * - Thread = CreateThread(0, 0, NewState, PPID); + * - Thread = CreateThread(NewState); * - Thread->ExecutionThread = FEXCore::Threads::Thread::Create(ThreadHandler, Arg); * - ThreadHandler calls `CTX->ExecuteThread(Thread)` * OS fork (New thread created with a clone of thread state): * - clone{2, 3} - * - Thread = CreateThread(0, 0, CopyOfThreadState, PPID); + * - Thread = CreateThread(CopyOfThreadState); * - ExecuteThread(Thread); // Starts executing without creating another host thread * Thunk callback executing guest code from native host thread - * - Thread = CreateThread(0, 0, NewState, PPID); + * - Thread = CreateThread(NewState); * - HandleCallback(Thread, RIP); */ - FEXCore::Core::InternalThreadState* CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState) override; + FEXCore::Core::InternalThreadState* CreateThread(const FEXCore::Core::CPUState* NewThreadState) override; /** * @brief Destroys this FEX thread object and stops tracking it internally diff --git a/FEXCore/Source/Interface/Core/CodeCache.cpp b/FEXCore/Source/Interface/Core/CodeCache.cpp index e7b46ae82..8c32e5ae3 100644 --- a/FEXCore/Source/Interface/Core/CodeCache.cpp +++ b/FEXCore/Source/Interface/Core/CodeCache.cpp @@ -406,7 +406,7 @@ void CodeCache::Validate(const ExecutableFileSectionInfo& Section, fextl::setCreateThread(0, 0, nullptr)); + ValidationThread.reset(ValidationCTX->CreateThread(nullptr)); auto Frame = ValidationThread->CurrentFrame; Frame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT] = &ValidationGDT[0]; diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 0e363d6ea..e05d84930 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -414,16 +414,12 @@ void ContextImpl::InitializeCompiler(FEXCore::Core::InternalThreadState* Thread) Thread->PassManager->Finalize(); } -FEXCore::Core::InternalThreadState* -ContextImpl::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState) { +FEXCore::Core::InternalThreadState* ContextImpl::CreateThread(const FEXCore::Core::CPUState* NewThreadState) { FEXCore::Core::InternalThreadState* Thread = new FEXCore::Core::InternalThreadState { .CTX = this, }; FEXCore::Allocator::VirtualName("FEXMem_ThreadState", Thread, sizeof(*Thread)); - Thread->CurrentFrame->State.gregs[X86State::REG_RSP] = StackPointer; - Thread->CurrentFrame->State.rip = InitialRIP; - // Copy over the new thread state to the new object if (NewThreadState) { memcpy(&Thread->CurrentFrame->State, NewThreadState, sizeof(FEXCore::Core::CPUState)); diff --git a/FEXCore/include/FEXCore/Core/Context.h b/FEXCore/include/FEXCore/Core/Context.h index 66dd0377a..8aa448e2e 100644 --- a/FEXCore/include/FEXCore/Core/Context.h +++ b/FEXCore/include/FEXCore/Core/Context.h @@ -113,15 +113,12 @@ public: * @brief Create a new thread object that doesn't inherit any state. * Used to create FEX thread objects in preparation for creating a true OS thread. * - * @param InitialRIP The starting RIP of this thread - * @param StackPointer The starting RSP of this thread * @param NewThreadState The thread state to inherit from if not nullptr. * * @return A new InternalThreadState object for using with a new guest thread. */ - FEX_DEFAULT_VISIBILITY virtual FEXCore::Core::InternalThreadState* - CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState = nullptr) = 0; + FEX_DEFAULT_VISIBILITY virtual FEXCore::Core::InternalThreadState* CreateThread(const FEXCore::Core::CPUState* NewThreadState = nullptr) = 0; FEX_DEFAULT_VISIBILITY virtual void DestroyThread(FEXCore::Core::InternalThreadState* Thread) = 0; #ifndef _WIN32 diff --git a/Source/Tools/CodeSizeValidation/Main.cpp b/Source/Tools/CodeSizeValidation/Main.cpp index 1232bf9e4..75360042c 100644 --- a/Source/Tools/CodeSizeValidation/Main.cpp +++ b/Source/Tools/CodeSizeValidation/Main.cpp @@ -660,7 +660,7 @@ int main(int argc, char** argv, char** const envp) { if (!CTX->InitCore()) { return -1; } - auto ParentThread = CTX->CreateThread(0, 0); + auto ParentThread = CTX->CreateThread(); // GDT data FEXCore::Core::CPUState::gdt_segment gdt[32] {}; diff --git a/Source/Tools/FEXInterpreter/AOT/AOTGenerator.cpp b/Source/Tools/FEXInterpreter/AOT/AOTGenerator.cpp index 32dba1239..f5d47b6e2 100644 --- a/Source/Tools/FEXInterpreter/AOT/AOTGenerator.cpp +++ b/Source/Tools/FEXInterpreter/AOT/AOTGenerator.cpp @@ -111,7 +111,7 @@ void AOTGenSection(FEXCore::Context::Context* CTX, ELFCodeLoader::LoadedSection& setpriority(PRIO_PROCESS, FHU::Syscalls::gettid(), 19); // Setup thread - Each compilation thread uses its own backing FEX thread - auto Thread = CTX->CreateThread(0, 0); + auto Thread = CTX->CreateThread(); fextl::set ExternalBranchesLocal; CTX->ConfigureAOTGen(Thread, &ExternalBranchesLocal, SectionMaxAddress); diff --git a/Source/Tools/FEXInterpreter/FEXInterpreter.cpp b/Source/Tools/FEXInterpreter/FEXInterpreter.cpp index 527abab27..6bbfa02b1 100644 --- a/Source/Tools/FEXInterpreter/FEXInterpreter.cpp +++ b/Source/Tools/FEXInterpreter/FEXInterpreter.cpp @@ -573,7 +573,7 @@ int main(int argc, char** argv, char** const envp) { } // Create a thread without a RIP or stack pointer setup initially. - auto ParentThread = SyscallHandler->TM.CreateThread(0, 0); + auto ParentThread = SyscallHandler->TM.CreateThread(); SyscallHandler->TM.TrackThread(ParentThread); SignalDelegation->RegisterTLSState(ParentThread); ThunkHandler->RegisterTLSState(ParentThread); diff --git a/Source/Tools/FEXOfflineCompiler/Main.cpp b/Source/Tools/FEXOfflineCompiler/Main.cpp index 3f8d7414b..0c344dc91 100644 --- a/Source/Tools/FEXOfflineCompiler/Main.cpp +++ b/Source/Tools/FEXOfflineCompiler/Main.cpp @@ -173,7 +173,7 @@ static constexpr size_t DefaultCS {4}; #endif static FEXCore::Core::InternalThreadState* SetupCompileThread(FEXCore::Context::Context& CTX, bool Is64Bit) { - auto Thread = CTX.CreateThread(0, 0); + auto Thread = CTX.CreateThread(); auto Frame = Thread->CurrentFrame; Frame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT] = &gdt[0]; diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp index 4de7632c7..0a51b98a3 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp @@ -89,7 +89,7 @@ static void* ThreadHandler(void* Data) { FEX::HLE::ThreadStateObject* CreateNewThread(FEXCore::Context::Context* CTX, FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::clone3_args* args) { uint64_t flags = args->args.flags; - auto NewThread = FEX::HLE::_SyscallHandler->TM.CreateThread(0, 0, &Frame->State, args->args.parent_tid, + auto NewThread = FEX::HLE::_SyscallHandler->TM.CreateThread(&Frame->State, args->args.parent_tid, FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame)); NewThread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RAX] = 0; @@ -185,7 +185,7 @@ uint64_t HandleNewClone(FEX::HLE::ThreadStateObject* Thread, FEXCore::Context::C if (flags & CLONE_THREAD) { // Overwrite thread - Thread = FEX::HLE::_SyscallHandler->TM.CreateThread(0, 0, &Frame->State, GuestArgs->parent_tid, + Thread = FEX::HLE::_SyscallHandler->TM.CreateThread(&Frame->State, GuestArgs->parent_tid, FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame)); Thread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RAX] = 0; diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp index b9906f025..69e10b3d2 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp @@ -169,8 +169,8 @@ void ThreadManager::SetThreadName(const char* name) { constexpr size_t CALLRET_STACK_ALLOC_SIZE = FEXCore::Core::InternalThreadState::CALLRET_STACK_SIZE + 2 * FEXCore::Utils::FEX_PAGE_SIZE; -FEX::HLE::ThreadStateObject* ThreadManager::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState, - uint64_t ParentTID, FEX::HLE::ThreadStateObject* InheritThread) { +FEX::HLE::ThreadStateObject* +ThreadManager::CreateThread(const FEXCore::Core::CPUState* NewThreadState, uint64_t ParentTID, FEX::HLE::ThreadStateObject* InheritThread) { auto ThreadStateObject = new FEX::HLE::ThreadStateObject; ThreadStateObject->ThreadInfo.parent_tid = ParentTID; @@ -178,7 +178,7 @@ FEX::HLE::ThreadStateObject* ThreadManager::CreateThread(uint64_t InitialRIP, ui ThreadStateObject->ThreadInfo.TID = FHU::Syscalls::gettid(); - ThreadStateObject->Thread = CTX->CreateThread(InitialRIP, StackPointer, NewThreadState); + ThreadStateObject->Thread = CTX->CreateThread(NewThreadState); auto Frame = ThreadStateObject->Thread->CurrentFrame; // Allocate the call-ret stack with guard pages on both sides diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h index 6371b8fb5..dfcd4b0eb 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h @@ -186,8 +186,8 @@ public: return static_cast(Thread->FrontendPtr); } - FEX::HLE::ThreadStateObject* CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState = nullptr, - uint64_t ParentTID = 0, FEX::HLE::ThreadStateObject* InheritThread = nullptr); + FEX::HLE::ThreadStateObject* CreateThread(const FEXCore::Core::CPUState* NewThreadState = nullptr, uint64_t ParentTID = 0, + FEX::HLE::ThreadStateObject* InheritThread = nullptr); void TrackThread(FEX::HLE::ThreadStateObject* Thread) { std::lock_guard lk(ThreadCreationMutex); Threads.emplace_back(Thread); diff --git a/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp b/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp index 203225870..4cda1815a 100644 --- a/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp +++ b/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp @@ -343,7 +343,8 @@ int main(int argc, char** argv, char** const envp) { return -ENOEXEC; } - auto ParentThread = SyscallHandler->TM.CreateThread(Loader.DefaultRIP(), 0); + auto ParentThread = SyscallHandler->TM.CreateThread(); + ParentThread->Thread->CurrentFrame->State.rip = Loader.DefaultRIP(); SyscallHandler->TM.TrackThread(ParentThread); SignalDelegation->RegisterTLSState(ParentThread); @@ -379,7 +380,7 @@ int main(int argc, char** argv, char** const envp) { else { // Run as host SupportsAVX = true; - auto ParentThread = SyscallHandler->TM.CreateThread(Loader.DefaultRIP(), 0); + auto ParentThread = SyscallHandler->TM.CreateThread(); SyscallHandler->TM.TrackThread(ParentThread); SignalDelegation->RegisterTLSState(ParentThread); diff --git a/Source/Windows/ARM64EC/Module.cpp b/Source/Windows/ARM64EC/Module.cpp index 234489a7b..0d132e939 100644 --- a/Source/Windows/ARM64EC/Module.cpp +++ b/Source/Windows/ARM64EC/Module.cpp @@ -922,7 +922,7 @@ NTSTATUS ThreadInit() { CPUArea.EmulatorStackLimit() = EmulatorStack; CPUArea.EmulatorStackBase() = EmulatorStack + EmulatorStackSize; - auto* Thread = CTX->CreateThread(0, 0); + auto* Thread = CTX->CreateThread(); // Default segment setup. auto Frame = Thread->CurrentFrame; diff --git a/Source/Windows/WOW64/Module.cpp b/Source/Windows/WOW64/Module.cpp index 2061bf061..6ef2c3f0a 100644 --- a/Source/Windows/WOW64/Module.cpp +++ b/Source/Windows/WOW64/Module.cpp @@ -598,7 +598,7 @@ void BTCpuThreadInit() { static constexpr size_t DefaultWow64CS {4}; std::scoped_lock Lock(ThreadCreationMutex); FEX::Windows::InitCRTThread(); - auto* Thread = CTX->CreateThread(0, 0); + auto* Thread = CTX->CreateThread(); // Default segment setup. auto Frame = Thread->CurrentFrame;