mirror of
https://github.com/FEX-Emu/FEX.git
synced 2025-01-31 11:32:07 +00:00
Merge pull request #3290 from Sonicadvance1/move_signaldelegator
FEXCore: Moves more SignalDelegator functions to the frontend
This commit is contained in:
commit
6e8af295c5
@ -100,7 +100,6 @@ set (SRCS
|
||||
Interface/Core/OpcodeDispatcher/X87.cpp
|
||||
Interface/Core/OpcodeDispatcher/X87F64.cpp
|
||||
Interface/Core/OpcodeDispatcher.cpp
|
||||
Interface/Core/SignalDelegator.cpp
|
||||
Interface/Core/X86Tables.cpp
|
||||
Interface/Core/X86HelperGen.cpp
|
||||
Interface/Core/ArchHelpers/Arm64Emitter.cpp
|
||||
|
@ -1,41 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include <FEXCore/Core/SignalDelegator.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXHeaderUtils/Syscalls.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
namespace FEXCore {
|
||||
void SignalDelegator::RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
SetHostSignalHandler(Signal, Func, Required);
|
||||
FrontendRegisterHostSignalHandler(Signal, Func, Required);
|
||||
}
|
||||
|
||||
void SignalDelegator::HandleSignal(int Signal, void *Info, void *UContext) {
|
||||
// Let the host take first stab at handling the signal
|
||||
auto Thread = GetTLSThread();
|
||||
HostSignalHandler &Handler = HostHandlers[Signal];
|
||||
|
||||
if (!Thread) {
|
||||
LogMan::Msg::AFmt("[{}] Thread has received a signal and hasn't registered itself with the delegate! Programming error!", FHU::Syscalls::gettid());
|
||||
}
|
||||
else {
|
||||
for (auto &Handler : Handler.Handlers) {
|
||||
if (Handler(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)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,8 +35,6 @@ namespace Core {
|
||||
#endif
|
||||
};
|
||||
}
|
||||
using HostSignalDelegatorFunction = std::function<bool(FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext)>;
|
||||
|
||||
class SignalDelegator {
|
||||
public:
|
||||
virtual ~SignalDelegator() = default;
|
||||
@ -49,16 +47,6 @@ namespace Core {
|
||||
virtual void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) = 0;
|
||||
virtual void UninstallTLSState(FEXCore::Core::InternalThreadState *Thread) = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required);
|
||||
|
||||
// Called from the thunk handler to handle the signal
|
||||
void HandleSignal(int Signal, void *Info, void *UContext);
|
||||
|
||||
/**
|
||||
* @brief Check to ensure the XID handler is still set to the FEX handler
|
||||
*
|
||||
@ -67,12 +55,6 @@ namespace Core {
|
||||
*/
|
||||
virtual void CheckXIDHandler() = 0;
|
||||
|
||||
constexpr static size_t MAX_SIGNALS {64};
|
||||
|
||||
// Use the last signal just so we are less likely to ever conflict with something that the guest application is using
|
||||
// 64 is used internally by Valgrind
|
||||
constexpr static size_t SIGNAL_FOR_PAUSE {63};
|
||||
|
||||
struct SignalDelegatorConfig {
|
||||
bool StaticRegisterAllocation{};
|
||||
bool SupportsAVX{};
|
||||
@ -124,31 +106,5 @@ namespace Core {
|
||||
|
||||
protected:
|
||||
SignalDelegatorConfig Config;
|
||||
|
||||
virtual FEXCore::Core::InternalThreadState *GetTLSThread() = 0;
|
||||
virtual void HandleGuestSignal(FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
virtual void FrontendRegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) = 0;
|
||||
virtual void FrontendRegisterFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) = 0;
|
||||
|
||||
private:
|
||||
struct HostSignalHandler {
|
||||
fextl::vector<FEXCore::HostSignalDelegatorFunction> Handlers{};
|
||||
FEXCore::HostSignalDelegatorFunction FrontendHandler{};
|
||||
};
|
||||
std::array<HostSignalHandler, MAX_SIGNALS + 1> HostHandlers{};
|
||||
|
||||
protected:
|
||||
void SetHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
HostHandlers[Signal].Handlers.push_back(std::move(Func));
|
||||
}
|
||||
void SetFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
HostHandlers[Signal].FrontendHandler = std::move(Func);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -34,21 +34,11 @@ class DummySignalDelegator final : public FEXCore::SignalDelegator, public FEXCo
|
||||
}
|
||||
|
||||
protected:
|
||||
// Called from the thunk handler to handle the signal
|
||||
void HandleGuestSignal(FEXCore::Core::InternalThreadState *Thread, int Signal, void *Info, void *UContext) override {}
|
||||
|
||||
void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) override;
|
||||
void UninstallTLSState(FEXCore::Core::InternalThreadState *Thread) override;
|
||||
|
||||
FEXCore::Core::InternalThreadState *GetTLSThread() override;
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void FrontendRegisterHostSignalHandler(int Signal, FEXCore::HostSignalDelegatorFunction Func, bool Required) override {}
|
||||
void FrontendRegisterFrontendHostSignalHandler(int Signal, FEXCore::HostSignalDelegatorFunction Func, bool Required) override {}
|
||||
private:
|
||||
FEXCore::Core::InternalThreadState *GetTLSThread();
|
||||
};
|
||||
|
||||
fextl::unique_ptr<FEXCore::HLE::SyscallHandler> CreateSyscallHandler();
|
||||
|
@ -79,7 +79,7 @@ GdbServer::~GdbServer() {
|
||||
close(ListenSocket);
|
||||
}
|
||||
|
||||
GdbServer::GdbServer(FEXCore::Context::Context *ctx, FEXCore::SignalDelegator *SignalDelegation, FEXCore::HLE::SyscallHandler *const SyscallHandler)
|
||||
GdbServer::GdbServer(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *SignalDelegation, FEXCore::HLE::SyscallHandler *const SyscallHandler)
|
||||
: CTX(ctx)
|
||||
, SyscallHandler {SyscallHandler} {
|
||||
// Pass all signals by default
|
||||
@ -97,7 +97,7 @@ GdbServer::GdbServer(FEXCore::Context::Context *ctx, FEXCore::SignalDelegator *S
|
||||
|
||||
// This is a total hack as there is currently no way to resume once hitting a segfault
|
||||
// But it's semi-useful for debugging.
|
||||
for (uint32_t Signal = 0; Signal <= FEXCore::SignalDelegator::MAX_SIGNALS; ++Signal) {
|
||||
for (uint32_t Signal = 0; Signal <= FEX::HLE::SignalDelegator::MAX_SIGNALS; ++Signal) {
|
||||
SignalDelegation->RegisterHostSignalHandler(Signal, [this] (FEXCore::Core::InternalThreadState *Thread, int Signal, void *info, void *ucontext) {
|
||||
if (PassSignals[Signal]) {
|
||||
// Pass signal to the guest
|
||||
@ -989,7 +989,7 @@ GdbServer::HandledPacketType GdbServer::handleQuery(const fextl::string &packet)
|
||||
// We now have a semi-colon deliminated list of signals to pass to the guest process
|
||||
for (fextl::string tmp; std::getline(ss, tmp, ';'); ) {
|
||||
uint32_t Signal = std::stoi(tmp.c_str(), nullptr, 16);
|
||||
if (Signal < FEXCore::SignalDelegator::MAX_SIGNALS) {
|
||||
if (Signal < FEX::HLE::SignalDelegator::MAX_SIGNALS) {
|
||||
PassSignals[Signal] = true;
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,13 @@ $end_info$
|
||||
#include <mutex>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "LinuxSyscalls/SignalDelegator.h"
|
||||
|
||||
namespace FEX {
|
||||
|
||||
class GdbServer {
|
||||
public:
|
||||
GdbServer(FEXCore::Context::Context *ctx, FEXCore::SignalDelegator *SignalDelegation, FEXCore::HLE::SyscallHandler *const SyscallHandler);
|
||||
GdbServer(FEXCore::Context::Context *ctx, FEX::HLE::SignalDelegator *SignalDelegation, FEXCore::HLE::SyscallHandler *const SyscallHandler);
|
||||
~GdbServer();
|
||||
|
||||
// Public for threading
|
||||
@ -96,7 +98,7 @@ private:
|
||||
fextl::string LibraryMapString{};
|
||||
|
||||
// Used to keep track of which signals to pass to the guest
|
||||
std::array<bool, FEXCore::SignalDelegator::MAX_SIGNALS + 1> PassSignals{};
|
||||
std::array<bool, FEX::HLE::SignalDelegator::MAX_SIGNALS + 1> PassSignals{};
|
||||
uint32_t CurrentDebuggingThread{};
|
||||
int ListenSocket{};
|
||||
fextl::string GdbUnixSocketPath{};
|
||||
|
@ -150,6 +150,38 @@ namespace FEX::HLE {
|
||||
return SigInfoLayout::LAYOUT_KILL;
|
||||
}
|
||||
|
||||
void SignalDelegator::HandleSignal(int Signal, void *Info, void *UContext) {
|
||||
// Let the host take first stab at handling the signal
|
||||
auto Thread = GetTLSThread();
|
||||
|
||||
if (!Thread) {
|
||||
LogMan::Msg::AFmt("[{}] Thread has received a signal and hasn't registered itself with the delegate! Programming error!", FHU::Syscalls::gettid());
|
||||
}
|
||||
else {
|
||||
SignalHandler &Handler = HostHandlers[Signal];
|
||||
for (auto &HandlerFunc : Handler.Handlers) {
|
||||
if (HandlerFunc(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)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void SignalDelegator::RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
SetHostSignalHandler(Signal, Func, Required);
|
||||
FrontendRegisterHostSignalHandler(Signal, Func, Required);
|
||||
}
|
||||
|
||||
void SignalDelegator::SpillSRA(FEXCore::Core::InternalThreadState *Thread, void *ucontext, uint32_t IgnoreMask) {
|
||||
#ifdef _M_ARM_64
|
||||
for (size_t i = 0; i < Config.SRAGPRCount; i++) {
|
||||
@ -1811,7 +1843,7 @@ namespace FEX::HLE {
|
||||
ThreadData.Thread = nullptr;
|
||||
}
|
||||
|
||||
void SignalDelegator::FrontendRegisterHostSignalHandler(int Signal, FEXCore::HostSignalDelegatorFunction Func, bool Required) {
|
||||
void SignalDelegator::FrontendRegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
// Linux signal handlers are per-process rather than per thread
|
||||
// Multiple threads could be calling in to this
|
||||
std::lock_guard lk(HostDelegatorMutex);
|
||||
@ -1819,7 +1851,7 @@ namespace FEX::HLE {
|
||||
InstallHostThunk(Signal);
|
||||
}
|
||||
|
||||
void SignalDelegator::FrontendRegisterFrontendHostSignalHandler(int Signal, FEXCore::HostSignalDelegatorFunction Func, bool Required) {
|
||||
void SignalDelegator::FrontendRegisterFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
// Linux signal handlers are per-process rather than per thread
|
||||
// Multiple threads could be calling in to this
|
||||
std::lock_guard lk(HostDelegatorMutex);
|
||||
|
@ -40,20 +40,36 @@ namespace FEX::HLE {
|
||||
|
||||
class SignalDelegator final : public FEXCore::SignalDelegator, public FEXCore::Allocator::FEXAllocOperators {
|
||||
public:
|
||||
constexpr static size_t MAX_SIGNALS {64};
|
||||
|
||||
// Use the last signal just so we are less likely to ever conflict with something that the guest application is using
|
||||
// 64 is used internally by Valgrind
|
||||
constexpr static size_t SIGNAL_FOR_PAUSE {63};
|
||||
|
||||
// Returns true if the host handled the signal
|
||||
// Arguments are the same as sigaction handler
|
||||
SignalDelegator(FEXCore::Context::Context *_CTX, const std::string_view ApplicationName);
|
||||
~SignalDelegator() override;
|
||||
|
||||
// Called from the signal trampoline function.
|
||||
void HandleSignal(int Signal, void *Info, void *UContext);
|
||||
|
||||
void RegisterTLSState(FEXCore::Core::InternalThreadState *Thread) override;
|
||||
void UninstallTLSState(FEXCore::Core::InternalThreadState *Thread) override;
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void RegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required);
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal specifically for guest handling
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void RegisterHostSignalHandlerForGuest(int Signal, FEX::HLE::HostSignalDelegatorFunctionForGuest Func);
|
||||
void RegisterHostSignalHandlerForGuest(int Signal, HostSignalDelegatorFunctionForGuest Func);
|
||||
void RegisterFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required);
|
||||
|
||||
/**
|
||||
@ -107,21 +123,27 @@ namespace FEX::HLE {
|
||||
FEX_CONFIG_OPT(ParanoidTSO, PARANOIDTSO);
|
||||
|
||||
void SaveTelemetry();
|
||||
protected:
|
||||
// Called from the thunk handler to handle the signal
|
||||
void HandleGuestSignal(FEXCore::Core::InternalThreadState *Thread, int Signal, void *Info, void *UContext) override;
|
||||
private:
|
||||
FEXCore::Core::InternalThreadState *GetTLSThread();
|
||||
|
||||
FEXCore::Core::InternalThreadState *GetTLSThread() override;
|
||||
// Called from the thunk handler to handle the signal
|
||||
void HandleGuestSignal(FEXCore::Core::InternalThreadState *Thread, int Signal, void *Info, void *UContext);
|
||||
|
||||
/**
|
||||
* @brief Registers a signal handler for the host to handle a signal
|
||||
*
|
||||
* It's a process level signal handler so one must be careful
|
||||
*/
|
||||
void FrontendRegisterHostSignalHandler(int Signal, FEXCore::HostSignalDelegatorFunction Func, bool Required) override;
|
||||
void FrontendRegisterFrontendHostSignalHandler(int Signal, FEXCore::HostSignalDelegatorFunction Func, bool Required) override;
|
||||
void FrontendRegisterHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required);
|
||||
void FrontendRegisterFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required);
|
||||
|
||||
void SetHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
HostHandlers[Signal].Handlers.push_back(std::move(Func));
|
||||
}
|
||||
void SetFrontendHostSignalHandler(int Signal, HostSignalDelegatorFunction Func, bool Required) {
|
||||
HostHandlers[Signal].FrontendHandler = std::move(Func);
|
||||
}
|
||||
|
||||
private:
|
||||
FEX_CONFIG_OPT(Is64BitMode, IS64BIT_MODE);
|
||||
FEX_CONFIG_OPT(Core, CORE);
|
||||
fextl::string const ApplicationName;
|
||||
@ -155,6 +177,10 @@ namespace FEX::HLE {
|
||||
FEX::HLE::HostSignalDelegatorFunctionForGuest GuestHandler{};
|
||||
GuestSigAction GuestAction{};
|
||||
DefaultBehaviour DefaultBehaviour {DEFAULT_TERM};
|
||||
|
||||
// Callbacks
|
||||
fextl::vector<HostSignalDelegatorFunction> Handlers{};
|
||||
HostSignalDelegatorFunction FrontendHandler{};
|
||||
};
|
||||
|
||||
std::array<SignalHandler, MAX_SIGNALS + 1> HostHandlers{};
|
||||
|
Loading…
x
Reference in New Issue
Block a user