diff --git a/FEXCore/Source/Interface/Core/DiskCache.cpp b/FEXCore/Source/Interface/Core/DiskCache.cpp index e9c49f8df..cb2f27e45 100644 --- a/FEXCore/Source/Interface/Core/DiskCache.cpp +++ b/FEXCore/Source/Interface/Core/DiskCache.cpp @@ -381,7 +381,8 @@ namespace DiskCache { } if (IsWritingDiskCache()) { - Writer = fextl::make_unique(true); + FEXCore::Threads::Flags WriterThreadFlags = {.LowPriority = true, .Internal = true}; + Writer = fextl::make_unique(WriterThreadFlags); } } diff --git a/FEXCore/Source/Utils/Threads.cpp b/FEXCore/Source/Utils/Threads.cpp index fd0701563..4b2ee9b74 100644 --- a/FEXCore/Source/Utils/Threads.cpp +++ b/FEXCore/Source/Utils/Threads.cpp @@ -7,7 +7,7 @@ #include namespace FEXCore::Threads { -static fextl::unique_ptr CreateThread_Default(ThreadFunc Func, void* Arg, bool LowPriority) { +static fextl::unique_ptr CreateThread_Default(ThreadFunc Func, void* Arg, FEXCore::Threads::Flags Flags) { ERROR_AND_DIE_FMT("Frontend didn't setup thread creation!"); } @@ -20,8 +20,8 @@ static FEXCore::Threads::Pointers Ptrs = { .CleanupAfterFork = CleanupAfterFork_Default, }; -fextl::unique_ptr FEXCore::Threads::Thread::Create(ThreadFunc Func, void* Arg, bool LowPriority) { - return Ptrs.CreateThread(Func, Arg, LowPriority); +fextl::unique_ptr FEXCore::Threads::Thread::Create(ThreadFunc Func, void* Arg, FEXCore::Threads::Flags Flags) { + return Ptrs.CreateThread(Func, Arg, Flags); } void FEXCore::Threads::Thread::CleanupAfterFork() { diff --git a/FEXCore/Source/Utils/WorkQueueThread.cpp b/FEXCore/Source/Utils/WorkQueueThread.cpp index 2d3a74f15..710c87834 100644 --- a/FEXCore/Source/Utils/WorkQueueThread.cpp +++ b/FEXCore/Source/Utils/WorkQueueThread.cpp @@ -4,8 +4,8 @@ namespace FEXCore { -WorkQueueThread::WorkQueueThread(bool LowPriority) { - Thread = FEXCore::Threads::Thread::Create(ThreadEntry, this, LowPriority); +WorkQueueThread::WorkQueueThread(FEXCore::Threads::Flags ThreadFlags) { + Thread = FEXCore::Threads::Thread::Create(ThreadEntry, this, ThreadFlags); } WorkQueueThread::~WorkQueueThread() { diff --git a/FEXCore/include/FEXCore/Utils/Threads.h b/FEXCore/include/FEXCore/Utils/Threads.h index 43616c613..905c0c48a 100644 --- a/FEXCore/include/FEXCore/Utils/Threads.h +++ b/FEXCore/include/FEXCore/Utils/Threads.h @@ -4,10 +4,16 @@ #include namespace FEXCore::Threads { + +struct Flags { + bool LowPriority : 1 {}; + bool Internal : 1 {}; +}; + using ThreadFunc = void* (*)(void* user_ptr); class Thread; -using CreateThreadFunc = fextl::unique_ptr (*)(ThreadFunc Func, void* Arg, bool LowPriority); +using CreateThreadFunc = fextl::unique_ptr (*)(ThreadFunc Func, void* Arg, Flags Flags); using CleanupAfterForkFunc = void (*)(); struct Pointers { @@ -28,7 +34,7 @@ public: * @name Calls provided API functions * @{ */ - static fextl::unique_ptr Create(ThreadFunc Func, void* Arg, bool LowPriority = false); + static fextl::unique_ptr Create(ThreadFunc Func, void* Arg, Flags Flags = {}); static void CleanupAfterFork(); diff --git a/FEXCore/include/FEXCore/Utils/WorkQueueThread.h b/FEXCore/include/FEXCore/Utils/WorkQueueThread.h index a17d3d7ce..d33aad0b8 100644 --- a/FEXCore/include/FEXCore/Utils/WorkQueueThread.h +++ b/FEXCore/include/FEXCore/Utils/WorkQueueThread.h @@ -18,7 +18,7 @@ public: virtual void Run() = 0; }; - WorkQueueThread(bool LowPriority = false); + WorkQueueThread(FEXCore::Threads::Flags Flags = {}); ~WorkQueueThread(); void QueueWork(fextl::unique_ptr Work); diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp index 9b2fd344f..db7a11a6c 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp @@ -1482,9 +1482,7 @@ static void* ThreadHandler(void* Arg) { } void GdbServer::StartThread() { - uint64_t OldMask = HLE::ThreadManager::SetSignalMask(~0ULL); - gdbServerThread = FEXCore::Threads::Thread::Create(ThreadHandler, this); - HLE::ThreadManager::SetSignalMask(OldMask); + gdbServerThread = FEXCore::Threads::Thread::Create(ThreadHandler, this, {.Internal = true}); } void GdbServer::OpenListenSocket() { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Utils/Threads.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Utils/Threads.cpp index 34b6750f6..dd85c0d65 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Utils/Threads.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Utils/Threads.cpp @@ -197,11 +197,11 @@ namespace PThreads { class PThread final : public FEXCore::Threads::Thread { public: - PThread(StackTracker* STracker, FEXCore::Threads::ThreadFunc Func, void* Arg, bool LowPriority) + PThread(StackTracker* STracker, FEXCore::Threads::ThreadFunc Func, void* Arg, FEXCore::Threads::Flags Flags) : STracker {STracker} , UserFunc {Func} , UserArg {Arg} - , LowPriority {LowPriority} { + , Flags {Flags} { pthread_attr_t Attr {}; Stack = STracker->AllocateStackObject(); // pthreads allocates its dtv region behind our back and there is nothing we can do about it. @@ -216,7 +216,15 @@ namespace PThreads { // `set_tid_address` address construct. If the stack is reused before the address is set to zero, then glibc won't initialize the new thread's // DTV/TLS region, resulting in TLS usage crashing. pthread_attr_setstacksize(&Attr, PTHREAD_STACK_MIN); + uint64_t OldMask; + bool BlockingSignals = Flags.Internal; + if (BlockingSignals) { + OldMask = HLE::ThreadManager::SetSignalMask(~0ULL); + } pthread_create(&Thread, &Attr, InitializeThread, this); + if (BlockingSignals) { + HLE::ThreadManager::SetSignalMask(OldMask); + } pthread_attr_destroy(&Attr); } @@ -260,8 +268,8 @@ namespace PThreads { return Stack; } - bool GetLowPriority() const { - return LowPriority; + FEXCore::Threads::Flags GetFlags() const { + return Flags; } StackTracker* GetStackTracker() const { @@ -294,7 +302,7 @@ namespace PThreads { FEXCore::Threads::ThreadFunc UserFunc; void* UserArg; void* Stack {}; - bool LowPriority {}; + FEXCore::Threads::Flags Flags {}; // Use FEXCore's UncheckedLongJump to avoid fortification checks. // This avoids a false positive since glibc does not understand stack pivots. @@ -313,7 +321,7 @@ namespace PThreads { bool LongJumpExit {}; - if (Thread->GetLowPriority()) { + if (Thread->GetFlags().LowPriority) { setpriority(PRIO_PROCESS, FHU::Syscalls::gettid(), 19); } @@ -366,8 +374,9 @@ namespace PThreads { static StackTracker* STracker {}; - static fextl::unique_ptr CreateThread_PThread(FEXCore::Threads::ThreadFunc Func, void* Arg, bool LowPriority) { - return fextl::make_unique(STracker, Func, Arg, LowPriority); + static fextl::unique_ptr + CreateThread_PThread(FEXCore::Threads::ThreadFunc Func, void* Arg, FEXCore::Threads::Flags Flags) { + return fextl::make_unique(STracker, Func, Arg, Flags); } static void CleanupAfterFork_PThread() { diff --git a/Source/Windows/Common/Threads.cpp b/Source/Windows/Common/Threads.cpp index a703caeac..85b6b0b74 100644 --- a/Source/Windows/Common/Threads.cpp +++ b/Source/Windows/Common/Threads.cpp @@ -13,13 +13,15 @@ namespace FEX::Windows { namespace WinThreadImpl { class Thread final : public FEXCore::Threads::Thread { public: - Thread(FEXCore::Threads::ThreadFunc Func, void* Arg, bool LowPriority) + Thread(FEXCore::Threads::ThreadFunc Func, void* Arg, FEXCore::Threads::Flags Flags) : UserFunc {Func} , UserArg {Arg} - , LowPriority {LowPriority} { + , Flags {Flags} { // hide everything from guest, don't initialize anything, we'll do that manually in RunThread() - const ULONG CreateFlags = THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER | - THREAD_CREATE_FLAGS_SKIP_LOADER_INIT | THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE; + ULONG CreateFlags = THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | THREAD_CREATE_FLAGS_SKIP_LOADER_INIT | THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE; + if (Flags.Internal) { + CreateFlags |= THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER; + } NTSTATUS Status = NtCreateThreadEx(&Handle, THREAD_ALL_ACCESS, nullptr, GetCurrentProcess(), reinterpret_cast(&Thread::RunThread), this, CreateFlags, 0, 0, 0, nullptr); if (Status < 0) { @@ -62,14 +64,14 @@ namespace WinThreadImpl { } } - bool GetLowPriority() const { - return LowPriority; + FEXCore::Threads::Flags GetFlags() const { + return Flags; } private: static void RunThread(Thread* This) { This->TID = GetCurrentThreadId(); - if (This->GetLowPriority()) { + if (This->GetFlags().LowPriority) { LONG Priority = THREAD_BASE_PRIORITY_IDLE; NtSetInformationThread(NtCurrentThread(), ThreadBasePriority, &Priority, sizeof(Priority)); } @@ -82,14 +84,14 @@ namespace WinThreadImpl { FEXCore::Threads::ThreadFunc UserFunc; void* UserArg; - bool LowPriority {}; + FEXCore::Threads::Flags Flags {}; HANDLE Handle {}; DWORD TID {}; void* ReturnValue {}; }; - fextl::unique_ptr CreateThread(FEXCore::Threads::ThreadFunc Func, void* Arg, bool LowPriority) { - return fextl::make_unique(Func, Arg, LowPriority); + fextl::unique_ptr CreateThread(FEXCore::Threads::ThreadFunc Func, void* Arg, FEXCore::Threads::Flags Flags) { + return fextl::make_unique(Func, Arg, Flags); } void CleanupAfterFork() {}