linux-user: Add support for 'rt_sigtimedwait_time64()' and 'sched_rr_get_interval_time64()'

This patch implements functionality for following time64 syscalls:

*rt_sigtimedwait_time64()

    This is a year 2038 safe variant of syscall:

    int rt_sigtimedwait(const sigset_t *set, siginfo_t *info,
                        const struct timespec *timeout, size_t sigsetsize)
    --synchronously wait for queued signals--
    man page: https://man7.org/linux/man-pages/man2/rt_sigtimedwait.2.html

*sched_rr_get_interval_time64()

    This is a year 2038 safe variant of syscall:

    int sched_rr_get_interval(pid_t pid, struct timespec *tp)
    --get  the  SCHED_RR  interval  for the named process--
    man page: https://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html

Implementation notes:

    These syscalls were implemented in similar ways like
    'rt_sigtimedwait()' and 'sched_rr_get_interval()' except
    that functions 'target_to_host_timespec64()' and
    'host_to_target_timespec64()' were used to convert values
    of 'struct timespec' between host and target.

Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20200824192116.65562-3-Filip.Bozuta@syrmia.com>
[lv: add missing defined(TARGET_NR_rt_sigtimedwait_time64)]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
Filip Bozuta 2020-08-24 21:21:16 +02:00 committed by Laurent Vivier
parent 6ac03b2cac
commit ddcbde157d

View File

@ -764,7 +764,7 @@ safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
safe_syscall2(int, flock, int, fd, int, operation)
#ifdef TARGET_NR_rt_sigtimedwait
#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
const struct timespec *, uts, size_t, sigsetsize)
#endif
@ -1243,7 +1243,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts,
defined(TARGET_NR_mq_timedsend_time64) || \
defined(TARGET_NR_mq_timedreceive_time64) || \
(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
defined(TARGET_NR_clock_nanosleep_time64)
defined(TARGET_NR_clock_nanosleep_time64) || \
defined(TARGET_NR_rt_sigtimedwait_time64)
static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
abi_ulong target_addr)
{
@ -9044,6 +9045,48 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
}
return ret;
#endif
#ifdef TARGET_NR_rt_sigtimedwait_time64
case TARGET_NR_rt_sigtimedwait_time64:
{
sigset_t set;
struct timespec uts, *puts;
siginfo_t uinfo;
if (arg4 != sizeof(target_sigset_t)) {
return -TARGET_EINVAL;
}
p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
if (!p) {
return -TARGET_EFAULT;
}
target_to_host_sigset(&set, p);
unlock_user(p, arg1, 0);
if (arg3) {
puts = &uts;
if (target_to_host_timespec64(puts, arg3)) {
return -TARGET_EFAULT;
}
} else {
puts = NULL;
}
ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
SIGSET_T_SIZE));
if (!is_error(ret)) {
if (arg2) {
p = lock_user(VERIFY_WRITE, arg2,
sizeof(target_siginfo_t), 0);
if (!p) {
return -TARGET_EFAULT;
}
host_to_target_siginfo(p, &uinfo);
unlock_user(p, arg2, sizeof(target_siginfo_t));
}
ret = host_to_target_signal(ret);
}
}
return ret;
#endif
case TARGET_NR_rt_sigqueueinfo:
{
@ -10568,6 +10611,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
return ret;
#endif
#ifdef TARGET_NR_sched_rr_get_interval_time64
case TARGET_NR_sched_rr_get_interval_time64:
{
struct timespec ts;
ret = get_errno(sched_rr_get_interval(arg1, &ts));
if (!is_error(ret)) {
ret = host_to_target_timespec64(arg2, &ts);
}
}
return ret;
#endif
#if defined(TARGET_NR_nanosleep)
case TARGET_NR_nanosleep:
{