Skip to content

Commit

Permalink
Merge pull request #4080 from Sonicadvance1/improve_createthread_stack
Browse files Browse the repository at this point in the history
Linux: Optimize CreateNewThread and HandleNewClone stack usage
  • Loading branch information
lioncash authored Sep 24, 2024
2 parents b5c9eb3 + f5def7a commit d547f2b
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 24 deletions.
2 changes: 1 addition & 1 deletion FEXCore/Source/Interface/Context/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class ContextImpl final : public FEXCore::Context::Context {
*/

FEXCore::Core::InternalThreadState*
CreateThread(uint64_t InitialRIP, uint64_t StackPointer, FEXCore::Core::CPUState* NewThreadState, uint64_t ParentTID) override;
CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState, uint64_t ParentTID) override;

// Public for threading
void ExecutionThread(FEXCore::Core::InternalThreadState* Thread) override;
Expand Down
2 changes: 1 addition & 1 deletion FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ void ContextImpl::InitializeCompiler(FEXCore::Core::InternalThreadState* Thread)
}

FEXCore::Core::InternalThreadState*
ContextImpl::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, FEXCore::Core::CPUState* NewThreadState, uint64_t ParentTID) {
ContextImpl::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState, uint64_t ParentTID) {
FEXCore::Core::InternalThreadState* Thread = new FEXCore::Core::InternalThreadState {};

Thread->CurrentFrame->State.gregs[X86State::REG_RSP] = StackPointer;
Expand Down
4 changes: 2 additions & 2 deletions FEXCore/include/FEXCore/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ class Context {
* @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;
FEX_DEFAULT_VISIBILITY virtual FEXCore::Core::InternalThreadState* CreateThread(
uint64_t InitialRIP, uint64_t StackPointer, const 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 DestroyThread(FEXCore::Core::InternalThreadState* Thread, bool NeedsTLSUninstall = false) = 0;
Expand Down
28 changes: 10 additions & 18 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,18 @@ 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;
FEXCore::Core::CPUState NewThreadState {};
// Clone copies the parent thread's state
memcpy(&NewThreadState, Frame, sizeof(FEXCore::Core::CPUState));
auto NewThread = FEX::HLE::_SyscallHandler->TM.CreateThread(0, 0, &Frame->State, args->args.parent_tid,
FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame));

NewThreadState.gregs[FEXCore::X86State::REG_RAX] = 0;
NewThread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RAX] = 0;
if (args->Type == TYPE_CLONE3) {
// stack pointer points to the lowest address to the stack
// set RSP to stack + size
NewThreadState.gregs[FEXCore::X86State::REG_RSP] = args->args.stack + args->args.stack_size;
NewThread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP] = args->args.stack + args->args.stack_size;
} else {
NewThreadState.gregs[FEXCore::X86State::REG_RSP] = args->args.stack;
NewThread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP] = args->args.stack;
}

auto NewThread = FEX::HLE::_SyscallHandler->TM.CreateThread(0, 0, &NewThreadState, args->args.parent_tid,
FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame));

if (FEX::HLE::_SyscallHandler->Is64BitMode()) {
if (flags & CLONE_SETTLS) {
x64::SetThreadArea(NewThread->Thread->CurrentFrame, reinterpret_cast<void*>(args->args.tls));
Expand Down Expand Up @@ -161,21 +157,17 @@ uint64_t HandleNewClone(FEX::HLE::ThreadStateObject* Thread, FEXCore::Context::C
bool CreatedNewThreadObject {};

if (flags & CLONE_THREAD) {
FEXCore::Core::CPUState NewThreadState {};
// Clone copies the parent thread's state
memcpy(&NewThreadState, Frame, sizeof(FEXCore::Core::CPUState));
// Overwrite thread
NewThread = FEX::HLE::_SyscallHandler->TM.CreateThread(0, 0, &Frame->State, GuestArgs->parent_tid,
FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame));

NewThreadState.gregs[FEXCore::X86State::REG_RAX] = 0;
NewThread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RAX] = 0;
if (GuestArgs->stack == 0) {
// Copies in the original thread's stack
} else {
NewThreadState.gregs[FEXCore::X86State::REG_RSP] = GuestArgs->stack;
NewThread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP] = GuestArgs->stack;
}

// Overwrite thread
NewThread = FEX::HLE::_SyscallHandler->TM.CreateThread(0, 0, &NewThreadState, GuestArgs->parent_tid,
FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame));

// 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
NewThread->Thread->StartRunning.NotifyAll(); // Clear the start running flag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <FEXHeaderUtils/Syscalls.h>

namespace FEX::HLE {
FEX::HLE::ThreadStateObject* ThreadManager::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, FEXCore::Core::CPUState* NewThreadState,
FEX::HLE::ThreadStateObject* ThreadManager::CreateThread(uint64_t InitialRIP, uint64_t StackPointer, const FEXCore::Core::CPUState* NewThreadState,
uint64_t ParentTID, FEX::HLE::ThreadStateObject* InheritThread) {
auto ThreadStateObject = new FEX::HLE::ThreadStateObject;

Expand Down
2 changes: 1 addition & 1 deletion Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class ThreadManager final {
return static_cast<FEX::HLE::ThreadStateObject*>(Thread->FrontendPtr);
}

FEX::HLE::ThreadStateObject* CreateThread(uint64_t InitialRIP, uint64_t StackPointer, FEXCore::Core::CPUState* NewThreadState = nullptr,
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);
void TrackThread(FEX::HLE::ThreadStateObject* Thread) {
std::lock_guard lk(ThreadCreationMutex);
Expand Down

0 comments on commit d547f2b

Please sign in to comment.