From e58f67b76ccdb4f95f7930fd9073c366bca1c702 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 17 Dec 2024 15:03:09 -0800 Subject: [PATCH] ThreadManager: Add some sanity asserts These couple of functions have some footguns that I'm encountering while rewriting gdbserver. Ensure that assertion builds capture the problems --- .../LinuxSyscalls/ThreadManager.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp index 75cb1d87e5..106e5a4cb1 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.cpp @@ -56,6 +56,14 @@ void ThreadManager::HandleThreadDeletion(FEX::HLE::ThreadStateObject* Thread, bo } if (NeedsTLSUninstall) { +#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED + // Sanity check. This can only be called from the owning thread. + { + const auto pid = ::getpid(); + const auto tid = FHU::Syscalls::gettid(); + LOGMAN_THROW_A_FMT(Thread->ThreadInfo.PID == pid && Thread->ThreadInfo.TID == tid, "Can't delete TLS data from a different thread!"); + } +#endif FEXCore::Allocator::UninstallTLSData(Thread->Thread); } @@ -76,6 +84,18 @@ void ThreadManager::NotifyPause() { } void ThreadManager::Pause() { +#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED + // Sanity check. This can't be called from an emulation thread. + { + const auto pid = ::getpid(); + const auto tid = FHU::Syscalls::gettid(); + std::lock_guard lk(ThreadCreationMutex); + for (auto& Thread : Threads) { + LOGMAN_THROW_A_FMT(!(Thread->ThreadInfo.PID == pid && Thread->ThreadInfo.TID == tid), "Can't put threads to sleep from inside " + "emulation thread!"); + } + } +#endif NotifyPause(); WaitForIdle(); } @@ -164,6 +184,15 @@ void ThreadManager::Stop(bool IgnoreCurrentThread) { void ThreadManager::SleepThread(FEXCore::Context::Context* CTX, FEXCore::Core::CpuStateFrame* Frame) { auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame); +#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED + // Sanity check. This can only be called from the owning thread. + { + const auto pid = ::getpid(); + const auto tid = FHU::Syscalls::gettid(); + LOGMAN_THROW_A_FMT(ThreadObject->ThreadInfo.PID == pid && ThreadObject->ThreadInfo.TID == tid, "Can't delete TLS data from a different " + "thread!"); + } +#endif --IdleWaitRefCount; IdleWaitCV.notify_all();