Skip to content

Commit

Permalink
FEXLoader: Changes frontend thread management to wrap FEXCore thread …
Browse files Browse the repository at this point in the history
…objects

A bit of refactoring necessary before we can move the remaining Linux
specific code to the frontend.

Most of this taken from FEX-Emu#3535 but attempting to be NFC as much as
possible.
  • Loading branch information
Sonicadvance1 committed May 5, 2024
1 parent 729e32c commit d372552
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 119 deletions.
6 changes: 3 additions & 3 deletions Source/Tools/FEXLoader/FEXLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ int main(int argc, char** argv, char** const envp) {
FEX::AOT::AOTGenSection(CTX.get(), Section);
}
} else {
CTX->RunUntilExit(ParentThread);
CTX->RunUntilExit(ParentThread->Thread);
}

if (AOTEnabled) {
Expand All @@ -565,10 +565,10 @@ int main(int argc, char** argv, char** const envp) {
}
}

auto ProgramStatus = ParentThread->StatusCode;
auto ProgramStatus = ParentThread->Thread->StatusCode;

SignalDelegation->UninstallTLSState(ParentThread);
CTX->DestroyThread(ParentThread);
SyscallHandler->TM.DestroyThread(ParentThread);

DebugServer.reset();
SyscallHandler.reset();
Expand Down
28 changes: 14 additions & 14 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/GdbServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,29 +320,29 @@ fextl::string GdbServer::readRegs() {
FEXCore::Core::CPUState state {};

auto Threads = SyscallHandler->TM.GetThreads();
FEXCore::Core::InternalThreadState* CurrentThread {Threads->at(0)};
FEX::HLE::ThreadStateObject* CurrentThread {Threads->at(0)};
bool Found = false;

for (auto& Thread : *Threads) {
if (Thread->ThreadManager.GetTID() != CurrentDebuggingThread) {
if (Thread->Thread->ThreadManager.GetTID() != CurrentDebuggingThread) {
continue;
}
memcpy(&state, Thread->CurrentFrame, sizeof(state));
memcpy(&state, Thread->Thread->CurrentFrame, sizeof(state));
CurrentThread = Thread;
Found = true;
break;
}

if (!Found) {
// If set to an invalid thread then just get the parent thread ID
memcpy(&state, CurrentThread->CurrentFrame, sizeof(state));
memcpy(&state, CurrentThread->Thread->CurrentFrame, sizeof(state));
}

// Encode the GDB context definition
memcpy(&GDB.gregs[0], &state.gregs[0], sizeof(GDB.gregs));
memcpy(&GDB.rip, &state.rip, sizeof(GDB.rip));

GDB.eflags = CTX->ReconstructCompactedEFLAGS(CurrentThread, false, nullptr, 0);
GDB.eflags = CTX->ReconstructCompactedEFLAGS(CurrentThread->Thread, false, nullptr, 0);

for (size_t i = 0; i < FEXCore::Core::CPUState::NUM_MMS; ++i) {
memcpy(&GDB.mm[i], &state.mm[i], sizeof(GDB.mm));
Expand Down Expand Up @@ -371,22 +371,22 @@ GdbServer::HandledPacketType GdbServer::readReg(const fextl::string& packet) {
FEXCore::Core::CPUState state {};

auto Threads = SyscallHandler->TM.GetThreads();
FEXCore::Core::InternalThreadState* CurrentThread {Threads->at(0)};
FEX::HLE::ThreadStateObject* CurrentThread {Threads->at(0)};
bool Found = false;

for (auto& Thread : *Threads) {
if (Thread->ThreadManager.GetTID() != CurrentDebuggingThread) {
if (Thread->Thread->ThreadManager.GetTID() != CurrentDebuggingThread) {
continue;
}
memcpy(&state, Thread->CurrentFrame, sizeof(state));
memcpy(&state, Thread->Thread->CurrentFrame, sizeof(state));
CurrentThread = Thread;
Found = true;
break;
}

if (!Found) {
// If set to an invalid thread then just get the parent thread ID
memcpy(&state, CurrentThread->CurrentFrame, sizeof(state));
memcpy(&state, CurrentThread->Thread->CurrentFrame, sizeof(state));
}


Expand All @@ -395,7 +395,7 @@ GdbServer::HandledPacketType GdbServer::readReg(const fextl::string& packet) {
} else if (addr == offsetof(GDBContextDefinition, rip)) {
return {encodeHex((unsigned char*)(&state.rip), sizeof(uint64_t)), HandledPacketType::TYPE_ACK};
} else if (addr == offsetof(GDBContextDefinition, eflags)) {
uint32_t eflags = CTX->ReconstructCompactedEFLAGS(CurrentThread, false, nullptr, 0);
uint32_t eflags = CTX->ReconstructCompactedEFLAGS(CurrentThread->Thread, false, nullptr, 0);

return {encodeHex((unsigned char*)(&eflags), sizeof(uint32_t)), HandledPacketType::TYPE_ACK};
} else if (addr >= offsetof(GDBContextDefinition, cs) && addr < offsetof(GDBContextDefinition, mm[0])) {
Expand Down Expand Up @@ -722,8 +722,8 @@ GdbServer::HandledPacketType GdbServer::handleXfer(const fextl::string& packet)
ss << "<threads>\n";
for (auto& Thread : *Threads) {
// Thread id is in hex without 0x prefix
const auto ThreadName = getThreadName(Thread->ThreadManager.GetTID());
ss << "<thread id=\"" << std::hex << Thread->ThreadManager.GetTID() << "\"";
const auto ThreadName = getThreadName(Thread->Thread->ThreadManager.GetTID());
ss << "<thread id=\"" << std::hex << Thread->Thread->ThreadManager.GetTID() << "\"";
if (!ThreadName.empty()) {
ss << " name=\"" << ThreadName << "\"";
}
Expand Down Expand Up @@ -962,7 +962,7 @@ GdbServer::HandledPacketType GdbServer::handleQuery(const fextl::string& packet)
ss << "m";
for (size_t i = 0; i < Threads->size(); ++i) {
auto Thread = Threads->at(i);
ss << std::hex << Thread->ThreadManager.TID;
ss << std::hex << Thread->Thread->ThreadManager.TID;
if (i != (Threads->size() - 1)) {
ss << ",";
}
Expand All @@ -985,7 +985,7 @@ GdbServer::HandledPacketType GdbServer::handleQuery(const fextl::string& packet)
// Returns the current Thread ID
auto Threads = SyscallHandler->TM.GetThreads();
fextl::ostringstream ss;
ss << "m" << std::hex << Threads->at(0)->ThreadManager.TID;
ss << "m" << std::hex << Threads->at(0)->Thread->ThreadManager.TID;
return {ss.str(), HandledPacketType::TYPE_ACK};
}
if (match("QStartNoAckMode")) {
Expand Down
24 changes: 12 additions & 12 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ constexpr static uint32_t X86_MINSIGSTKSZ = 0x2000U;
static SignalDelegator* GlobalDelegator {};

struct ThreadState {
FEXCore::Core::InternalThreadState* Thread {};
FEX::HLE::ThreadStateObject* Thread {};

void* AltStackPtr {};
stack_t GuestAltStack {
Expand Down Expand Up @@ -148,19 +148,19 @@ void SignalDelegator::HandleSignal(int Signal, void* Info, void* UContext) {
} else {
SignalHandler& Handler = HostHandlers[Signal];
for (auto& HandlerFunc : Handler.Handlers) {
if (HandlerFunc(Thread, Signal, Info, UContext)) {
if (HandlerFunc(Thread->Thread, Signal, Info, UContext)) {
// If the host handler handled the fault then we can continue now
return;
}
}

if (Handler.FrontendHandler && Handler.FrontendHandler(Thread, Signal, Info, UContext)) {
if (Handler.FrontendHandler && Handler.FrontendHandler(Thread->Thread, Signal, Info, UContext)) {
return;
}

// Now let the frontend handle the signal
// It's clearly a guest signal and this ends up being an OS specific issue
HandleGuestSignal(Thread, Signal, Info, UContext);
HandleGuestSignal(Thread->Thread, Signal, Info, UContext);
}
}

Expand Down Expand Up @@ -1739,11 +1739,11 @@ SignalDelegator::~SignalDelegator() {
GlobalDelegator = nullptr;
}

FEXCore::Core::InternalThreadState* SignalDelegator::GetTLSThread() {
FEX::HLE::ThreadStateObject* SignalDelegator::GetTLSThread() {
return ThreadData.Thread;
}

void SignalDelegator::RegisterTLSState(FEXCore::Core::InternalThreadState* Thread) {
void SignalDelegator::RegisterTLSState(FEX::HLE::ThreadStateObject* Thread) {
ThreadData.Thread = Thread;

// Set up our signal alternative stack
Expand All @@ -1764,14 +1764,14 @@ void SignalDelegator::RegisterTLSState(FEXCore::Core::InternalThreadState* Threa
// Get the current host signal mask
::syscall(SYS_rt_sigprocmask, 0, nullptr, &ThreadData.CurrentSignalMask.Val, 8);

if (Thread != (FEXCore::Core::InternalThreadState*)UINTPTR_MAX) {
if (Thread->Thread) {
// Reserve a small amount of deferred signal frames. Usually the stack won't be utilized beyond
// 1 or 2 signals but add a few more just in case.
Thread->DeferredSignalFrames.reserve(8);
Thread->Thread->DeferredSignalFrames.reserve(8);
}
}

void SignalDelegator::UninstallTLSState(FEXCore::Core::InternalThreadState* Thread) {
void SignalDelegator::UninstallTLSState(FEX::HLE::ThreadStateObject* Thread) {
FEXCore::Allocator::munmap(ThreadData.AltStackPtr, SIGSTKSZ * 16);

ThreadData.AltStackPtr = nullptr;
Expand Down Expand Up @@ -1874,7 +1874,7 @@ uint64_t SignalDelegator::RegisterGuestSigAltStack(const stack_t* ss, stack_t* o
bool UsingAltStack {};
uint64_t AltStackBase = reinterpret_cast<uint64_t>(ThreadData.GuestAltStack.ss_sp);
uint64_t AltStackEnd = AltStackBase + ThreadData.GuestAltStack.ss_size;
uint64_t GuestSP = Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP];
uint64_t GuestSP = Thread->Thread->CurrentFrame->State.gregs[FEXCore::X86State::REG_RSP];

if (!(ThreadData.GuestAltStack.ss_flags & SS_DISABLE) && GuestSP >= AltStackBase && GuestSP <= AltStackEnd) {
UsingAltStack = true;
Expand Down Expand Up @@ -1977,7 +1977,7 @@ uint64_t SignalDelegator::GuestSigProcMask(int how, const uint64_t* set, uint64_
*oldset = OldSet;
}

CheckForPendingSignals(GetTLSThread());
CheckForPendingSignals(GetTLSThread()->Thread);

return 0;
}
Expand Down Expand Up @@ -2040,7 +2040,7 @@ uint64_t SignalDelegator::GuestSigSuspend(uint64_t* set, size_t sigsetsize) {
// then this is safe-ish
ThreadData.CurrentSignalMask = ThreadData.PreviousSuspendMask;

CheckForPendingSignals(GetTLSThread());
CheckForPendingSignals(GetTLSThread()->Thread);

return Result == -1 ? -errno : Result;
}
Expand Down
6 changes: 3 additions & 3 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/SignalDelegator.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ class SignalDelegator final : public FEXCore::SignalDelegator, public FEXCore::A
// Called from the signal trampoline function.
void HandleSignal(int Signal, void* Info, void* UContext);

void RegisterTLSState(FEXCore::Core::InternalThreadState* Thread);
void UninstallTLSState(FEXCore::Core::InternalThreadState* Thread);
void RegisterTLSState(FEX::HLE::ThreadStateObject* Thread);
void UninstallTLSState(FEX::HLE::ThreadStateObject* Thread);

/**
* @brief Registers a signal handler for the host to handle a signal
Expand Down Expand Up @@ -134,7 +134,7 @@ class SignalDelegator final : public FEXCore::SignalDelegator, public FEXCore::A

void SaveTelemetry();
private:
FEXCore::Core::InternalThreadState* GetTLSThread();
FEX::HLE::ThreadStateObject* GetTLSThread();

// Called from the thunk handler to handle the signal
void HandleGuestSignal(FEXCore::Core::InternalThreadState* Thread, int Signal, void* Info, void* UContext);
Expand Down
12 changes: 6 additions & 6 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ static bool AllFlagsSet(uint64_t Flags, uint64_t Mask) {
}

struct StackFrameData {
FEXCore::Core::InternalThreadState* Thread {};
FEX::HLE::ThreadStateObject* Thread {};
FEXCore::Context::Context* CTX {};
FEXCore::Core::CpuStateFrame NewFrame {};
FEX::HLE::clone3_args GuestArgs {};
Expand Down Expand Up @@ -443,7 +443,7 @@ static void PrintFlags(uint64_t Flags) {

static uint64_t Clone2Handler(FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::clone3_args* args) {
StackFrameData* Data = (StackFrameData*)FEXCore::Allocator::malloc(sizeof(StackFrameData));
Data->Thread = Frame->Thread;
Data->Thread = static_cast<FEX::HLE::ThreadStateObject*>(Frame->Thread->FrontendPtr);
Data->CTX = Frame->Thread->CTX;
Data->GuestArgs = *args;

Expand All @@ -469,7 +469,7 @@ static uint64_t Clone3Handler(FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::clo
constexpr size_t Offset = sizeof(StackFramePlusRet);
StackFramePlusRet* Data = (StackFramePlusRet*)(reinterpret_cast<uint64_t>(args->NewStack) + args->StackSize - Offset);
Data->Ret = (uint64_t)Clone3HandlerRet;
Data->Data.Thread = Frame->Thread;
Data->Data.Thread = static_cast<FEX::HLE::ThreadStateObject*>(Frame->Thread->FrontendPtr);
Data->Data.CTX = Frame->Thread->CTX;
Data->Data.GuestArgs = *args;

Expand Down Expand Up @@ -609,17 +609,17 @@ uint64_t CloneHandler(FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::clone3_args
auto NewThread = FEX::HLE::CreateNewThread(Thread->CTX, Frame, args);

// Return the new threads TID
uint64_t Result = NewThread->ThreadManager.GetTID();
uint64_t Result = NewThread->Thread->ThreadManager.GetTID();

// Actually start the thread
FEX::HLE::_SyscallHandler->TM.RunThread(NewThread);

if (flags & CLONE_VFORK) {
// If VFORK is set then the calling process is suspended until the thread exits with execve or exit
NewThread->ExecutionThread->join(nullptr);
NewThread->Thread->ExecutionThread->join(nullptr);

// Normally a thread cleans itself up on exit. But because we need to join, we are now responsible
Thread->CTX->DestroyThread(NewThread);
FEX::HLE::_SyscallHandler->TM.DestroyThread(NewThread);
}

SYSCALL_ERRNO();
Expand Down
Loading

0 comments on commit d372552

Please sign in to comment.