Merge pull request #1275 from Sonicadvance1/implement_timer_create

Linux: Implements support for timer_create
This commit is contained in:
Ryan Houdek authored and GitHub committed 2021-09-12 17:34:06 -07:00
commit f232dcebfc
6 files changed
+157 -18

No files matched your search

+1 -10
View File
@@ -572,16 +572,7 @@ namespace FEX::HLE {
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);
uint64_t Result = ::syscall(SYS_rt_sigtimedwait, set, info, timeout);
return Result == -1 ? -errno : Result;
}
@@ -25,11 +25,6 @@ namespace FEX::HLE {
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL(timer_create, [](FEXCore::Core::CpuStateFrame *Frame, clockid_t clockid, struct sigevent *sevp, kernel_timer_t *timerid) -> uint64_t {
uint64_t Result = ::syscall(SYS_timer_create, clockid, sevp, timerid);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL(timer_getoverrun, [](FEXCore::Core::CpuStateFrame *Frame, kernel_timer_t timerid) -> uint64_t {
uint64_t Result = ::syscall(SYS_timer_getoverrun, timerid);
SYSCALL_ERRNO();
+67 -2
View File
@@ -10,6 +10,7 @@ $end_info$
#include "Tests/LinuxSyscalls/x32/Types.h"
#include <FEXCore/Core/SignalDelegator.h>
#include <FEXCore/Core/UContext.h>
#include <errno.h>
#include <bits/types/siginfo_t.h>
#include <stdint.h>
@@ -20,6 +21,53 @@ namespace FEXCore::Core {
}
namespace FEX::HLE::x32 {
void CopySigInfo(FEXCore::x86::siginfo_t *Info, siginfo_t const &Host) {
// Copy the basic things first
Info->si_signo = Host.si_signo;
Info->si_errno = Host.si_errno;
Info->si_code = Host.si_code;
// Check si_code to determine how we need to interpret this
if (Info->si_code == SI_TIMER) {
// SI_TIMER means pid, uid, value
Info->_sifields._timer.tid = Host.si_timerid;
Info->_sifields._timer.overrun = Host.si_overrun;
Info->_sifields._timer.sigval.sival_int = Host.si_value.sival_int;
}
else {
// Now we need to copy over the more complex things
switch (Info->si_signo) {
case SIGSEGV:
case SIGBUS:
// This is the address trying to be accessed, not the RIP
Info->_sifields._sigfault.addr = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(Host.si_addr));
break;
case SIGFPE:
case SIGILL:
// Can't really give a real result here. This is the RIP causing a sigill or sigfpe
// Claim at RIP 0 for now
Info->_sifields._sigfault.addr = 0;
break;
case SIGCHLD:
Info->_sifields._sigchld.pid = Host.si_pid;
Info->_sifields._sigchld.uid = Host.si_uid;
Info->_sifields._sigchld.status = Host.si_status;
Info->_sifields._sigchld.utime = Host.si_utime;
Info->_sifields._sigchld.stime = Host.si_stime;
break;
case SIGALRM:
case SIGVTALRM:
Info->_sifields._timer.tid = Host.si_timerid;
Info->_sifields._timer.overrun = Host.si_overrun;
Info->_sifields._timer.sigval.sival_int = Host.si_int;
break;
default:
LogMan::Msg::E("Unhandled siginfo_t for sigtimedwait: %d", Info->si_signo);
break;
}
}
}
void RegisterSignals() {
REGISTER_SYSCALL_IMPL_X32(sigpending, [](FEXCore::Core::CpuStateFrame *Frame, compat_old_sigset_t *set) -> uint64_t {
uint64_t HostSet{};
@@ -66,7 +114,7 @@ namespace FEX::HLE::x32 {
return Result;
});
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 {
REGISTER_SYSCALL_IMPL_X32(rt_sigtimedwait, [](FEXCore::Core::CpuStateFrame *Frame, uint64_t *set, compat_ptr<FEXCore::x86::siginfo_t> info, const struct timespec32* timeout, size_t sigsetsize) -> uint64_t {
struct timespec* timeout_ptr{};
struct timespec tp64{};
if (timeout) {
@@ -74,7 +122,24 @@ namespace FEX::HLE::x32 {
timeout_ptr = &tp64;
}
return FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, info, timeout_ptr, sigsetsize);
siginfo_t HostInfo{};
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, &HostInfo, timeout_ptr, sigsetsize);
if (Result != -1) {
// We need to translate the 64-bit siginfo_t to 32-bit siginfo_t
CopySigInfo(info, HostInfo);
}
return Result;
});
REGISTER_SYSCALL_IMPL_X32(rt_sigtimedwait_time64, [](FEXCore::Core::CpuStateFrame *Frame, uint64_t *set, compat_ptr<FEXCore::x86::siginfo_t> info, const struct timespec* timeout, size_t sigsetsize) -> uint64_t {
siginfo_t HostInfo{};
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->GuestSigTimedWait(set, &HostInfo, timeout, sigsetsize);
if (Result != -1) {
// We need to translate the 64-bit siginfo_t to 32-bit siginfo_t
CopySigInfo(info, HostInfo);
}
return Result;
});
}
+6
View File
@@ -96,5 +96,11 @@ namespace FEX::HLE::x32 {
}
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X32(timer_create, [](FEXCore::Core::CpuStateFrame *Frame, clockid_t clockid, compat_ptr<FEX::HLE::x32::sigevent32> sevp, kernel_timer_t *timerid) -> uint64_t {
sigevent Host = *sevp;
uint64_t Result = ::syscall(SYS_timer_create, clockid, &Host, timerid);
SYSCALL_ERRNO();
});
}
}
+77 -1
View File
@@ -13,6 +13,7 @@ $end_info$
#include <cstdint>
#include <cstring>
#include <fcntl.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -962,7 +963,6 @@ rlimit32 {
static_assert(std::is_trivial<rlimit32<true>>::value, "Needs to be trivial");
static_assert(sizeof(rlimit32<true>) == 8, "Incorrect size");
struct
FEX_ANNOTATE("alias-x86_32-timex")
FEX_ANNOTATE("fex-match")
@@ -1048,4 +1048,80 @@ timex32 {
static_assert(std::is_trivial<timex32>::value, "Needs to be trivial");
static_assert(sizeof(timex32) == 128, "Incorrect size");
union
FEX_ANNOTATE("alias-x86_32-sigval")
FEX_ANNOTATE("fex-match")
sigval32 {
int sival_int;
compat_ptr<void> sival_ptr;
sigval32() = delete;
operator sigval() const {
sigval val{};
val.sival_ptr = sival_ptr;
return val;
}
sigval32(sigval val) {
sival_ptr = val.sival_ptr;
}
};
static_assert(std::is_trivial<sigval32>::value, "Needs to be trivial");
static_assert(sizeof(sigval32) == 4, "Incorrect size");
constexpr size_t SIGEV_MAX_SIZE = 64;
constexpr size_t SIGEV_PAD_SIZE = (SIGEV_MAX_SIZE - (sizeof(int32_t) * 2 + sizeof(sigval32))) / sizeof(int32_t);
struct
FEX_ANNOTATE("fex-match")
sigevent32 {
FEX::HLE::x32::sigval32 sigev_value;
int sigev_signo;
int sigev_notify;
union {
int _pad[SIGEV_PAD_SIZE];
int _tid;
struct {
uint32_t _function;
uint32_t _attribute;
} _sigev_thread;
} _sigev_un;
sigevent32() = delete;
operator sigevent() const {
sigevent val{};
val.sigev_value = sigev_value;
val.sigev_signo = sigev_signo;
val.sigev_notify = sigev_notify;
if (sigev_notify == SIGEV_THREAD_ID) {
val._sigev_un._tid = _sigev_un._tid;
}
else if (sigev_notify == SIGEV_THREAD) {
val.sigev_notify_function = reinterpret_cast<void(*)(sigval)>(_sigev_un._sigev_thread._function);
val.sigev_notify_attributes = reinterpret_cast<pthread_attr_t*>(_sigev_un._sigev_thread._attribute);
}
return val;
}
sigevent32(sigevent val)
: sigev_value { val.sigev_value } {
sigev_signo = val.sigev_signo;
sigev_notify = val.sigev_notify;
if (sigev_notify == SIGEV_THREAD_ID) {
_sigev_un._tid = val._sigev_un._tid;
}
else if (sigev_notify == SIGEV_THREAD) {
sigev_notify_function = static_cast<uint32_t>(reinterpret_cast<uint64_t>(val._sigev_un._sigev_thread._function));
sigev_notify_attributes = static_cast<uint32_t>(reinterpret_cast<uint64_t>(val._sigev_un._sigev_thread._attribute));
}
}
};
static_assert(std::is_trivial<sigval32>::value, "Needs to be trivial");
static_assert(sizeof(sigval32) == 4, "Incorrect size");
}
+6
View File
@@ -94,6 +94,7 @@ namespace FEX::HLE::x64 {
uint64_t Result = ::syscall(SYS_timer_gettime, timerid, curr_value);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(adjtimex, [](FEXCore::Core::CpuStateFrame *Frame, struct timex *buf) -> uint64_t {
uint64_t Result = ::adjtimex(buf);
SYSCALL_ERRNO();
@@ -103,6 +104,11 @@ namespace FEX::HLE::x64 {
uint64_t Result = ::clock_adjtime(clk_id, buf);
SYSCALL_ERRNO();
});
REGISTER_SYSCALL_IMPL_X64(timer_create, [](FEXCore::Core::CpuStateFrame *Frame, clockid_t clockid, struct sigevent *sevp, kernel_timer_t *timerid) -> uint64_t {
uint64_t Result = ::syscall(SYS_timer_create, clockid, sevp, timerid);
SYSCALL_ERRNO();
});
}
}