diff --git a/Source/Tests/LinuxSyscalls/SignalDelegator.cpp b/Source/Tests/LinuxSyscalls/SignalDelegator.cpp index cc9846bd8..5b3a68596 100644 --- a/Source/Tests/LinuxSyscalls/SignalDelegator.cpp +++ b/Source/Tests/LinuxSyscalls/SignalDelegator.cpp @@ -611,4 +611,23 @@ namespace FEX::HLE { return Result == -1 ? -errno : Result; } + + uint64_t SignalDelegator::GuestSigTimedWait(uint64_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) { + if (sigsetsize > sizeof(uint64_t)) { + return -EINVAL; + } + + sigset_t HostSet{}; + sigemptyset(&HostSet); + + for (int32_t i = 0; i < MAX_SIGNALS; ++i) { + if (*set & (1ULL << i)) { + sigaddset(&HostSet, i + 1); + } + } + + uint64_t Result = sigtimedwait(&HostSet, info, timeout); + + return Result == -1 ? -errno : Result; + } } diff --git a/Source/Tests/LinuxSyscalls/SignalDelegator.h b/Source/Tests/LinuxSyscalls/SignalDelegator.h index 4d09d64da..e63abb796 100644 --- a/Source/Tests/LinuxSyscalls/SignalDelegator.h +++ b/Source/Tests/LinuxSyscalls/SignalDelegator.h @@ -81,6 +81,7 @@ namespace FEX::HLE { uint64_t GuestSigProcMask(int how, const uint64_t *set, uint64_t *oldset); uint64_t GuestSigPending(uint64_t *set, size_t sigsetsize); uint64_t GuestSigSuspend(uint64_t *set, size_t sigsetsize); + uint64_t GuestSigTimedWait(uint64_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize); // Called from the thunk handler to handle the signal void HandleSignal(int Signal, void *Info, void *UContext); diff --git a/Source/Tests/LinuxSyscalls/Syscalls/Stubs.cpp b/Source/Tests/LinuxSyscalls/Syscalls/Stubs.cpp index daec3e978..304734a48 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls/Stubs.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls/Stubs.cpp @@ -40,10 +40,6 @@ namespace FEX::HLE { return -EPERM; }); - REGISTER_SYSCALL_IMPL(rt_sigtimedwait, [](FEXCore::Core::CpuStateFrame *Frame, sigset_t *set, const struct timespec*, size_t sigsetsize) -> uint64_t { - SYSCALL_STUB(rt_sigtimedwait); - }); - REGISTER_SYSCALL_IMPL(rt_sigqueueinfo, [](FEXCore::Core::CpuStateFrame *Frame, pid_t pid, int sig, siginfo_t *uinfo) -> uint64_t { SYSCALL_STUB(rt_sigqueueinfo); }); diff --git a/Source/Tests/LinuxSyscalls/x32/Signals.cpp b/Source/Tests/LinuxSyscalls/x32/Signals.cpp index f68dc2bcf..4f65e74de 100644 --- a/Source/Tests/LinuxSyscalls/x32/Signals.cpp +++ b/Source/Tests/LinuxSyscalls/x32/Signals.cpp @@ -52,5 +52,16 @@ namespace FEX::HLE::x32 { SYSCALL_ERRNO(); }); + REGISTER_SYSCALL_IMPL_X32(rt_sigtimedwait, [](FEXCore::Core::CpuStateFrame *Frame, uint64_t *set, siginfo_t *info, const struct timespec32* timeout, size_t sigsetsize) -> uint64_t { + struct timespec* timeout_ptr{}; + struct timespec tp64{}; + if (timeout) { + tp64 = *timeout; + timeout_ptr = &tp64; + } + + return FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, info, timeout_ptr, sigsetsize); + }); + } } diff --git a/Source/Tests/LinuxSyscalls/x64/Signals.cpp b/Source/Tests/LinuxSyscalls/x64/Signals.cpp index 63134ae41..8dfa6c28e 100644 --- a/Source/Tests/LinuxSyscalls/x64/Signals.cpp +++ b/Source/Tests/LinuxSyscalls/x64/Signals.cpp @@ -20,6 +20,10 @@ namespace FEX::HLE::x64 { REGISTER_SYSCALL_IMPL_X64(rt_sigaction, [](FEXCore::Core::CpuStateFrame *Frame, int signum, const FEXCore::GuestSigAction *act, FEXCore::GuestSigAction *oldact) -> uint64_t { return FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSignalHandler(signum, act, oldact); }); + + REGISTER_SYSCALL_IMPL_X64(rt_sigtimedwait, [](FEXCore::Core::CpuStateFrame *Frame, uint64_t *set, siginfo_t *info, const struct timespec* timeout, size_t sigsetsize) -> uint64_t { + return FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, info, timeout, sigsetsize); + }); } }