mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 15:00:53 +02:00
Merge pull request #1275 from Sonicadvance1/implement_timer_create
Linux: Implements support for timer_create
This commit is contained in:
6 files changed
+157
-18
No files matched your search
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user