diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index f4a9d9512..344793a51 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -71,7 +71,7 @@ namespace FEXCore::Context { class ContextImpl final : public FEXCore::Context::Context { public: // Context base class implementation. - FEXCore::Core::InternalThreadState* InitCore(uint64_t InitialRIP, uint64_t StackPointer) override; + bool InitCore() override; void SetExitHandler(ExitHandler handler) override; ExitHandler GetExitHandler() const override; @@ -81,7 +81,7 @@ namespace FEXCore::Context { void Stop() override; void Step() override; - ExitReason RunUntilExit() override; + ExitReason RunUntilExit(FEXCore::Core::InternalThreadState *Thread) override; void ExecuteThread(FEXCore::Core::InternalThreadState *Thread) override; @@ -128,7 +128,7 @@ namespace FEXCore::Context { * - HandleCallback(Thread, RIP); */ - FEXCore::Core::InternalThreadState* CreateThread(uint64_t InitialRIP, uint64_t StackPointer, FEXCore::Core::CPUState *NewThreadState, uint64_t ParentTID) override; + FEXCore::Core::InternalThreadState* CreateThread(uint64_t InitialRIP, uint64_t StackPointer, ManagedBy WhoManages, FEXCore::Core::CPUState *NewThreadState, uint64_t ParentTID) override; // Public for threading void ExecutionThread(FEXCore::Core::InternalThreadState *Thread) override; @@ -144,7 +144,7 @@ namespace FEXCore::Context { * * @param Thread The internal FEX thread state object */ - void DestroyThread(FEXCore::Core::InternalThreadState *Thread) override; + void DestroyThread(FEXCore::Core::InternalThreadState *Thread, bool NeedsTLSUninstall) override; #ifndef _WIN32 void LockBeforeFork(FEXCore::Core::InternalThreadState *Thread) override; @@ -178,7 +178,7 @@ namespace FEXCore::Context { } void InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length) override; void InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length, CodeRangeInvalidationFn callback) override; - void MarkMemoryShared() override; + void MarkMemoryShared(FEXCore::Core::InternalThreadState *Thread) override; void ConfigureAOTGen(FEXCore::Core::InternalThreadState *Thread, fextl::set *ExternalBranches, uint64_t SectionMaxAddress) override; // returns false if a handler was already registered diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index aa13a7b92..6a388bf6a 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -103,10 +103,6 @@ namespace FEXCore::Context { } ContextImpl::~ContextImpl() { - if (ParentThread) { - DestroyThread(ParentThread); - } - { if (CodeObjectCacheService) { CodeObjectCacheService->Shutdown(); @@ -268,7 +264,7 @@ namespace FEXCore::Context { Frame->State.flags[X86State::RFLAG_IF_LOC] = 1; } - FEXCore::Core::InternalThreadState* ContextImpl::InitCore(uint64_t InitialRIP, uint64_t StackPointer) { + bool ContextImpl::InitCore() { // Initialize the CPU core signal handlers & DispatcherConfig switch (Config.Core) { case FEXCore::Config::CONFIG_IRJIT: @@ -278,8 +274,8 @@ namespace FEXCore::Context { // Do nothing break; default: - ERROR_AND_DIE_FMT("Unknown core configuration"); - break; + LogMan::Msg::EFmt("Unknown core configuration"); + return false; } DispatcherConfig.StaticRegisterAllocation = Config.StaticRegisterAllocation && BackendFeatures.SupportsStaticRegisterAllocation; @@ -330,12 +326,7 @@ namespace FEXCore::Context { StartPaused = true; } - FEXCore::Core::InternalThreadState *Thread = CreateThread(InitialRIP, StackPointer, nullptr, 0); - - // We are the parent thread - ParentThread = Thread; - - return Thread; + return true; } void ContextImpl::HandleCallback(FEXCore::Core::InternalThreadState *Thread, uint64_t RIP) { @@ -485,7 +476,7 @@ namespace FEXCore::Context { } } - FEXCore::Context::ExitReason ContextImpl::RunUntilExit() { + FEXCore::Context::ExitReason ContextImpl::RunUntilExit(FEXCore::Core::InternalThreadState *Thread) { if(!StartPaused) { // We will only have one thread at this point, but just in case run notify everything std::lock_guard lk(ThreadCreationMutex); @@ -494,10 +485,10 @@ namespace FEXCore::Context { } } - ExecutionThread(ParentThread); + ExecutionThread(Thread); while(true) { this->WaitForIdle(); - auto reason = ParentThread->ExitReason; + auto reason = Thread->ExitReason; // Don't return if a custom exit handling the exit if (!CustomExitHandler || reason == ExitReason::EXIT_SHUTDOWN) { @@ -575,7 +566,7 @@ namespace FEXCore::Context { Thread->PassManager->Finalize(); } - FEXCore::Core::InternalThreadState* ContextImpl::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, FEXCore::Core::CPUState *NewThreadState, uint64_t ParentTID) { + FEXCore::Core::InternalThreadState* ContextImpl::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, ManagedBy WhoManages, FEXCore::Core::CPUState *NewThreadState, uint64_t ParentTID) { FEXCore::Core::InternalThreadState *Thread = new FEXCore::Core::InternalThreadState{}; Thread->CurrentFrame->State.gregs[X86State::REG_RSP] = StackPointer; @@ -594,9 +585,10 @@ namespace FEXCore::Context { Thread->CurrentFrame->State.DeferredSignalRefCount.Store(0); Thread->CurrentFrame->State.DeferredSignalFaultAddress = reinterpret_cast*>(FEXCore::Allocator::VirtualAlloc(4096)); + Thread->DestroyedByParent = WhoManages == ManagedBy::FRONTEND; // Insert after the Thread object has been fully initialized - { + if (WhoManages == ManagedBy::CORE) { std::lock_guard lk(ThreadCreationMutex); Threads.push_back(Thread); } @@ -604,15 +596,19 @@ namespace FEXCore::Context { return Thread; } - void ContextImpl::DestroyThread(FEXCore::Core::InternalThreadState *Thread) { + void ContextImpl::DestroyThread(FEXCore::Core::InternalThreadState *Thread, bool NeedsTLSUninstall) { // remove new thread object { std::lock_guard lk(ThreadCreationMutex); auto It = std::find(Threads.begin(), Threads.end(), Thread); - LOGMAN_THROW_A_FMT(It != Threads.end(), "Thread wasn't in Threads"); + // TODO: Some threads aren't currently tracked in FEXCore. + // Re-enable once tracking is in frontend. + // LOGMAN_THROW_A_FMT(It != Threads.end(), "Thread wasn't in Threads"); - Threads.erase(It); + if (It != Threads.end()) { + Threads.erase(It); + } } if (Thread->ExecutionThread && @@ -621,6 +617,14 @@ namespace FEXCore::Context { Thread->ExecutionThread->detach(); } + // TODO: This is temporary until the frontend has full ownership of threads. + if (NeedsTLSUninstall) { +#ifndef _WIN32 + Alloc::OSAllocator::UninstallTLSData(Thread); +#endif + SignalDelegation->UninstallTLSState(Thread); + } + FEXCore::Allocator::VirtualFree(reinterpret_cast(Thread->CurrentFrame->State.DeferredSignalFaultAddress), 4096); delete Thread; } @@ -1113,7 +1117,7 @@ namespace FEXCore::Context { // Now notify the thread that we are initialized Thread->ThreadWaiting.NotifyAll(); - if (Thread != static_cast(Thread->CTX)->ParentThread || StartPaused || Thread->StartPaused) { + if (StartPaused || Thread->StartPaused) { // Parent thread doesn't need to wait to run Thread->StartRunning.Wait(); } @@ -1157,7 +1161,7 @@ namespace FEXCore::Context { SignalDelegation->UninstallTLSState(Thread); // If the parent thread is waiting to join, then we can't destroy our thread object - if (!Thread->DestroyedByParent && Thread != static_cast(Thread->CTX)->ParentThread) { + if (!Thread->DestroyedByParent) { Thread->CTX->DestroyThread(Thread); } } @@ -1176,12 +1180,21 @@ namespace FEXCore::Context { } } - static void InvalidateGuestCodeRangeInternal(ContextImpl *CTX, uint64_t Start, uint64_t Length) { + static void InvalidateGuestCodeRangeInternal(FEXCore::Core::InternalThreadState *CallingThread, ContextImpl *CTX, uint64_t Start, uint64_t Length) { std::lock_guard lk(static_cast(CTX)->ThreadCreationMutex); for (auto &Thread : static_cast(CTX)->Threads) { + + // TODO: Skip calling thread. + // Remove once frontend has thread ownership. + if (CallingThread == Thread) continue; InvalidateGuestThreadCodeRange(Thread, Start, Length); } + + // Now invalidate calling thread's code. + if (CallingThread) { + InvalidateGuestThreadCodeRange(CallingThread, Start, Length); + } } void ContextImpl::InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length) { @@ -1190,7 +1203,7 @@ namespace FEXCore::Context { // To be more optimal the frontend should provide this code with a valid Thread object earlier. auto lk = GuardSignalDeferringSectionWithFallback(CodeInvalidationMutex, Thread); - InvalidateGuestCodeRangeInternal(this, Start, Length); + InvalidateGuestCodeRangeInternal(Thread, this, Start, Length); } void ContextImpl::InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length, CodeRangeInvalidationFn CallAfter) { @@ -1199,20 +1212,17 @@ namespace FEXCore::Context { // To be more optimal the frontend should provide this code with a valid Thread object earlier. auto lk = GuardSignalDeferringSectionWithFallback(CodeInvalidationMutex, Thread); - InvalidateGuestCodeRangeInternal(this, Start, Length); + InvalidateGuestCodeRangeInternal(Thread, this, Start, Length); CallAfter(Start, Length); } - void ContextImpl::MarkMemoryShared() { + void ContextImpl::MarkMemoryShared(FEXCore::Core::InternalThreadState *Thread) { if (!IsMemoryShared) { IsMemoryShared = true; UpdateAtomicTSOEmulationConfig(); if (Config.TSOAutoMigration) { std::lock_guard lkThreads(ThreadCreationMutex); - LogMan::Throw::AFmt(Threads.size() == 1, "First MarkMemoryShared called must be before creating any threads"); - - auto Thread = Threads[0]; // Only the lookup cache is cleared here, so that old code can keep running until next compilation std::lock_guard lkLookupCache(Thread->LookupCache->WriteLock); diff --git a/FEXCore/include/FEXCore/Core/Context.h b/FEXCore/include/FEXCore/Core/Context.h index fe51907a1..04b5d46ee 100644 --- a/FEXCore/include/FEXCore/Core/Context.h +++ b/FEXCore/include/FEXCore/Core/Context.h @@ -124,7 +124,7 @@ namespace FEXCore::Context { * * @return true if we loaded code */ - FEX_DEFAULT_VISIBILITY virtual FEXCore::Core::InternalThreadState* InitCore(uint64_t InitialRIP, uint64_t StackPointer) = 0; + FEX_DEFAULT_VISIBILITY virtual bool InitCore() = 0; FEX_DEFAULT_VISIBILITY virtual void SetExitHandler(ExitHandler handler) = 0; FEX_DEFAULT_VISIBILITY virtual ExitHandler GetExitHandler() const = 0; @@ -181,7 +181,7 @@ namespace FEXCore::Context { * * @return The ExitReason for the parentthread. */ - FEX_DEFAULT_VISIBILITY virtual ExitReason RunUntilExit() = 0; + FEX_DEFAULT_VISIBILITY virtual ExitReason RunUntilExit(FEXCore::Core::InternalThreadState *Thread) = 0; /** * @brief Executes the supplied thread context on the current thread until a return is requested @@ -248,17 +248,24 @@ namespace FEXCore::Context { * * @param InitialRIP The starting RIP of this thread * @param StackPointer The starting RSP of this thread + * @param WhoManages The flag to determine what manages ownership of the InternalThreadState object * @param NewThreadState The thread state to inherit from if not nullptr. * @param ParentTID The thread ID that the parent is inheriting from * * @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, FEXCore::Core::CPUState *NewThreadState = nullptr, uint64_t ParentTID = 0) = 0; + + // TODO: This is a temporary construct and will be removed once the frontend has full ownership of InternalThreadState objects. + enum class [[deprecated]] ManagedBy { + CORE, + FRONTEND, + }; + FEX_DEFAULT_VISIBILITY virtual FEXCore::Core::InternalThreadState* CreateThread(uint64_t InitialRIP, uint64_t StackPointer, ManagedBy WhoManages, FEXCore::Core::CPUState *NewThreadState = nullptr, uint64_t ParentTID = 0) = 0; FEX_DEFAULT_VISIBILITY virtual void ExecutionThread(FEXCore::Core::InternalThreadState *Thread) = 0; FEX_DEFAULT_VISIBILITY virtual void RunThread(FEXCore::Core::InternalThreadState *Thread) = 0; FEX_DEFAULT_VISIBILITY virtual void StopThread(FEXCore::Core::InternalThreadState *Thread) = 0; - FEX_DEFAULT_VISIBILITY virtual void DestroyThread(FEXCore::Core::InternalThreadState *Thread) = 0; + FEX_DEFAULT_VISIBILITY virtual void DestroyThread(FEXCore::Core::InternalThreadState *Thread, bool NeedsTLSUninstall = false) = 0; #ifndef _WIN32 FEX_DEFAULT_VISIBILITY virtual void LockBeforeFork(FEXCore::Core::InternalThreadState *Thread) {} FEX_DEFAULT_VISIBILITY virtual void UnlockAfterFork(FEXCore::Core::InternalThreadState *Thread, bool Child) {} @@ -281,7 +288,7 @@ namespace FEXCore::Context { FEX_DEFAULT_VISIBILITY virtual void WriteFilesWithCode(AOTIRCodeFileWriterFn Writer) = 0; FEX_DEFAULT_VISIBILITY virtual void InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length) = 0; FEX_DEFAULT_VISIBILITY virtual void InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState *Thread, uint64_t Start, uint64_t Length, CodeRangeInvalidationFn callback) = 0; - FEX_DEFAULT_VISIBILITY virtual void MarkMemoryShared() = 0; + FEX_DEFAULT_VISIBILITY virtual void MarkMemoryShared(FEXCore::Core::InternalThreadState *Thread) = 0; FEX_DEFAULT_VISIBILITY virtual void ConfigureAOTGen(FEXCore::Core::InternalThreadState *Thread, fextl::set *ExternalBranches, uint64_t SectionMaxAddress) = 0; FEX_DEFAULT_VISIBILITY virtual CustomIRResult AddCustomIREntrypoint(uintptr_t Entrypoint, CustomIREntrypointHandler Handler, void *Creator = nullptr, void *Data = nullptr) = 0; diff --git a/Source/Tools/CodeSizeValidation/Main.cpp b/Source/Tools/CodeSizeValidation/Main.cpp index 1fc53fad5..309c8e6ec 100644 --- a/Source/Tools/CodeSizeValidation/Main.cpp +++ b/Source/Tools/CodeSizeValidation/Main.cpp @@ -558,11 +558,16 @@ int main(int argc, char **argv, char **const envp) { CTX->SetSignalDelegator(SignalDelegation.get()); CTX->SetSyscallHandler(SyscallHandler.get()); - auto ParentThread = CTX->InitCore(0, 0); + if (!CTX->InitCore()) { + return -1; + } + auto ParentThread = CTX->CreateThread(0, 0, FEXCore::Context::Context::ManagedBy::FRONTEND); // Calculate the base stats for instruction testing. CodeSize::Validation.CalculateBaseStats(CTX.get(), ParentThread); // Test all the instructions. - return TestInstructions(CTX.get(), ParentThread, argc >= 2 ? argv[2] : nullptr) ? 0 : 1; + auto Result = TestInstructions(CTX.get(), ParentThread, argc >= 2 ? argv[2] : nullptr) ? 0 : 1; + CTX->DestroyThread(ParentThread); + return Result; } diff --git a/Source/Tools/FEXLoader/AOT/AOTGenerator.cpp b/Source/Tools/FEXLoader/AOT/AOTGenerator.cpp index 88c4d44ef..96d689569 100644 --- a/Source/Tools/FEXLoader/AOT/AOTGenerator.cpp +++ b/Source/Tools/FEXLoader/AOT/AOTGenerator.cpp @@ -106,7 +106,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(0, 0, FEXCore::Context::Context::ManagedBy::FRONTEND); fextl::set ExternalBranchesLocal; CTX->ConfigureAOTGen(Thread, &ExternalBranchesLocal, SectionMaxAddress); diff --git a/Source/Tools/FEXLoader/FEXLoader.cpp b/Source/Tools/FEXLoader/FEXLoader.cpp index ed6b2ecc7..80031010e 100644 --- a/Source/Tools/FEXLoader/FEXLoader.cpp +++ b/Source/Tools/FEXLoader/FEXLoader.cpp @@ -486,7 +486,11 @@ int main(int argc, char **argv, char **const envp) { DebugServer = fextl::make_unique(CTX.get(), SignalDelegation.get(), SyscallHandler.get()); } - auto ParentThread = CTX->InitCore(Loader.DefaultRIP(), Loader.GetStackPointer()); + if (!CTX->InitCore()) { + return 1; + } + + auto ParentThread = CTX->CreateThread(Loader.DefaultRIP(), Loader.GetStackPointer(), FEXCore::Context::Context::ManagedBy::FRONTEND); // Pass in our VDSO thunks CTX->AppendThunkDefinitions(FEX::VDSO::GetVDSOThunkDefinitions()); @@ -541,7 +545,7 @@ int main(int argc, char **argv, char **const envp) { FEX::AOT::AOTGenSection(CTX.get(), Section); } } else { - CTX->RunUntilExit(); + CTX->RunUntilExit(ParentThread); } if (AOTEnabled) { @@ -564,6 +568,8 @@ int main(int argc, char **argv, char **const envp) { auto ProgramStatus = ParentThread->StatusCode; + CTX->DestroyThread(ParentThread); + DebugServer.reset(); SyscallHandler.reset(); SignalDelegation.reset(); diff --git a/Source/Tools/IRLoader/IRLoader.cpp b/Source/Tools/IRLoader/IRLoader.cpp index 878040203..f94b8a50c 100644 --- a/Source/Tools/IRLoader/IRLoader.cpp +++ b/Source/Tools/IRLoader/IRLoader.cpp @@ -178,7 +178,10 @@ int main(int argc, char **argv, char **const envp) if (Loader.LoadIR(CTX.get())) { - auto ParentThread = CTX->InitCore(Loader.DefaultRIP(), Loader.GetStackPointer()); + if (!CTX->InitCore()) { + return -1; + } + auto ParentThread = CTX->CreateThread(Loader.DefaultRIP(), Loader.GetStackPointer(), FEXCore::Context::Context::ManagedBy::FRONTEND); auto ShutdownReason = FEXCore::Context::ExitReason::EXIT_SHUTDOWN; @@ -204,7 +207,7 @@ int main(int argc, char **argv, char **const envp) LongJumpVal = setjmp(LongJump); if (!LongJumpVal) { - CTX->RunUntilExit(); + CTX->RunUntilExit(ParentThread); } LogMan::Msg::DFmt("Reason we left VM: {}", FEXCore::ToUnderlying(ShutdownReason)); @@ -215,6 +218,7 @@ int main(int argc, char **argv, char **const envp) LogMan::Msg::IFmt("Passed? {}\n", Passed ? "Yes" : "No"); Return = Passed ? 0 : -1; + CTX->DestroyThread(ParentThread); } else { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp index 402f2df76..38ca3be14 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp @@ -573,7 +573,7 @@ uint64_t CloneHandler(FEXCore::Core::CpuStateFrame *Frame, FEX::HLE::clone3_args }; if (flags & CLONE_VM) { - Frame->Thread->CTX->MarkMemoryShared(); + Frame->Thread->CTX->MarkMemoryShared(Frame->Thread); } // If there are flags that can't be handled regularly then we need to hand off to the true clone handler diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp index 7cd731f0f..f3580657d 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp @@ -73,7 +73,7 @@ namespace FEX::HLE { NewThreadState.gregs[FEXCore::X86State::REG_RSP] = args->args.stack; } - auto NewThread = CTX->CreateThread(0, 0, &NewThreadState, args->args.parent_tid); + auto NewThread = CTX->CreateThread(0, 0, FEXCore::Context::Context::ManagedBy::CORE, &NewThreadState, args->args.parent_tid); if (FEX::HLE::_SyscallHandler->Is64BitMode()) { if (flags & CLONE_SETTLS) { @@ -166,7 +166,7 @@ namespace FEX::HLE { } // Overwrite thread - NewThread = CTX->CreateThread(0, 0, &NewThreadState, GuestArgs->parent_tid); + NewThread = CTX->CreateThread(0, 0, FEXCore::Context::Context::ManagedBy::CORE, &NewThreadState, GuestArgs->parent_tid); // CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID, CLONE_PIDFD will be handled by kernel // Call execution thread directly since we already are on the new thread diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp index e968f3987..092dcf538 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/SyscallsSMCTracking.cpp @@ -187,7 +187,7 @@ void SyscallHandler::TrackMmap(FEXCore::Core::InternalThreadState *Thread, uintp Size = FEXCore::AlignUp(Size, FHU::FEX_PAGE_SIZE); if (Flags & MAP_SHARED) { - CTX->MarkMemoryShared(); + CTX->MarkMemoryShared(Thread); } { @@ -322,7 +322,7 @@ void SyscallHandler::TrackMremap(FEXCore::Core::InternalThreadState *Thread, uin } void SyscallHandler::TrackShmat(FEXCore::Core::InternalThreadState *Thread, int shmid, uintptr_t Base, int shmflg) { - CTX->MarkMemoryShared(); + CTX->MarkMemoryShared(Thread); shmid_ds stat; diff --git a/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp b/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp index 3b1d018c8..37c5cabc9 100644 --- a/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp +++ b/Source/Tools/TestHarnessRunner/TestHarnessRunner.cpp @@ -301,7 +301,10 @@ int main(int argc, char **argv, char **const envp) { CTX->SetSignalDelegator(SignalDelegation.get()); CTX->SetSyscallHandler(SyscallHandler.get()); - auto ParentThread = CTX->InitCore(Loader.DefaultRIP(), Loader.GetStackPointer()); + if (!CTX->InitCore()) { + return 1; + } + auto ParentThread = CTX->CreateThread(Loader.DefaultRIP(), Loader.GetStackPointer(), FEXCore::Context::Context::ManagedBy::FRONTEND); if (!ParentThread) { return 1; @@ -309,13 +312,15 @@ int main(int argc, char **argv, char **const envp) { int LongJumpVal = setjmp(LongJumpHandler::LongJump); if (!LongJumpVal) { - CTX->RunUntilExit(); + CTX->RunUntilExit(ParentThread); } // Just re-use compare state. It also checks against the expected values in config. memcpy(&State, &ParentThread->CurrentFrame->State, sizeof(State)); SyscallHandler.reset(); + + CTX->DestroyThread(ParentThread, true); } #ifndef _WIN32 else { diff --git a/Source/Windows/WOW64/Module.cpp b/Source/Windows/WOW64/Module.cpp index 6a1da5d53..4306cbde7 100644 --- a/Source/Windows/WOW64/Module.cpp +++ b/Source/Windows/WOW64/Module.cpp @@ -517,7 +517,7 @@ void BTCpuProcessInit() { CTX = FEXCore::Context::Context::CreateNewContext(); CTX->SetSignalDelegator(SignalDelegator.get()); CTX->SetSyscallHandler(SyscallHandler.get()); - CTX->InitCore(0, 0); + CTX->InitCore(); CpuInfo.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; @@ -554,7 +554,7 @@ void BTCpuProcessInit() { } NTSTATUS BTCpuThreadInit() { - GetTLS().ThreadState() = CTX->CreateThread(0, 0); + GetTLS().ThreadState() = CTX->CreateThread(0, 0, FEXCore::Context::Context::ManagedBy::FRONTEND); std::scoped_lock Lock(ThreadSuspendLock); InitializedWOWThreads.emplace(GetCurrentThreadId());