diff mbox series

[uclibc-ng-devel] Add time64 support for PowerPC.

Message ID 20240224150047.1039669-1-dm.chestnykh@gmail.com
State Superseded
Headers show
Series [uclibc-ng-devel] Add time64 support for PowerPC. | expand

Commit Message

Dmitry Chestnykh Feb. 24, 2024, 3 p.m. UTC
PowerPC is big-endian architecture, so there are some
significant differences in comparison with time64 support
for little-endian architectures like ARM and xtensa.
The main difference is that we strictly need to pass two 64bit
values to system calls because Linux Kernel internally uses
`struct __ketnel_timespec` and similar, which consists of two
64bit fields.
For this reason many files have been changed to convert
timespec-family structures (mixed of 64bit and 32bit values)
to the 64bit-only structures for using as system calls args.
Now time64 syscalls works properly both for LE (ARM, xtensa)
and BE (PPC) memory layouts.

Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
---
 extra/Configs/Config.in                       |  2 +-
 libc/inet/socketcalls.c                       | 16 ++++++++-
 libc/misc/sysvipc/sem.c                       | 16 ++++++++-
 libc/signal/sigwait.c                         |  3 +-
 libc/sysdeps/linux/common/__rt_sigtimedwait.c | 23 ++++++++++--
 libc/sysdeps/linux/common/__rt_sigwaitinfo.c  |  2 +-
 libc/sysdeps/linux/common/alarm.c             |  2 +-
 libc/sysdeps/linux/common/clock_getres.c      | 20 ++++++++++-
 libc/sysdeps/linux/common/clock_gettime.c     | 21 ++++++++++-
 libc/sysdeps/linux/common/clock_settime.c     | 17 ++++++++-
 libc/sysdeps/linux/common/ppoll.c             | 15 +++++++-
 libc/sysdeps/linux/common/pselect.c           | 15 +++++++-
 libc/sysdeps/linux/common/select.c            | 23 +++++++++---
 libc/sysdeps/linux/common/time.c              |  2 +-
 libc/sysdeps/linux/common/timerfd.c           | 23 +++++++++++-
 libc/sysdeps/linux/common/utimensat.c         | 23 +++++++++++-
 libc/sysdeps/linux/powerpc/bits/kernel_stat.h | 28 +++++++++++++--
 libc/sysdeps/linux/powerpc/bits/sem.h         | 16 +++++++++
 libpthread/nptl/pthread_mutex_timedlock.c     | 20 +++++++++--
 .../sysdeps/pthread/pthread_cond_timedwait.c  |  5 +--
 .../pthread/pthread_rwlock_timedrdlock.c      |  5 +--
 .../pthread/pthread_rwlock_timedwrlock.c      |  5 +--
 .../sysdeps/unix/sysv/linux/lowlevellock.c    | 10 +++---
 .../sysdeps/unix/sysv/linux/lowlevellock.h    | 35 +++++++++++++++++--
 .../unix/sysv/linux/lowlevelrobustlock.c      |  6 ++--
 .../sysdeps/unix/sysv/linux/sem_timedwait.c   |  6 ++--
 .../sysdeps/unix/sysv/linux/timer_settime.c   | 19 +++++++++-
 librt/clock_gettime.c                         | 20 +++++++++--
 librt/clock_nanosleep.c                       | 23 ++++++++++--
 librt/mq_timedreceive.c                       | 22 ++++++++++--
 librt/mq_timedsend.c                          | 20 ++++++++++-
 librt/timer_settime.c                         | 28 +++++++++++++--
 32 files changed, 435 insertions(+), 56 deletions(-)

Comments

Max Filippov Feb. 24, 2024, 4:08 p.m. UTC | #1
On Sat, Feb 24, 2024 at 7:01 AM Dmitry Chestnykh <dm.chestnykh@gmail.com> wrote:
>
> PowerPC is big-endian architecture, so there are some
> significant differences in comparison with time64 support
> for little-endian architectures like ARM and xtensa.

JFYI xtensa supports both little and big endianness. Which
suggests that it needs similar treatment as a BE PPC.

> The main difference is that we strictly need to pass two 64bit
> values to system calls because Linux Kernel internally uses
> `struct __ketnel_timespec` and similar, which consists of two
> 64bit fields.
> For this reason many files have been changed to convert
> timespec-family structures (mixed of 64bit and 32bit values)
> to the 64bit-only structures for using as system calls args.
> Now time64 syscalls works properly both for LE (ARM, xtensa)
> and BE (PPC) memory layouts.

I'd suggest splitting this change into two parts: generic
arch-independent changes followed by PPC-specific changes.

> Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
> ---
>  extra/Configs/Config.in                       |  2 +-
>  libc/inet/socketcalls.c                       | 16 ++++++++-
>  libc/misc/sysvipc/sem.c                       | 16 ++++++++-
>  libc/signal/sigwait.c                         |  3 +-
>  libc/sysdeps/linux/common/__rt_sigtimedwait.c | 23 ++++++++++--
>  libc/sysdeps/linux/common/__rt_sigwaitinfo.c  |  2 +-
>  libc/sysdeps/linux/common/alarm.c             |  2 +-
>  libc/sysdeps/linux/common/clock_getres.c      | 20 ++++++++++-
>  libc/sysdeps/linux/common/clock_gettime.c     | 21 ++++++++++-
>  libc/sysdeps/linux/common/clock_settime.c     | 17 ++++++++-
>  libc/sysdeps/linux/common/ppoll.c             | 15 +++++++-
>  libc/sysdeps/linux/common/pselect.c           | 15 +++++++-
>  libc/sysdeps/linux/common/select.c            | 23 +++++++++---
>  libc/sysdeps/linux/common/time.c              |  2 +-
>  libc/sysdeps/linux/common/timerfd.c           | 23 +++++++++++-
>  libc/sysdeps/linux/common/utimensat.c         | 23 +++++++++++-
>  libc/sysdeps/linux/powerpc/bits/kernel_stat.h | 28 +++++++++++++--
>  libc/sysdeps/linux/powerpc/bits/sem.h         | 16 +++++++++
>  libpthread/nptl/pthread_mutex_timedlock.c     | 20 +++++++++--
>  .../sysdeps/pthread/pthread_cond_timedwait.c  |  5 +--
>  .../pthread/pthread_rwlock_timedrdlock.c      |  5 +--
>  .../pthread/pthread_rwlock_timedwrlock.c      |  5 +--
>  .../sysdeps/unix/sysv/linux/lowlevellock.c    | 10 +++---
>  .../sysdeps/unix/sysv/linux/lowlevellock.h    | 35 +++++++++++++++++--
>  .../unix/sysv/linux/lowlevelrobustlock.c      |  6 ++--
>  .../sysdeps/unix/sysv/linux/sem_timedwait.c   |  6 ++--
>  .../sysdeps/unix/sysv/linux/timer_settime.c   | 19 +++++++++-
>  librt/clock_gettime.c                         | 20 +++++++++--
>  librt/clock_nanosleep.c                       | 23 ++++++++++--
>  librt/mq_timedreceive.c                       | 22 ++++++++++--
>  librt/mq_timedsend.c                          | 20 ++++++++++-
>  librt/timer_settime.c                         | 28 +++++++++++++--
>  32 files changed, 435 insertions(+), 56 deletions(-)
>
> diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
> index 9351dffc8..f11a63b79 100644
> --- a/extra/Configs/Config.in
> +++ b/extra/Configs/Config.in
> @@ -1026,7 +1026,7 @@ config UCLIBC_FALLBACK_TO_ETC_LOCALTIME
>
>  config UCLIBC_USE_TIME64
>         bool "Use *time64 syscalls instead of 32bit ones (if possible)"
> -       depends on TARGET_arm || TARGET_xtensa
> +       depends on TARGET_arm || TARGET_powerpc || TARGET_xtensa
>         # TODO: add support for other architectures
>         default n
>
> diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c
> index eb0983698..7ec439887 100644
> --- a/libc/inet/socketcalls.c
> +++ b/libc/inet/socketcalls.c
> @@ -268,12 +268,26 @@ lt_libc_hidden(recvmsg)
>  #endif
>
>  #ifdef L_recvmmsg
> +
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +
> +#endif

This pattern and a similar pattern with struct its64_struct
is repeated multiple times in this patch. It seems that this
repetition can be easily avoided?

> +
>  #ifdef __ASSUME_RECVMMSG_SYSCALL
>  static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen,
>                               int flags, struct timespec *tmo)
>  {
>  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64)
> -       return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo);
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = tmo ? tmo->tv_sec : 0,
> +               .tv_nsec = tmo ? tmo->tv_nsec : 0
> +       };
> +       return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo ? &__ts64 : 0);
>  # elif defined(__NR_recvmmsg)
>         return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen, flags, tmo);
>  # elif __NR_socketcall
> diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c
> index cd541761c..d0bd0ba28 100644
> --- a/libc/misc/sysvipc/sem.c
> +++ b/libc/misc/sysvipc/sem.c
> @@ -96,7 +96,21 @@ int semop (int semid, struct sembuf *sops, size_t nsops)
>  #ifdef L_semtimedop
>
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_semtimedop_time64)
> -_syscall4_time64(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout)
> +
> +struct ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +
> +int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout) {
> +    struct ts64_struct __ts64 = {
> +        .tv_sec = timeout ? timeout->tv_sec : 0,
> +        .tv_nsec = timeout ? timeout->tv_nsec : 0
> +    };
> +
> +    return INLINE_SYSCALL(semtimedop_time64, 4, semid, sops, nsops, timeout ? &__ts64 : 0);
> +}
> +
>  #elif defined(__NR_semtimedop)
>  _syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout)
>
> diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c
> index 3557a039e..b237534cd 100644
> --- a/libc/signal/sigwait.c
> +++ b/libc/signal/sigwait.c
> @@ -24,7 +24,8 @@
>  #include <signal.h>
>  #include <cancel.h>
>
> -#if defined __NR_rt_sigtimedwait && defined __UCLIBC_HAS_REALTIME__
> +#if (defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64))) && \
> +    defined(__UCLIBC_HAS_REALTIME__)
>
>  #include <string.h>
>
> diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> index bd82ca6d5..cd25fe177 100644
> --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> @@ -9,7 +9,7 @@
>
>  #include <sys/syscall.h>
>
> -#ifdef __NR_rt_sigtimedwait
> +#if defined(__NR_rt_sigtimedwait) || (defined(__NR_rt_sigtimedwait_time64) && defined(__UCLIBC_USE_TIME64__))
>  # include <signal.h>
>  # include <cancel.h>
>  # ifdef __UCLIBC_HAS_THREADS_NATIVE__
> @@ -21,6 +21,15 @@
>  #  include <string.h>
>  # endif
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +       __S64_TYPE tv_sec;
> +       __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
>                        const struct timespec *timeout)
>  {
> @@ -53,8 +62,12 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
>            real size of the user-level sigset_t.  */
>         /* on uClibc we use the kernel sigset_t size */
>  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = timeout ? timeout->tv_sec : 0,
> +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> +       };
>         result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
> -                                   timeout, __SYSCALL_SIGSET_T_SIZE);
> +                                   timeout ? &__ts64 : 0, __SYSCALL_SIGSET_T_SIZE);
>  # else
>         result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
>                                     timeout, __SYSCALL_SIGSET_T_SIZE);
> @@ -71,8 +84,12 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
>  # else
>         /* on uClibc we use the kernel sigset_t size */
>  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = timeout ? timeout->tv_sec : 0,
> +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> +       };
>         return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
> -                             timeout, __SYSCALL_SIGSET_T_SIZE);
> +                             timeout ? &__ts64 : 0, __SYSCALL_SIGSET_T_SIZE);
>  # else
>         return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
>                               timeout, __SYSCALL_SIGSET_T_SIZE);
> diff --git a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> index d2d176a64..7830b2e2c 100644
> --- a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> +++ b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> @@ -9,7 +9,7 @@
>
>  #include <sys/syscall.h>
>
> -#ifdef __NR_rt_sigtimedwait
> +#if defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64))
>  # define __need_NULL
>  # include <stddef.h>
>  # include <signal.h>
> diff --git a/libc/sysdeps/linux/common/alarm.c b/libc/sysdeps/linux/common/alarm.c
> index 4e6e2215b..861f6ad8e 100644
> --- a/libc/sysdeps/linux/common/alarm.c
> +++ b/libc/sysdeps/linux/common/alarm.c
> @@ -9,7 +9,7 @@
>  #include <sys/syscall.h>
>  #include <unistd.h>
>
> -#ifdef __NR_alarm && !defined(__UCLIBC_USE_TIME64__)
> +#if defined(__NR_alarm) && !defined(__UCLIBC_USE_TIME64__)
>  _syscall1(unsigned int, alarm, unsigned int, seconds)
>  #else
>  # include <sys/time.h>
> diff --git a/libc/sysdeps/linux/common/clock_getres.c b/libc/sysdeps/linux/common/clock_getres.c
> index d4b989958..c72b0a21c 100644
> --- a/libc/sysdeps/linux/common/clock_getres.c
> +++ b/libc/sysdeps/linux/common/clock_getres.c
> @@ -10,9 +10,27 @@
>  #include <sys/syscall.h>
>  #include <time.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +       __S64_TYPE tv_sec;
> +       __S64_TYPE tv_nsec;
> +};
> +
> +#endif
>
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64)
> -_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
> +int clock_getres(clockid_t clock_id, struct timespec *res)
> +{
> +       struct ts64_struct __ts64;
> +       int __ret = INLINE_SYSCALL(clock_getres_time64, 2, clock_id, &__ts64);
> +       if (__ret == 0 && res) {
> +               res->tv_sec = __ts64.tv_sec;
> +               res->tv_nsec = __ts64.tv_nsec;
> +       };
> +
> +       return __ret;
> +}
>  #elif defined(__NR_clock_getres)
>  _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
>  #else
> diff --git a/libc/sysdeps/linux/common/clock_gettime.c b/libc/sysdeps/linux/common/clock_gettime.c
> index a595bd691..dbb767c94 100644
> --- a/libc/sysdeps/linux/common/clock_gettime.c
> +++ b/libc/sysdeps/linux/common/clock_gettime.c
> @@ -11,8 +11,27 @@
>  #include <sys/syscall.h>
>  #include <time.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +       __S64_TYPE tv_sec;
> +       __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
> -_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
> +int clock_gettime(clockid_t clock_id, struct timespec *tp)
> +{
> +       struct ts64_struct __ts64;
> +       int __ret = INLINE_SYSCALL(clock_gettime64, 2, clock_id, &__ts64);
> +       if (tp) {
> +               tp->tv_sec = __ts64.tv_sec;
> +               tp->tv_nsec = __ts64.tv_nsec;
> +       }
> +
> +       return __ret;
> +}
>  #elif defined(__NR_clock_gettime)
>  _syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
>  #else
> diff --git a/libc/sysdeps/linux/common/clock_settime.c b/libc/sysdeps/linux/common/clock_settime.c
> index 89550af5a..54bfa20e8 100644
> --- a/libc/sysdeps/linux/common/clock_settime.c
> +++ b/libc/sysdeps/linux/common/clock_settime.c
> @@ -12,7 +12,22 @@
>
>
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64)
> -_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp)
> +
> +struct ts64_struct {
> +       __S64_TYPE tv_sec;
> +       __S64_TYPE tv_nsec;
> +};
> +
> +int clock_settime(clockid_t clock_id, const struct timespec *tp)
> +{
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = tp->tv_sec,
> +               .tv_nsec = tp->tv_nsec
> +       };
> +
> +       return INLINE_SYSCALL(clock_settime64, 2, clock_id, &__ts64);
> +}
> +
>  #elif defined(__NR_clock_settime)
>  _syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp)
>  #else
> diff --git a/libc/sysdeps/linux/common/ppoll.c b/libc/sysdeps/linux/common/ppoll.c
> index cb36149c5..16d836b6f 100644
> --- a/libc/sysdeps/linux/common/ppoll.c
> +++ b/libc/sysdeps/linux/common/ppoll.c
> @@ -26,6 +26,15 @@
>  #include <sys/poll.h>
>  #include <cancel.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +   __S64_TYPE tv_sec;
> +   __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  static int
>  __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
>             const sigset_t *sigmask)
> @@ -38,7 +47,11 @@ __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
>                 timeout = &tval;
>         }
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64)
> -       return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE);
> +   struct ts64_struct __ts64 = {
> +      .tv_sec = timeout ? timeout->tv_sec : 0,
> +      .tv_nsec = timeout ? timeout->tv_nsec : 0
> +   };
> +       return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout ? &__ts64 : 0, sigmask, __SYSCALL_SIGSET_T_SIZE);
>  #else
>         return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE);
>  #endif
> diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c
> index 23bdab5cf..a189624ec 100644
> --- a/libc/sysdeps/linux/common/pselect.c
> +++ b/libc/sysdeps/linux/common/pselect.c
> @@ -26,6 +26,15 @@
>  #include <signal.h>
>  #include <cancel.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
>                          fd_set *exceptfds, const struct timespec *timeout,
>                          const sigset_t *sigmask)
> @@ -57,7 +66,11 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
>                 sigmask = (void *)&data;
>         }
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
> -       return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask);
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = timeout ? timeout->tv_sec : 0,
> +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> +       };
> +       return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout ? &__ts64 : 0, sigmask);
>  #else
>         return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask);
>  #endif
> diff --git a/libc/sysdeps/linux/common/select.c b/libc/sysdeps/linux/common/select.c
> index 3132a109c..a55a61df1 100644
> --- a/libc/sysdeps/linux/common/select.c
> +++ b/libc/sysdeps/linux/common/select.c
> @@ -15,17 +15,22 @@
>  # define __NR_select __NR__newselect
>  #endif
>
> -#if !defined __NR_select && defined __NR_pselect6
> +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
>  # include <stdint.h>
>  # define USEC_PER_SEC 1000000L
>  #endif
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +struct ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +#endif
> +
>  int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
>                  struct timeval *timeout)
>  {
> -#ifdef __NR_select
> -       return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout);
> -#elif defined __NR_pselect6
> +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
>         struct timespec _ts, *ts = 0;
>         if (timeout) {
>                 uint32_t usec;
> @@ -47,8 +52,18 @@ int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
>
>                 ts = &_ts;
>         }
> +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = ts ? ts->tv_sec : 0,
> +               .tv_nsec = ts ? ts->tv_nsec : 0
> +       };
> +       return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds, exceptfds, timeout ? &__ts64 : 0, 0);
> +#else
>         return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds, exceptfds, ts, 0);
>  #endif
> +#elif defined(__NR_select)
> +       return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout);
> +#endif
>  }
>  /* we should guard it, but we need it in other files, so let it fail
>   * if we miss any of the syscalls */
> diff --git a/libc/sysdeps/linux/common/time.c b/libc/sysdeps/linux/common/time.c
> index 22403f174..d084ffaad 100644
> --- a/libc/sysdeps/linux/common/time.c
> +++ b/libc/sysdeps/linux/common/time.c
> @@ -9,7 +9,7 @@
>  #include <sys/syscall.h>
>  #include <time.h>
>
> -#ifdef __NR_time
> +#if defined(__NR_time) && !defined(__UCLIBC_USE_TIME64__)
>  _syscall_noerr1(time_t, time, time_t *, t)
>  #else
>  # include <sys/time.h>
> diff --git a/libc/sysdeps/linux/common/timerfd.c b/libc/sysdeps/linux/common/timerfd.c
> index 0f19b44ed..04db6ed00 100644
> --- a/libc/sysdeps/linux/common/timerfd.c
> +++ b/libc/sysdeps/linux/common/timerfd.c
> @@ -16,12 +16,33 @@
>  _syscall2(int, timerfd_create, int, clockid, int, flags)
>  #endif
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct its64_struct {
> +    __S64_TYPE interval_tv_sec;
> +    __S64_TYPE interval_tv_nsec;
> +    __S64_TYPE value_tv_sec;
> +    __S64_TYPE value_tv_nsec;
> +};
> +
> +#endif
> +
>  /*
>   * timerfd_settime()
>   */
>  #if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64)
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64)
> -_syscall4_64(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr)
> +int timerfd_settime(int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)
> +{
> +    struct its64_struct __its64 = {
> +        .interval_tv_sec = utmr->it_interval.tv_sec,
> +        .interval_tv_nsec = utmr->it_interval.tv_nsec,
> +        .value_tv_sec = utmr->it_value.tv_sec,
> +        .value_tv_nsec = utmr->it_value.tv_nsec,
> +    };
> +
> +    return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, &__its64, otmr);
> +}
>  #else
>  _syscall4(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr)
>  #endif
> diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c
> index 6a78ebb4f..0c87b5c45 100644
> --- a/libc/sysdeps/linux/common/utimensat.c
> +++ b/libc/sysdeps/linux/common/utimensat.c
> @@ -9,9 +9,30 @@
>  #include <sys/syscall.h>
>  #include <sys/stat.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct uts64_struct {
> +    __S64_TYPE tv_sec1;
> +    __S64_TYPE tv_nsec1;
> +    __S64_TYPE tv_sec2;
> +    __S64_TYPE tv_nsec2;
> +};
> +
> +#endif
> +
>  #if defined(__NR_utimensat) || defined(__NR_utimensat_time64)
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64)
> -_syscall4_time64(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
> +int utimensat(int fd, const char *path, const struct timespec times[2], int flags)
> +{
> +    struct uts64_struct __uts64 = {
> +        .tv_sec1 = times ? times[0].tv_sec : 0,
> +        .tv_nsec1 = times ? times[0].tv_nsec : 0,
> +        .tv_sec2 = times ? times[1].tv_sec : 0,
> +        .tv_nsec2 = times ? times[1].tv_nsec : 0
> +    };
> +
> +    return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? &__uts64 : 0, flags);
> +}
>  #else
>  _syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
>  #endif
> diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> index ce62b2ba2..0e76120ab 100644
> --- a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> +++ b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> @@ -5,6 +5,16 @@
>   * struct kernel_stat should look like...  It turns out each arch has a
>   * different opinion on the subject... */
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +#include <bits/types.h>
> +
> +struct ts32_struct {
> +       __S32_TYPE tv_sec;
> +       __S32_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  #if __WORDSIZE == 64
>  #define kernel_stat kernel_stat64
>  #else
> @@ -19,9 +29,15 @@ struct kernel_stat {
>         __kernel_off_t  st_size;
>         unsigned long   st_blksize;
>         unsigned long   st_blocks;
> +#if defined(__UCLIBC_USE_TIME64__)
> +       struct ts32_struct __st_atim32;
> +       struct ts32_struct __st_mtim32;
> +       struct ts32_struct __st_ctim32;
> +#else
>         struct timespec st_atim;
>         struct timespec st_mtim;
>         struct timespec st_ctim;
> +#endif
>         unsigned long   __unused4;
>         unsigned long   __unused5;
>  };
> @@ -39,9 +55,15 @@ struct kernel_stat64 {
>         long long st_size;              /* Size of file, in bytes.  */
>         long st_blksize;                /* Optimal block size for I/O.  */
>         long long st_blocks;            /* Number 512-byte blocks allocated. */
> -       struct timespec st_atim;        /* Time of last access.  */
> -       struct timespec st_mtim;        /* Time of last modification.  */
> -       struct timespec st_ctim;        /* Time of last status change.  */
> +#if defined(__UCLIBC_USE_TIME64__)
> +       struct ts32_struct __st_atim32;
> +       struct ts32_struct __st_mtim32;
> +       struct ts32_struct __st_ctim32;
> +#else
> +       struct timespec st_atim;
> +       struct timespec st_mtim;
> +       struct timespec st_ctim;
> +#endif
>         unsigned long int __uclibc_unused4;
>         unsigned long int __uclibc_unused5;
>  };
> diff --git a/libc/sysdeps/linux/powerpc/bits/sem.h b/libc/sysdeps/linux/powerpc/bits/sem.h
> index a9d895374..8d338eac0 100644
> --- a/libc/sysdeps/linux/powerpc/bits/sem.h
> +++ b/libc/sysdeps/linux/powerpc/bits/sem.h
> @@ -35,6 +35,7 @@
>  #define SETALL         17              /* set all semval's */
>
>
> +
>  /* Data structure describing a set of semaphores.  */
>  struct semid_ds
>  {
> @@ -42,16 +43,31 @@ struct semid_ds
>  #if __WORDSIZE == 32
>    unsigned int __uclibc_unused1;
>  #endif
> +#if defined(__UCLIBC_USE_TIME64__)
> +  unsigned long int __sem_otime_internal_1; /* last semop() time */
> +  unsigned long int __sem_otime_internal_2;
> +#else
>    __time_t sem_otime;                  /* last semop() time */
> +#endif
>  #if __WORDSIZE == 32
>    unsigned int __uclibc_unused2;
>  #endif
> +#if defined(__UCLIBC_USE_TIME64__)
> +  unsigned long int __sem_ctime_internal_1; /* last time changed by semctl() */
> +  unsigned long int __sem_ctime_internal_2;
> +#else
>    __time_t sem_ctime;                  /* last time changed by semctl() */
> +#endif
>    unsigned long int sem_nsems;         /* number of semaphores in set */
> +#if defined(__UCLIBC_USE_TIME64__)
> +  __time_t sem_otime;
> +  __time_t sem_ctime;
> +#endif
>    unsigned long __uclibc_unused3;
>    unsigned long __uclibc_unused4;
>  };
>
> +
>  /* The user should define a union like the following to use it for arguments
>     for `semctl'.
>
> diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c
> index 25f9ec3b2..d55495683 100644
> --- a/libpthread/nptl/pthread_mutex_timedlock.c
> +++ b/libpthread/nptl/pthread_mutex_timedlock.c
> @@ -23,6 +23,15 @@
>  #include <lowlevellock.h>
>  #include <not-cancel.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  /* We need to build this function with optimization to avoid
>   * lll_timedlock erroring out with
>   * error: can't find a register in class ‘GENERAL_REGS’ while reloading ‘asm’
> @@ -265,10 +274,14 @@ pthread_mutex_timedlock (
>             INTERNAL_SYSCALL_DECL (__err);
>
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> +           struct ts64_struct __ts64 = {
> +               .tv_sec = abstime ? abstime->tv_sec : 0,
> +               .tv_nsec = abstime ? abstime->tv_nsec : 0
> +           };
>             int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock,
>                                       __lll_private_flag (FUTEX_LOCK_PI,
>                                                           private), 1,
> -                                     abstime);
> +                                     &__ts64);
>  #else
>             int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
>                                       __lll_private_flag (FUTEX_LOCK_PI,
> @@ -454,7 +467,7 @@ pthread_mutex_timedlock (
>                       }
>
>                     struct timeval tv;
> -                   struct timespec rt;
> +                   struct timespec rt, *rtp;
>
>                     /* Get the current time.  */
>                     (void) gettimeofday (&tv, NULL);
> @@ -475,8 +488,9 @@ pthread_mutex_timedlock (

Starting from this hunk...

>                         goto failpp;
>                       }
>
> +                   rtp = &rt;
>                     lll_futex_timed_wait (&mutex->__data.__lock,
> -                                         ceilval | 2, &rt,
> +                                         ceilval | 2, rtp,
>                                           PTHREAD_MUTEX_PSHARED (mutex));
>                   }
>               }
> diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> index 49aab0293..1ea2a888a 100644
> --- a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> @@ -95,7 +95,7 @@ __pthread_cond_timedwait (
>
>    while (1)
>      {
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>        {
>  #ifdef __NR_clock_gettime
>         INTERNAL_SYSCALL_DECL (err);
> @@ -164,8 +164,9 @@ __pthread_cond_timedwait (
>        cbuffer.oldtype = __pthread_enable_asynccancel ();
>
>        /* Wait until woken by signal or broadcast.  */
> +      rtp = &rt;
>        err = lll_futex_timed_wait (&cond->__data.__futex,
> -                                 futex_val, &rt, pshared);
> +                                 futex_val, rtp, pshared);
>
>        /* Disable asynchronous cancellation.  */
>        __pthread_disable_asynccancel (cbuffer.oldtype);
> diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> index 596f5df51..379e92b43 100644
> --- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> @@ -81,7 +81,7 @@ pthread_rwlock_timedrdlock (
>        (void) gettimeofday (&tv, NULL);
>
>        /* Convert the absolute timeout value to a relative timeout.  */
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
>        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
>        if (rt.tv_nsec < 0)
> @@ -112,8 +112,9 @@ pthread_rwlock_timedrdlock (
>        lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
>
>        /* Wait for the writer to finish.  */
> +      rtp = &rt;
>        err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
> -                                 waitval, &rt, rwlock->__data.__shared);
> +                                 waitval, rtp, rwlock->__data.__shared);
>        /* Get the lock.  */
>        lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
> diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> index 0b04b357a..3ce9f9b13 100644
> --- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> @@ -72,7 +72,7 @@ pthread_rwlock_timedwrlock (
>        (void) gettimeofday (&tv, NULL);
>
>        /* Convert the absolute timeout value to a relative timeout.  */
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
>        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
>        if (rt.tv_nsec < 0)
> @@ -102,8 +102,9 @@ pthread_rwlock_timedwrlock (
>        lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
>
>        /* Wait for the writer or reader(s) to finish.  */
> +      rtp = &rt;
>        err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup,
> -                                 waitval, &rt, rwlock->__data.__shared);
> +                                 waitval, rtp, rwlock->__data.__shared);
>
>        /* Get the lock.  */
>        lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> index 4294a20b0..5f7301976 100644
> --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> @@ -63,7 +63,7 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
>        (void) gettimeofday (&tv, NULL);
>
>        /* Compute relative timeout.  */
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
>        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
>        if (rt.tv_nsec < 0)
> @@ -76,7 +76,8 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
>         return ETIMEDOUT;
>
>        /* Wait.  */
> -      lll_futex_timed_wait (futex, 2, &rt, private);
> +      rtp = &rt;
> +      lll_futex_timed_wait (futex, 2, rtp, private);
>      }
>
>    return 0;
> @@ -95,7 +96,7 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
>    while ((tid = *tidp) != 0)
>      {
>        struct timeval tv;
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>
>        /* Get the current time.  */
>        (void) __gettimeofday (&tv, NULL);
> @@ -115,7 +116,8 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
>
>        /* Wait until thread terminates.  The kernel so far does not use
>          the private futex operations for this.  */
> -      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
> +      rtp = &rt;
> +      if (lll_futex_timed_wait (tidp, tid, rtp, LLL_SHARED) == -ETIMEDOUT)
>         return ETIMEDOUT;
>      }
>

...and up to here: why are all these changes adding an intermediate
pointer needed?

> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> index e72fe5234..4209a21d3 100644
> --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> @@ -71,18 +71,49 @@
>  # endif
>  #endif
>
> +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> +
>  #define lll_futex_wait(futexp, val, private) \
> -  lll_futex_timed_wait(futexp, val, NULL, private)
> +  ({                                                                         \
> +    INTERNAL_SYSCALL_DECL (__err);                                           \
> +    long int __ret;                                                          \
> +    __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),                      \
> +                             __lll_private_flag (FUTEX_WAIT, private),       \
> +                             (val), NULL);                           \
> +    __ret;                                                                   \
> +  })
> +
> +#else
> +
> +#define lll_futex_wait(futexp, val, private) \
> +  ({                                                                         \
> +    INTERNAL_SYSCALL_DECL (__err);                                           \
> +    long int __ret;                                                          \
> +    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                     \
> +                             __lll_private_flag (FUTEX_WAIT, private),       \
> +                             (val), NULL);                           \
> +    __ret;                                                                   \
> +  })
> +
> +#endif
>
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
>
> +struct __ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +
> +#define ptr_timespec_to_ts64(ts) \
> +  (&(struct __ts64_struct) {.tv_sec = ts->tv_sec, .tv_nsec = ts->tv_nsec})
> +
>  #define lll_futex_timed_wait(futexp, val, timespec, private) \
>    ({                                                                         \
>      INTERNAL_SYSCALL_DECL (__err);                                           \
>      long int __ret;                                                          \
>      __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),                      \
>                               __lll_private_flag (FUTEX_WAIT, private),       \
> -                             (val), (timespec));                             \
> +                             (val), (ptr_timespec_to_ts64(timespec)));                       \
>      __ret;                                                                   \
>    })
>
> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> index 7b4e84343..5781359fb 100644
> --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> @@ -73,7 +73,7 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime,
>    do
>      {
>        struct timeval tv;
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>
>        /* Get the current time.  */
>        (void) __gettimeofday (&tv, NULL);
> @@ -99,8 +99,8 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime,
>        if (oldval != newval
>           && atomic_compare_and_exchange_bool_acq (futex, newval, oldval))
>         continue;
> -
> -      lll_futex_timed_wait (futex, newval, &rt, private);
> +      rtp = &rt;
> +      lll_futex_timed_wait (futex, newval, rtp, private);
>
>      try:
>        ;
> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> index 8c3ef47c5..05ba5bc13 100644
> --- a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> @@ -51,7 +51,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
>    while (1)
>      {
>        struct timeval tv;
> -      struct timespec rt;
> +      struct timespec rt, *rtp;
>        int sec, nsec;
>
>        /* Get the current time.  */
> @@ -79,10 +79,12 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
>        rt.tv_sec = sec;
>        rt.tv_nsec = nsec;
>
> +      rtp = &rt;
> +
>        /* Enable asynchronous cancellation.  Required by the standard.  */
>        int oldtype = __pthread_enable_asynccancel ();
>
> -      err = lll_futex_timed_wait (&isem->value, 0, &rt,
> +      err = lll_futex_timed_wait (&isem->value, 0, rtp,
>                                   isem->private ^ FUTEX_PRIVATE_FLAG);
>
>        /* Disable asynchronous cancellation.  */
> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> index 80d242f21..d7c2aa804 100644
> --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> @@ -38,6 +38,17 @@ static int compat_timer_settime (timer_t timerid, int flags,
>  #  define timer_settime timer_settime_alias
>  # endif
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct its64_struct {
> +    __S64_TYPE interval_tv_sec;
> +    __S64_TYPE interval_tv_nsec;
> +    __S64_TYPE value_tv_sec;
> +    __S64_TYPE value_tv_nsec;
> +};
> +
> +#endif
> +
>
>  int
>  timer_settime (
> @@ -55,8 +66,14 @@ timer_settime (
>
>        /* Delete the kernel timer object.  */
>  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
> +      struct its64_struct __its64 = {
> +            .interval_tv_sec = value->it_interval.tv_sec,
> +            .interval_tv_nsec = value->it_interval.tv_nsec,
> +            .value_tv_sec = value->it_value.tv_sec,
> +            .value_tv_nsec = value->it_value.tv_nsec,
> +      };
>        int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
> -                               value, ovalue);
> +                               value ? &__its64 : 0, ovalue);
>  # else
>        int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
>                                 value, ovalue);
> diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c
> index b66b60231..eff40d68f 100644
> --- a/librt/clock_gettime.c
> +++ b/librt/clock_gettime.c
> @@ -22,10 +22,26 @@
>  #include <sys/time.h>
>  #include "kernel-posix-cpu-timers.h"
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +  __S64_TYPE tv_sec;
> +  __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
>  #define SYSCALL_GETTIME \
> -  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
> -  break
> +  { \
> +  struct ts64_struct __ts64; \
> +  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, &__ts64); \
> +  if (tp) { \
> +    tp->tv_sec = __ts64.tv_sec; \
> +    tp->tv_nsec = __ts64.tv_nsec; \
> +  } \
> +  break; \
> +  }
>  #else
>  #define SYSCALL_GETTIME \
>    retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
> diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c
> index eaae75720..786f7eede 100644
> --- a/librt/clock_nanosleep.c
> +++ b/librt/clock_nanosleep.c
> @@ -21,6 +21,14 @@
>
>  #include "kernel-posix-cpu-timers.h"
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +    __S64_TYPE tv_sec;
> +    __S64_TYPE tv_nsec;
> +};
> +
> +#endif
>
>  /* We can simply use the syscall.  The CPU clocks are not supported
>     with this function.  */
> @@ -36,18 +44,27 @@ clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
>    if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
>      clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
>
> -  if (SINGLE_THREAD_P)
> +  if (SINGLE_THREAD_P) {
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64)
> -    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem);
> +    struct ts64_struct __ts64 = {
> +      .tv_sec = req ? req->tv_sec : 0,
> +      .tv_nsec = req ? req->tv_nsec : 0
> +    };
> +    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req ? &__ts64 : 0, rem);
>  #else
>      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
>  #endif
> +  }
>    else
>      {
>  #ifdef __NEW_THREADS
>        int oldstate = LIBC_CANCEL_ASYNC ();
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64)
> -      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem);
> +      struct ts64_struct __ts64_2 = {
> +        .tv_sec = req ? req->tv_sec : 0,
> +        .tv_nsec = req ? req->tv_nsec : 0
> +      };
> +      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req ? &__ts64_2 : 0, rem);
>  #else
>        r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req,
>                             rem);
> diff --git a/librt/mq_timedreceive.c b/librt/mq_timedreceive.c
> index db1ae1aa8..818f54faa 100644
> --- a/librt/mq_timedreceive.c
> +++ b/librt/mq_timedreceive.c
> @@ -8,13 +8,29 @@
>  #include <unistd.h>
>  #include <cancel.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +       __S64_TYPE tv_sec;
> +       __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedreceive_time64)
> -#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64
> +int _NC(mq_timedreceive)(mqd_t mqdes, char *restrict msg_ptr, size_t msg_len, unsigned int *restrict msq_prio, const struct timespec *restrict abs_timeout)
> +{
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
> +               .tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
> +       };
> +
> +       return INLINE_SYSCALL(mq_timedreceive_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
> +}
>  #else
>  #define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive
> -#endif
> -
>  _syscall5(ssize_t, __NC(mq_timedreceive), mqd_t, mqdes, char *__restrict, msg_ptr, size_t, msg_len, unsigned int *__restrict, msq_prio, const struct timespec *__restrict, abs_timeout)
> +#endif
>
>  CANCELLABLE_SYSCALL(ssize_t, mq_timedreceive, (mqd_t mqdes, char *__restrict msg_ptr, size_t msq_len, unsigned int *__restrict msq_prio, const struct timespec *__restrict abs_timeout),
>                     (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
> diff --git a/librt/mq_timedsend.c b/librt/mq_timedsend.c
> index 6afaf5157..e8deea9cb 100644
> --- a/librt/mq_timedsend.c
> +++ b/librt/mq_timedsend.c
> @@ -8,13 +8,31 @@
>  #include <unistd.h>
>  #include <cancel.h>
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct ts64_struct {
> +       __S64_TYPE tv_sec;
> +       __S64_TYPE tv_nsec;
> +};
> +
> +#endif
> +
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64)
>  #define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64
> +int _NC(mq_timedsend)(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msq_prio, const struct timespec *abs_timeout)
> +{
> +       struct ts64_struct __ts64 = {
> +               .tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
> +               .tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
> +       };
> +
> +       return INLINE_SYSCALL(mq_timedsend_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
> +}
>  #else
>  #define __NR___mq_timedsend_nocancel __NR_mq_timedsend
> +_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout)
>  #endif
>
> -_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout)
>  CANCELLABLE_SYSCALL(int, mq_timedsend, (mqd_t mqdes, const char *msg_ptr, size_t msq_len, unsigned int msq_prio, const struct timespec *abs_timeout),
>                     (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
>  lt_libc_hidden(mq_timedsend)
> diff --git a/librt/timer_settime.c b/librt/timer_settime.c
> index 022880297..31202b07a 100644
> --- a/librt/timer_settime.c
> +++ b/librt/timer_settime.c
> @@ -9,13 +9,36 @@
>
>  #include "kernel-posix-timers.h"
>
> +#if defined(__UCLIBC_USE_TIME64__)
> +
> +struct its64_struct {
> +    __S64_TYPE interval_tv_sec;
> +    __S64_TYPE interval_tv_nsec;
> +    __S64_TYPE value_tv_sec;
> +    __S64_TYPE value_tv_nsec;
> +};
> +
> +#endif
> +
>  #if defined(__NR_timer_settime) || defined(__NR_timer_settime64)
>
>  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
> -#define __NR___syscall_timer_settime __NR_timer_settime64
> +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue)
> +{
> +       struct timer *kt = (struct timer *)timerid;
> +
> +    struct its64_struct __its64 = {
> +        .interval_tv_sec = value->it_interval.tv_sec,
> +        .interval_tv_nsec = value->it_interval.tv_nsec,
> +        .value_tv_sec = value->it_value.tv_sec,
> +        .value_tv_nsec = value->it_value.tv_nsec,
> +    };
> +
> +       return INLINE_SYSCALL(timer_settime64, 4, kt->ktimerid, flags, value ? &__its64: 0, ovalue);
> +}
>  #else
> +
>  #define __NR___syscall_timer_settime __NR_timer_settime
> -#endif
>
>  static __inline__ _syscall4(int, __syscall_timer_settime, kernel_timer_t, ktimerid,
>                         int, flags, const void *, value, void *, ovalue);
> @@ -31,3 +54,4 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
>  }
>
>  #endif
> +#endif
> --
> 2.43.2
>
> _______________________________________________
> devel mailing list -- devel@uclibc-ng.org
> To unsubscribe send an email to devel-leave@uclibc-ng.org
Dmitry Chestnykh Feb. 24, 2024, 4:15 p.m. UTC | #2
Thanks for the review, okay, i will rework the patch.
Answering to your question about intermediate pointer, is it needed to use
inside ptr_timespec_to_ts64 macro (&rt doesn't work because of producing
&rt->tv_sec and &rt->tv_nsec),
but i got that it can be avoided via transforming `ts->tv_sec` to
`(ts)->tv_sec` and the similar for nsec.

сб, 24 февр. 2024 г. в 19:09, Max Filippov <jcmvbkbc@gmail.com>:

> On Sat, Feb 24, 2024 at 7:01 AM Dmitry Chestnykh <dm.chestnykh@gmail.com>
> wrote:
> >
> > PowerPC is big-endian architecture, so there are some
> > significant differences in comparison with time64 support
> > for little-endian architectures like ARM and xtensa.
>
> JFYI xtensa supports both little and big endianness. Which
> suggests that it needs similar treatment as a BE PPC.
>
> > The main difference is that we strictly need to pass two 64bit
> > values to system calls because Linux Kernel internally uses
> > `struct __ketnel_timespec` and similar, which consists of two
> > 64bit fields.
> > For this reason many files have been changed to convert
> > timespec-family structures (mixed of 64bit and 32bit values)
> > to the 64bit-only structures for using as system calls args.
> > Now time64 syscalls works properly both for LE (ARM, xtensa)
> > and BE (PPC) memory layouts.
>
> I'd suggest splitting this change into two parts: generic
> arch-independent changes followed by PPC-specific changes.
>
> > Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
> > ---
> >  extra/Configs/Config.in                       |  2 +-
> >  libc/inet/socketcalls.c                       | 16 ++++++++-
> >  libc/misc/sysvipc/sem.c                       | 16 ++++++++-
> >  libc/signal/sigwait.c                         |  3 +-
> >  libc/sysdeps/linux/common/__rt_sigtimedwait.c | 23 ++++++++++--
> >  libc/sysdeps/linux/common/__rt_sigwaitinfo.c  |  2 +-
> >  libc/sysdeps/linux/common/alarm.c             |  2 +-
> >  libc/sysdeps/linux/common/clock_getres.c      | 20 ++++++++++-
> >  libc/sysdeps/linux/common/clock_gettime.c     | 21 ++++++++++-
> >  libc/sysdeps/linux/common/clock_settime.c     | 17 ++++++++-
> >  libc/sysdeps/linux/common/ppoll.c             | 15 +++++++-
> >  libc/sysdeps/linux/common/pselect.c           | 15 +++++++-
> >  libc/sysdeps/linux/common/select.c            | 23 +++++++++---
> >  libc/sysdeps/linux/common/time.c              |  2 +-
> >  libc/sysdeps/linux/common/timerfd.c           | 23 +++++++++++-
> >  libc/sysdeps/linux/common/utimensat.c         | 23 +++++++++++-
> >  libc/sysdeps/linux/powerpc/bits/kernel_stat.h | 28 +++++++++++++--
> >  libc/sysdeps/linux/powerpc/bits/sem.h         | 16 +++++++++
> >  libpthread/nptl/pthread_mutex_timedlock.c     | 20 +++++++++--
> >  .../sysdeps/pthread/pthread_cond_timedwait.c  |  5 +--
> >  .../pthread/pthread_rwlock_timedrdlock.c      |  5 +--
> >  .../pthread/pthread_rwlock_timedwrlock.c      |  5 +--
> >  .../sysdeps/unix/sysv/linux/lowlevellock.c    | 10 +++---
> >  .../sysdeps/unix/sysv/linux/lowlevellock.h    | 35 +++++++++++++++++--
> >  .../unix/sysv/linux/lowlevelrobustlock.c      |  6 ++--
> >  .../sysdeps/unix/sysv/linux/sem_timedwait.c   |  6 ++--
> >  .../sysdeps/unix/sysv/linux/timer_settime.c   | 19 +++++++++-
> >  librt/clock_gettime.c                         | 20 +++++++++--
> >  librt/clock_nanosleep.c                       | 23 ++++++++++--
> >  librt/mq_timedreceive.c                       | 22 ++++++++++--
> >  librt/mq_timedsend.c                          | 20 ++++++++++-
> >  librt/timer_settime.c                         | 28 +++++++++++++--
> >  32 files changed, 435 insertions(+), 56 deletions(-)
> >
> > diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
> > index 9351dffc8..f11a63b79 100644
> > --- a/extra/Configs/Config.in
> > +++ b/extra/Configs/Config.in
> > @@ -1026,7 +1026,7 @@ config UCLIBC_FALLBACK_TO_ETC_LOCALTIME
> >
> >  config UCLIBC_USE_TIME64
> >         bool "Use *time64 syscalls instead of 32bit ones (if possible)"
> > -       depends on TARGET_arm || TARGET_xtensa
> > +       depends on TARGET_arm || TARGET_powerpc || TARGET_xtensa
> >         # TODO: add support for other architectures
> >         default n
> >
> > diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c
> > index eb0983698..7ec439887 100644
> > --- a/libc/inet/socketcalls.c
> > +++ b/libc/inet/socketcalls.c
> > @@ -268,12 +268,26 @@ lt_libc_hidden(recvmsg)
> >  #endif
> >
> >  #ifdef L_recvmmsg
> > +
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
>
> This pattern and a similar pattern with struct its64_struct
> is repeated multiple times in this patch. It seems that this
> repetition can be easily avoided?
>
> > +
> >  #ifdef __ASSUME_RECVMMSG_SYSCALL
> >  static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t
> vlen,
> >                               int flags, struct timespec *tmo)
> >  {
> >  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64)
> > -       return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg,
> vlen, flags, tmo);
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = tmo ? tmo->tv_sec : 0,
> > +               .tv_nsec = tmo ? tmo->tv_nsec : 0
> > +       };
> > +       return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg,
> vlen, flags, tmo ? &__ts64 : 0);
> >  # elif defined(__NR_recvmmsg)
> >         return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen,
> flags, tmo);
> >  # elif __NR_socketcall
> > diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c
> > index cd541761c..d0bd0ba28 100644
> > --- a/libc/misc/sysvipc/sem.c
> > +++ b/libc/misc/sysvipc/sem.c
> > @@ -96,7 +96,21 @@ int semop (int semid, struct sembuf *sops, size_t
> nsops)
> >  #ifdef L_semtimedop
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_semtimedop_time64)
> > -_syscall4_time64(int, semtimedop, int, semid, struct sembuf *, sops,
> size_t, nsops, const struct timespec *, timeout)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +int semtimedop(int semid, struct sembuf *sops, size_t nsops, const
> struct timespec *timeout) {
> > +    struct ts64_struct __ts64 = {
> > +        .tv_sec = timeout ? timeout->tv_sec : 0,
> > +        .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +    };
> > +
> > +    return INLINE_SYSCALL(semtimedop_time64, 4, semid, sops, nsops,
> timeout ? &__ts64 : 0);
> > +}
> > +
> >  #elif defined(__NR_semtimedop)
> >  _syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t,
> nsops, const struct timespec *, timeout)
> >
> > diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c
> > index 3557a039e..b237534cd 100644
> > --- a/libc/signal/sigwait.c
> > +++ b/libc/signal/sigwait.c
> > @@ -24,7 +24,8 @@
> >  #include <signal.h>
> >  #include <cancel.h>
> >
> > -#if defined __NR_rt_sigtimedwait && defined __UCLIBC_HAS_REALTIME__
> > +#if (defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__)
> && defined(__NR_rt_sigtimedwait_time64))) && \
> > +    defined(__UCLIBC_HAS_REALTIME__)
> >
> >  #include <string.h>
> >
> > diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> > index bd82ca6d5..cd25fe177 100644
> > --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> > +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> > @@ -9,7 +9,7 @@
> >
> >  #include <sys/syscall.h>
> >
> > -#ifdef __NR_rt_sigtimedwait
> > +#if defined(__NR_rt_sigtimedwait) ||
> (defined(__NR_rt_sigtimedwait_time64) && defined(__UCLIBC_USE_TIME64__))
> >  # include <signal.h>
> >  # include <cancel.h>
> >  # ifdef __UCLIBC_HAS_THREADS_NATIVE__
> > @@ -21,6 +21,15 @@
> >  #  include <string.h>
> >  # endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
> >                        const struct timespec *timeout)
> >  {
> > @@ -53,8 +62,12 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t
> *info,
> >            real size of the user-level sigset_t.  */
> >         /* on uClibc we use the kernel sigset_t size */
> >  # if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_rt_sigtimedwait_time64)
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = timeout ? timeout->tv_sec : 0,
> > +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +       };
> >         result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
> > -                                   timeout, __SYSCALL_SIGSET_T_SIZE);
> > +                                   timeout ? &__ts64 : 0,
> __SYSCALL_SIGSET_T_SIZE);
> >  # else
> >         result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
> >                                     timeout, __SYSCALL_SIGSET_T_SIZE);
> > @@ -71,8 +84,12 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t
> *info,
> >  # else
> >         /* on uClibc we use the kernel sigset_t size */
> >  # if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_rt_sigtimedwait_time64)
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = timeout ? timeout->tv_sec : 0,
> > +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +       };
> >         return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
> > -                             timeout, __SYSCALL_SIGSET_T_SIZE);
> > +                             timeout ? &__ts64 : 0,
> __SYSCALL_SIGSET_T_SIZE);
> >  # else
> >         return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
> >                               timeout, __SYSCALL_SIGSET_T_SIZE);
> > diff --git a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> > index d2d176a64..7830b2e2c 100644
> > --- a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> > +++ b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> > @@ -9,7 +9,7 @@
> >
> >  #include <sys/syscall.h>
> >
> > -#ifdef __NR_rt_sigtimedwait
> > +#if defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_rt_sigtimedwait_time64))
> >  # define __need_NULL
> >  # include <stddef.h>
> >  # include <signal.h>
> > diff --git a/libc/sysdeps/linux/common/alarm.c
> b/libc/sysdeps/linux/common/alarm.c
> > index 4e6e2215b..861f6ad8e 100644
> > --- a/libc/sysdeps/linux/common/alarm.c
> > +++ b/libc/sysdeps/linux/common/alarm.c
> > @@ -9,7 +9,7 @@
> >  #include <sys/syscall.h>
> >  #include <unistd.h>
> >
> > -#ifdef __NR_alarm && !defined(__UCLIBC_USE_TIME64__)
> > +#if defined(__NR_alarm) && !defined(__UCLIBC_USE_TIME64__)
> >  _syscall1(unsigned int, alarm, unsigned int, seconds)
> >  #else
> >  # include <sys/time.h>
> > diff --git a/libc/sysdeps/linux/common/clock_getres.c
> b/libc/sysdeps/linux/common/clock_getres.c
> > index d4b989958..c72b0a21c 100644
> > --- a/libc/sysdeps/linux/common/clock_getres.c
> > +++ b/libc/sysdeps/linux/common/clock_getres.c
> > @@ -10,9 +10,27 @@
> >  #include <sys/syscall.h>
> >  #include <time.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64)
> > -_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct
> timespec*, res)
> > +int clock_getres(clockid_t clock_id, struct timespec *res)
> > +{
> > +       struct ts64_struct __ts64;
> > +       int __ret = INLINE_SYSCALL(clock_getres_time64, 2, clock_id,
> &__ts64);
> > +       if (__ret == 0 && res) {
> > +               res->tv_sec = __ts64.tv_sec;
> > +               res->tv_nsec = __ts64.tv_nsec;
> > +       };
> > +
> > +       return __ret;
> > +}
> >  #elif defined(__NR_clock_getres)
> >  _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
> >  #else
> > diff --git a/libc/sysdeps/linux/common/clock_gettime.c
> b/libc/sysdeps/linux/common/clock_gettime.c
> > index a595bd691..dbb767c94 100644
> > --- a/libc/sysdeps/linux/common/clock_gettime.c
> > +++ b/libc/sysdeps/linux/common/clock_gettime.c
> > @@ -11,8 +11,27 @@
> >  #include <sys/syscall.h>
> >  #include <time.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
> > -_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*,
> tp)
> > +int clock_gettime(clockid_t clock_id, struct timespec *tp)
> > +{
> > +       struct ts64_struct __ts64;
> > +       int __ret = INLINE_SYSCALL(clock_gettime64, 2, clock_id,
> &__ts64);
> > +       if (tp) {
> > +               tp->tv_sec = __ts64.tv_sec;
> > +               tp->tv_nsec = __ts64.tv_nsec;
> > +       }
> > +
> > +       return __ret;
> > +}
> >  #elif defined(__NR_clock_gettime)
> >  _syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
> >  #else
> > diff --git a/libc/sysdeps/linux/common/clock_settime.c
> b/libc/sysdeps/linux/common/clock_settime.c
> > index 89550af5a..54bfa20e8 100644
> > --- a/libc/sysdeps/linux/common/clock_settime.c
> > +++ b/libc/sysdeps/linux/common/clock_settime.c
> > @@ -12,7 +12,22 @@
> >
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64)
> > -_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct
> timespec*, tp)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +int clock_settime(clockid_t clock_id, const struct timespec *tp)
> > +{
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = tp->tv_sec,
> > +               .tv_nsec = tp->tv_nsec
> > +       };
> > +
> > +       return INLINE_SYSCALL(clock_settime64, 2, clock_id, &__ts64);
> > +}
> > +
> >  #elif defined(__NR_clock_settime)
> >  _syscall2(int, clock_settime, clockid_t, clock_id, const struct
> timespec*, tp)
> >  #else
> > diff --git a/libc/sysdeps/linux/common/ppoll.c
> b/libc/sysdeps/linux/common/ppoll.c
> > index cb36149c5..16d836b6f 100644
> > --- a/libc/sysdeps/linux/common/ppoll.c
> > +++ b/libc/sysdeps/linux/common/ppoll.c
> > @@ -26,6 +26,15 @@
> >  #include <sys/poll.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +   __S64_TYPE tv_sec;
> > +   __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  static int
> >  __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec
> *timeout,
> >             const sigset_t *sigmask)
> > @@ -38,7 +47,11 @@ __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const
> struct timespec *timeout,
> >                 timeout = &tval;
> >         }
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64)
> > -       return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout,
> sigmask, __SYSCALL_SIGSET_T_SIZE);
> > +   struct ts64_struct __ts64 = {
> > +      .tv_sec = timeout ? timeout->tv_sec : 0,
> > +      .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +   };
> > +       return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout ?
> &__ts64 : 0, sigmask, __SYSCALL_SIGSET_T_SIZE);
> >  #else
> >         return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask,
> __SYSCALL_SIGSET_T_SIZE);
> >  #endif
> > diff --git a/libc/sysdeps/linux/common/pselect.c
> b/libc/sysdeps/linux/common/pselect.c
> > index 23bdab5cf..a189624ec 100644
> > --- a/libc/sysdeps/linux/common/pselect.c
> > +++ b/libc/sysdeps/linux/common/pselect.c
> > @@ -26,6 +26,15 @@
> >  #include <signal.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
> >                          fd_set *exceptfds, const struct timespec
> *timeout,
> >                          const sigset_t *sigmask)
> > @@ -57,7 +66,11 @@ static int __NC(pselect)(int nfds, fd_set *readfds,
> fd_set *writefds,
> >                 sigmask = (void *)&data;
> >         }
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
> > -       return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds,
> writefds, exceptfds, timeout, sigmask);
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = timeout ? timeout->tv_sec : 0,
> > +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +       };
> > +       return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds,
> writefds, exceptfds, timeout ? &__ts64 : 0, sigmask);
> >  #else
> >         return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds,
> exceptfds, timeout, sigmask);
> >  #endif
> > diff --git a/libc/sysdeps/linux/common/select.c
> b/libc/sysdeps/linux/common/select.c
> > index 3132a109c..a55a61df1 100644
> > --- a/libc/sysdeps/linux/common/select.c
> > +++ b/libc/sysdeps/linux/common/select.c
> > @@ -15,17 +15,22 @@
> >  # define __NR_select __NR__newselect
> >  #endif
> >
> > -#if !defined __NR_select && defined __NR_pselect6
> > +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
> >  # include <stdint.h>
> >  # define USEC_PER_SEC 1000000L
> >  #endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +#endif
> > +
> >  int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set
> *exceptfds,
> >                  struct timeval *timeout)
> >  {
> > -#ifdef __NR_select
> > -       return INLINE_SYSCALL(select, 5, n, readfds, writefds,
> exceptfds, timeout);
> > -#elif defined __NR_pselect6
> > +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
> >         struct timespec _ts, *ts = 0;
> >         if (timeout) {
> >                 uint32_t usec;
> > @@ -47,8 +52,18 @@ int __NC(select)(int n, fd_set *readfds, fd_set
> *writefds, fd_set *exceptfds,
> >
> >                 ts = &_ts;
> >         }
> > +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = ts ? ts->tv_sec : 0,
> > +               .tv_nsec = ts ? ts->tv_nsec : 0
> > +       };
> > +       return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds,
> exceptfds, timeout ? &__ts64 : 0, 0);
> > +#else
> >         return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds,
> exceptfds, ts, 0);
> >  #endif
> > +#elif defined(__NR_select)
> > +       return INLINE_SYSCALL(select, 5, n, readfds, writefds,
> exceptfds, timeout);
> > +#endif
> >  }
> >  /* we should guard it, but we need it in other files, so let it fail
> >   * if we miss any of the syscalls */
> > diff --git a/libc/sysdeps/linux/common/time.c
> b/libc/sysdeps/linux/common/time.c
> > index 22403f174..d084ffaad 100644
> > --- a/libc/sysdeps/linux/common/time.c
> > +++ b/libc/sysdeps/linux/common/time.c
> > @@ -9,7 +9,7 @@
> >  #include <sys/syscall.h>
> >  #include <time.h>
> >
> > -#ifdef __NR_time
> > +#if defined(__NR_time) && !defined(__UCLIBC_USE_TIME64__)
> >  _syscall_noerr1(time_t, time, time_t *, t)
> >  #else
> >  # include <sys/time.h>
> > diff --git a/libc/sysdeps/linux/common/timerfd.c
> b/libc/sysdeps/linux/common/timerfd.c
> > index 0f19b44ed..04db6ed00 100644
> > --- a/libc/sysdeps/linux/common/timerfd.c
> > +++ b/libc/sysdeps/linux/common/timerfd.c
> > @@ -16,12 +16,33 @@
> >  _syscall2(int, timerfd_create, int, clockid, int, flags)
> >  #endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct its64_struct {
> > +    __S64_TYPE interval_tv_sec;
> > +    __S64_TYPE interval_tv_nsec;
> > +    __S64_TYPE value_tv_sec;
> > +    __S64_TYPE value_tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  /*
> >   * timerfd_settime()
> >   */
> >  #if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64)
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64)
> > -_syscall4_64(int, timerfd_settime, int, ufd, int, flags, const struct
> itimerspec *, utmr, struct itimerspec *, otmr)
> > +int timerfd_settime(int ufd, int flags, const struct itimerspec *utmr,
> struct itimerspec *otmr)
> > +{
> > +    struct its64_struct __its64 = {
> > +        .interval_tv_sec = utmr->it_interval.tv_sec,
> > +        .interval_tv_nsec = utmr->it_interval.tv_nsec,
> > +        .value_tv_sec = utmr->it_value.tv_sec,
> > +        .value_tv_nsec = utmr->it_value.tv_nsec,
> > +    };
> > +
> > +    return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, &__its64,
> otmr);
> > +}
> >  #else
> >  _syscall4(int, timerfd_settime, int, ufd, int, flags, const struct
> itimerspec *, utmr, struct itimerspec *, otmr)
> >  #endif
> > diff --git a/libc/sysdeps/linux/common/utimensat.c
> b/libc/sysdeps/linux/common/utimensat.c
> > index 6a78ebb4f..0c87b5c45 100644
> > --- a/libc/sysdeps/linux/common/utimensat.c
> > +++ b/libc/sysdeps/linux/common/utimensat.c
> > @@ -9,9 +9,30 @@
> >  #include <sys/syscall.h>
> >  #include <sys/stat.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct uts64_struct {
> > +    __S64_TYPE tv_sec1;
> > +    __S64_TYPE tv_nsec1;
> > +    __S64_TYPE tv_sec2;
> > +    __S64_TYPE tv_nsec2;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__NR_utimensat) || defined(__NR_utimensat_time64)
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64)
> > -_syscall4_time64(int, utimensat, int, fd, const char *, path, const
> struct timespec *, times, int, flags)
> > +int utimensat(int fd, const char *path, const struct timespec times[2],
> int flags)
> > +{
> > +    struct uts64_struct __uts64 = {
> > +        .tv_sec1 = times ? times[0].tv_sec : 0,
> > +        .tv_nsec1 = times ? times[0].tv_nsec : 0,
> > +        .tv_sec2 = times ? times[1].tv_sec : 0,
> > +        .tv_nsec2 = times ? times[1].tv_nsec : 0
> > +    };
> > +
> > +    return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ?
> &__uts64 : 0, flags);
> > +}
> >  #else
> >  _syscall4(int, utimensat, int, fd, const char *, path, const struct
> timespec *, times, int, flags)
> >  #endif
> > diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> > index ce62b2ba2..0e76120ab 100644
> > --- a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> > +++ b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> > @@ -5,6 +5,16 @@
> >   * struct kernel_stat should look like...  It turns out each arch has a
> >   * different opinion on the subject... */
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +#include <bits/types.h>
> > +
> > +struct ts32_struct {
> > +       __S32_TYPE tv_sec;
> > +       __S32_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if __WORDSIZE == 64
> >  #define kernel_stat kernel_stat64
> >  #else
> > @@ -19,9 +29,15 @@ struct kernel_stat {
> >         __kernel_off_t  st_size;
> >         unsigned long   st_blksize;
> >         unsigned long   st_blocks;
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +       struct ts32_struct __st_atim32;
> > +       struct ts32_struct __st_mtim32;
> > +       struct ts32_struct __st_ctim32;
> > +#else
> >         struct timespec st_atim;
> >         struct timespec st_mtim;
> >         struct timespec st_ctim;
> > +#endif
> >         unsigned long   __unused4;
> >         unsigned long   __unused5;
> >  };
> > @@ -39,9 +55,15 @@ struct kernel_stat64 {
> >         long long st_size;              /* Size of file, in bytes.  */
> >         long st_blksize;                /* Optimal block size for I/O.
> */
> >         long long st_blocks;            /* Number 512-byte blocks
> allocated. */
> > -       struct timespec st_atim;        /* Time of last access.  */
> > -       struct timespec st_mtim;        /* Time of last modification.  */
> > -       struct timespec st_ctim;        /* Time of last status change.
> */
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +       struct ts32_struct __st_atim32;
> > +       struct ts32_struct __st_mtim32;
> > +       struct ts32_struct __st_ctim32;
> > +#else
> > +       struct timespec st_atim;
> > +       struct timespec st_mtim;
> > +       struct timespec st_ctim;
> > +#endif
> >         unsigned long int __uclibc_unused4;
> >         unsigned long int __uclibc_unused5;
> >  };
> > diff --git a/libc/sysdeps/linux/powerpc/bits/sem.h
> b/libc/sysdeps/linux/powerpc/bits/sem.h
> > index a9d895374..8d338eac0 100644
> > --- a/libc/sysdeps/linux/powerpc/bits/sem.h
> > +++ b/libc/sysdeps/linux/powerpc/bits/sem.h
> > @@ -35,6 +35,7 @@
> >  #define SETALL         17              /* set all semval's */
> >
> >
> > +
> >  /* Data structure describing a set of semaphores.  */
> >  struct semid_ds
> >  {
> > @@ -42,16 +43,31 @@ struct semid_ds
> >  #if __WORDSIZE == 32
> >    unsigned int __uclibc_unused1;
> >  #endif
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +  unsigned long int __sem_otime_internal_1; /* last semop() time */
> > +  unsigned long int __sem_otime_internal_2;
> > +#else
> >    __time_t sem_otime;                  /* last semop() time */
> > +#endif
> >  #if __WORDSIZE == 32
> >    unsigned int __uclibc_unused2;
> >  #endif
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +  unsigned long int __sem_ctime_internal_1; /* last time changed by
> semctl() */
> > +  unsigned long int __sem_ctime_internal_2;
> > +#else
> >    __time_t sem_ctime;                  /* last time changed by semctl()
> */
> > +#endif
> >    unsigned long int sem_nsems;         /* number of semaphores in set */
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +  __time_t sem_otime;
> > +  __time_t sem_ctime;
> > +#endif
> >    unsigned long __uclibc_unused3;
> >    unsigned long __uclibc_unused4;
> >  };
> >
> > +
> >  /* The user should define a union like the following to use it for
> arguments
> >     for `semctl'.
> >
> > diff --git a/libpthread/nptl/pthread_mutex_timedlock.c
> b/libpthread/nptl/pthread_mutex_timedlock.c
> > index 25f9ec3b2..d55495683 100644
> > --- a/libpthread/nptl/pthread_mutex_timedlock.c
> > +++ b/libpthread/nptl/pthread_mutex_timedlock.c
> > @@ -23,6 +23,15 @@
> >  #include <lowlevellock.h>
> >  #include <not-cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  /* We need to build this function with optimization to avoid
> >   * lll_timedlock erroring out with
> >   * error: can't find a register in class ‘GENERAL_REGS’ while reloading
> ‘asm’
> > @@ -265,10 +274,14 @@ pthread_mutex_timedlock (
> >             INTERNAL_SYSCALL_DECL (__err);
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> > +           struct ts64_struct __ts64 = {
> > +               .tv_sec = abstime ? abstime->tv_sec : 0,
> > +               .tv_nsec = abstime ? abstime->tv_nsec : 0
> > +           };
> >             int e = INTERNAL_SYSCALL (futex_time64, __err, 4,
> &mutex->__data.__lock,
> >                                       __lll_private_flag (FUTEX_LOCK_PI,
> >                                                           private), 1,
> > -                                     abstime);
> > +                                     &__ts64);
> >  #else
> >             int e = INTERNAL_SYSCALL (futex, __err, 4,
> &mutex->__data.__lock,
> >                                       __lll_private_flag (FUTEX_LOCK_PI,
> > @@ -454,7 +467,7 @@ pthread_mutex_timedlock (
> >                       }
> >
> >                     struct timeval tv;
> > -                   struct timespec rt;
> > +                   struct timespec rt, *rtp;
> >
> >                     /* Get the current time.  */
> >                     (void) gettimeofday (&tv, NULL);
> > @@ -475,8 +488,9 @@ pthread_mutex_timedlock (
>
> Starting from this hunk...
>
> >                         goto failpp;
> >                       }
> >
> > +                   rtp = &rt;
> >                     lll_futex_timed_wait (&mutex->__data.__lock,
> > -                                         ceilval | 2, &rt,
> > +                                         ceilval | 2, rtp,
> >                                           PTHREAD_MUTEX_PSHARED (mutex));
> >                   }
> >               }
> > diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> > index 49aab0293..1ea2a888a 100644
> > --- a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> > +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> > @@ -95,7 +95,7 @@ __pthread_cond_timedwait (
> >
> >    while (1)
> >      {
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        {
> >  #ifdef __NR_clock_gettime
> >         INTERNAL_SYSCALL_DECL (err);
> > @@ -164,8 +164,9 @@ __pthread_cond_timedwait (
> >        cbuffer.oldtype = __pthread_enable_asynccancel ();
> >
> >        /* Wait until woken by signal or broadcast.  */
> > +      rtp = &rt;
> >        err = lll_futex_timed_wait (&cond->__data.__futex,
> > -                                 futex_val, &rt, pshared);
> > +                                 futex_val, rtp, pshared);
> >
> >        /* Disable asynchronous cancellation.  */
> >        __pthread_disable_asynccancel (cbuffer.oldtype);
> > diff --git
> a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> > index 596f5df51..379e92b43 100644
> > --- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> > +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> > @@ -81,7 +81,7 @@ pthread_rwlock_timedrdlock (
> >        (void) gettimeofday (&tv, NULL);
> >
> >        /* Convert the absolute timeout value to a relative timeout.  */
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
> >        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
> >        if (rt.tv_nsec < 0)
> > @@ -112,8 +112,9 @@ pthread_rwlock_timedrdlock (
> >        lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
> >
> >        /* Wait for the writer to finish.  */
> > +      rtp = &rt;
> >        err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
> > -                                 waitval, &rt, rwlock->__data.__shared);
> > +                                 waitval, rtp, rwlock->__data.__shared);
> >        /* Get the lock.  */
> >        lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
> > diff --git
> a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> > index 0b04b357a..3ce9f9b13 100644
> > --- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> > +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> > @@ -72,7 +72,7 @@ pthread_rwlock_timedwrlock (
> >        (void) gettimeofday (&tv, NULL);
> >
> >        /* Convert the absolute timeout value to a relative timeout.  */
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
> >        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
> >        if (rt.tv_nsec < 0)
> > @@ -102,8 +102,9 @@ pthread_rwlock_timedwrlock (
> >        lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
> >
> >        /* Wait for the writer or reader(s) to finish.  */
> > +      rtp = &rt;
> >        err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup,
> > -                                 waitval, &rt, rwlock->__data.__shared);
> > +                                 waitval, rtp, rwlock->__data.__shared);
> >
> >        /* Get the lock.  */
> >        lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> > index 4294a20b0..5f7301976 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> > @@ -63,7 +63,7 @@ __lll_timedlock_wait (int *futex, const struct
> timespec *abstime, int private)
> >        (void) gettimeofday (&tv, NULL);
> >
> >        /* Compute relative timeout.  */
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
> >        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
> >        if (rt.tv_nsec < 0)
> > @@ -76,7 +76,8 @@ __lll_timedlock_wait (int *futex, const struct
> timespec *abstime, int private)
> >         return ETIMEDOUT;
> >
> >        /* Wait.  */
> > -      lll_futex_timed_wait (futex, 2, &rt, private);
> > +      rtp = &rt;
> > +      lll_futex_timed_wait (futex, 2, rtp, private);
> >      }
> >
> >    return 0;
> > @@ -95,7 +96,7 @@ __lll_timedwait_tid (int *tidp, const struct timespec
> *abstime)
> >    while ((tid = *tidp) != 0)
> >      {
> >        struct timeval tv;
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >
> >        /* Get the current time.  */
> >        (void) __gettimeofday (&tv, NULL);
> > @@ -115,7 +116,8 @@ __lll_timedwait_tid (int *tidp, const struct
> timespec *abstime)
> >
> >        /* Wait until thread terminates.  The kernel so far does not use
> >          the private futex operations for this.  */
> > -      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) ==
> -ETIMEDOUT)
> > +      rtp = &rt;
> > +      if (lll_futex_timed_wait (tidp, tid, rtp, LLL_SHARED) ==
> -ETIMEDOUT)
> >         return ETIMEDOUT;
> >      }
> >
>
> ...and up to here: why are all these changes adding an intermediate
> pointer needed?
>
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> > index e72fe5234..4209a21d3 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> > @@ -71,18 +71,49 @@
> >  # endif
> >  #endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> > +
> >  #define lll_futex_wait(futexp, val, private) \
> > -  lll_futex_timed_wait(futexp, val, NULL, private)
> > +  ({
>      \
> > +    INTERNAL_SYSCALL_DECL (__err);
>      \
> > +    long int __ret;
>       \
> > +    __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),
>               \
> > +                             __lll_private_flag (FUTEX_WAIT, private),
>      \
> > +                             (val), NULL);                           \
> > +    __ret;
>      \
> > +  })
> > +
> > +#else
> > +
> > +#define lll_futex_wait(futexp, val, private) \
> > +  ({
>      \
> > +    INTERNAL_SYSCALL_DECL (__err);
>      \
> > +    long int __ret;
>       \
> > +    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),
>      \
> > +                             __lll_private_flag (FUTEX_WAIT, private),
>      \
> > +                             (val), NULL);                           \
> > +    __ret;
>      \
> > +  })
> > +
> > +#endif
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> >
> > +struct __ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#define ptr_timespec_to_ts64(ts) \
> > +  (&(struct __ts64_struct) {.tv_sec = ts->tv_sec, .tv_nsec =
> ts->tv_nsec})
> > +
> >  #define lll_futex_timed_wait(futexp, val, timespec, private) \
> >    ({
>      \
> >      INTERNAL_SYSCALL_DECL (__err);
>      \
> >      long int __ret;
>       \
> >      __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),
>               \
> >                               __lll_private_flag (FUTEX_WAIT, private),
>      \
> > -                             (val), (timespec));
>      \
> > +                             (val), (ptr_timespec_to_ts64(timespec)));
>                      \
> >      __ret;
>      \
> >    })
> >
> > diff --git
> a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> > index 7b4e84343..5781359fb 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> > @@ -73,7 +73,7 @@ __lll_robust_timedlock_wait (int *futex, const struct
> timespec *abstime,
> >    do
> >      {
> >        struct timeval tv;
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >
> >        /* Get the current time.  */
> >        (void) __gettimeofday (&tv, NULL);
> > @@ -99,8 +99,8 @@ __lll_robust_timedlock_wait (int *futex, const struct
> timespec *abstime,
> >        if (oldval != newval
> >           && atomic_compare_and_exchange_bool_acq (futex, newval,
> oldval))
> >         continue;
> > -
> > -      lll_futex_timed_wait (futex, newval, &rt, private);
> > +      rtp = &rt;
> > +      lll_futex_timed_wait (futex, newval, rtp, private);
> >
> >      try:
> >        ;
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> > index 8c3ef47c5..05ba5bc13 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> > @@ -51,7 +51,7 @@ sem_timedwait (sem_t *sem, const struct timespec
> *abstime)
> >    while (1)
> >      {
> >        struct timeval tv;
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        int sec, nsec;
> >
> >        /* Get the current time.  */
> > @@ -79,10 +79,12 @@ sem_timedwait (sem_t *sem, const struct timespec
> *abstime)
> >        rt.tv_sec = sec;
> >        rt.tv_nsec = nsec;
> >
> > +      rtp = &rt;
> > +
> >        /* Enable asynchronous cancellation.  Required by the standard.
> */
> >        int oldtype = __pthread_enable_asynccancel ();
> >
> > -      err = lll_futex_timed_wait (&isem->value, 0, &rt,
> > +      err = lll_futex_timed_wait (&isem->value, 0, rtp,
> >                                   isem->private ^ FUTEX_PRIVATE_FLAG);
> >
> >        /* Disable asynchronous cancellation.  */
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> > index 80d242f21..d7c2aa804 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> > @@ -38,6 +38,17 @@ static int compat_timer_settime (timer_t timerid, int
> flags,
> >  #  define timer_settime timer_settime_alias
> >  # endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct its64_struct {
> > +    __S64_TYPE interval_tv_sec;
> > +    __S64_TYPE interval_tv_nsec;
> > +    __S64_TYPE value_tv_sec;
> > +    __S64_TYPE value_tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >
> >  int
> >  timer_settime (
> > @@ -55,8 +66,14 @@ timer_settime (
> >
> >        /* Delete the kernel timer object.  */
> >  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
> > +      struct its64_struct __its64 = {
> > +            .interval_tv_sec = value->it_interval.tv_sec,
> > +            .interval_tv_nsec = value->it_interval.tv_nsec,
> > +            .value_tv_sec = value->it_value.tv_sec,
> > +            .value_tv_nsec = value->it_value.tv_nsec,
> > +      };
> >        int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
> > -                               value, ovalue);
> > +                               value ? &__its64 : 0, ovalue);
> >  # else
> >        int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
> >                                 value, ovalue);
> > diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c
> > index b66b60231..eff40d68f 100644
> > --- a/librt/clock_gettime.c
> > +++ b/librt/clock_gettime.c
> > @@ -22,10 +22,26 @@
> >  #include <sys/time.h>
> >  #include "kernel-posix-cpu-timers.h"
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +  __S64_TYPE tv_sec;
> > +  __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
> >  #define SYSCALL_GETTIME \
> > -  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
> > -  break
> > +  { \
> > +  struct ts64_struct __ts64; \
> > +  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, &__ts64); \
> > +  if (tp) { \
> > +    tp->tv_sec = __ts64.tv_sec; \
> > +    tp->tv_nsec = __ts64.tv_nsec; \
> > +  } \
> > +  break; \
> > +  }
> >  #else
> >  #define SYSCALL_GETTIME \
> >    retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
> > diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c
> > index eaae75720..786f7eede 100644
> > --- a/librt/clock_nanosleep.c
> > +++ b/librt/clock_nanosleep.c
> > @@ -21,6 +21,14 @@
> >
> >  #include "kernel-posix-cpu-timers.h"
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> >
> >  /* We can simply use the syscall.  The CPU clocks are not supported
> >     with this function.  */
> > @@ -36,18 +44,27 @@ clock_nanosleep (clockid_t clock_id, int flags,
> const struct timespec *req,
> >    if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
> >      clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
> >
> > -  if (SINGLE_THREAD_P)
> > +  if (SINGLE_THREAD_P) {
> >  #if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_clock_nanosleep_time64)
> > -    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req, rem);
> > +    struct ts64_struct __ts64 = {
> > +      .tv_sec = req ? req->tv_sec : 0,
> > +      .tv_nsec = req ? req->tv_nsec : 0
> > +    };
> > +    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req ? &__ts64 : 0, rem);
> >  #else
> >      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
> req, rem);
> >  #endif
> > +  }
> >    else
> >      {
> >  #ifdef __NEW_THREADS
> >        int oldstate = LIBC_CANCEL_ASYNC ();
> >  #if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_clock_nanosleep_time64)
> > -      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req, rem);
> > +      struct ts64_struct __ts64_2 = {
> > +        .tv_sec = req ? req->tv_sec : 0,
> > +        .tv_nsec = req ? req->tv_nsec : 0
> > +      };
> > +      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req ? &__ts64_2 : 0, rem);
> >  #else
> >        r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
> req,
> >                             rem);
> > diff --git a/librt/mq_timedreceive.c b/librt/mq_timedreceive.c
> > index db1ae1aa8..818f54faa 100644
> > --- a/librt/mq_timedreceive.c
> > +++ b/librt/mq_timedreceive.c
> > @@ -8,13 +8,29 @@
> >  #include <unistd.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_mq_timedreceive_time64)
> > -#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64
> > +int _NC(mq_timedreceive)(mqd_t mqdes, char *restrict msg_ptr, size_t
> msg_len, unsigned int *restrict msq_prio, const struct timespec *restrict
> abs_timeout)
> > +{
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
> > +               .tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
> > +       };
> > +
> > +       return INLINE_SYSCALL(mq_timedreceive_time64, 5, mqdes, msg_ptr,
> msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
> > +}
> >  #else
> >  #define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive
> > -#endif
> > -
> >  _syscall5(ssize_t, __NC(mq_timedreceive), mqd_t, mqdes, char
> *__restrict, msg_ptr, size_t, msg_len, unsigned int *__restrict, msq_prio,
> const struct timespec *__restrict, abs_timeout)
> > +#endif
> >
> >  CANCELLABLE_SYSCALL(ssize_t, mq_timedreceive, (mqd_t mqdes, char
> *__restrict msg_ptr, size_t msq_len, unsigned int *__restrict msq_prio,
> const struct timespec *__restrict abs_timeout),
> >                     (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
> > diff --git a/librt/mq_timedsend.c b/librt/mq_timedsend.c
> > index 6afaf5157..e8deea9cb 100644
> > --- a/librt/mq_timedsend.c
> > +++ b/librt/mq_timedsend.c
> > @@ -8,13 +8,31 @@
> >  #include <unistd.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64)
> >  #define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64
> > +int _NC(mq_timedsend)(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
> unsigned int msq_prio, const struct timespec *abs_timeout)
> > +{
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
> > +               .tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
> > +       };
> > +
> > +       return INLINE_SYSCALL(mq_timedsend_time64, 5, mqdes, msg_ptr,
> msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
> > +}
> >  #else
> >  #define __NR___mq_timedsend_nocancel __NR_mq_timedsend
> > +_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr,
> size_t, msg_len, unsigned int, msq_prio, const struct timespec *,
> abs_timeout)
> >  #endif
> >
> > -_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr,
> size_t, msg_len, unsigned int, msq_prio, const struct timespec *,
> abs_timeout)
> >  CANCELLABLE_SYSCALL(int, mq_timedsend, (mqd_t mqdes, const char
> *msg_ptr, size_t msq_len, unsigned int msq_prio, const struct timespec
> *abs_timeout),
> >                     (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
> >  lt_libc_hidden(mq_timedsend)
> > diff --git a/librt/timer_settime.c b/librt/timer_settime.c
> > index 022880297..31202b07a 100644
> > --- a/librt/timer_settime.c
> > +++ b/librt/timer_settime.c
> > @@ -9,13 +9,36 @@
> >
> >  #include "kernel-posix-timers.h"
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct its64_struct {
> > +    __S64_TYPE interval_tv_sec;
> > +    __S64_TYPE interval_tv_nsec;
> > +    __S64_TYPE value_tv_sec;
> > +    __S64_TYPE value_tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__NR_timer_settime) || defined(__NR_timer_settime64)
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
> > -#define __NR___syscall_timer_settime __NR_timer_settime64
> > +int timer_settime(timer_t timerid, int flags, const struct itimerspec
> *value, struct itimerspec *ovalue)
> > +{
> > +       struct timer *kt = (struct timer *)timerid;
> > +
> > +    struct its64_struct __its64 = {
> > +        .interval_tv_sec = value->it_interval.tv_sec,
> > +        .interval_tv_nsec = value->it_interval.tv_nsec,
> > +        .value_tv_sec = value->it_value.tv_sec,
> > +        .value_tv_nsec = value->it_value.tv_nsec,
> > +    };
> > +
> > +       return INLINE_SYSCALL(timer_settime64, 4, kt->ktimerid, flags,
> value ? &__its64: 0, ovalue);
> > +}
> >  #else
> > +
> >  #define __NR___syscall_timer_settime __NR_timer_settime
> > -#endif
> >
> >  static __inline__ _syscall4(int, __syscall_timer_settime,
> kernel_timer_t, ktimerid,
> >                         int, flags, const void *, value, void *, ovalue);
> > @@ -31,3 +54,4 @@ int timer_settime(timer_t timerid, int flags, const
> struct itimerspec *value,
> >  }
> >
> >  #endif
> > +#endif
> > --
> > 2.43.2
> >
> > _______________________________________________
> > devel mailing list -- devel@uclibc-ng.org
> > To unsubscribe send an email to devel-leave@uclibc-ng.org
>
>
>
> --
> Thanks.
> -- Max
>
Dmitry Chestnykh Feb. 24, 2024, 6:29 p.m. UTC | #3
Patch is splitted, intermediate pointers removed.

сб, 24 февр. 2024 г. в 19:09, Max Filippov <jcmvbkbc@gmail.com>:

> On Sat, Feb 24, 2024 at 7:01 AM Dmitry Chestnykh <dm.chestnykh@gmail.com>
> wrote:
> >
> > PowerPC is big-endian architecture, so there are some
> > significant differences in comparison with time64 support
> > for little-endian architectures like ARM and xtensa.
>
> JFYI xtensa supports both little and big endianness. Which
> suggests that it needs similar treatment as a BE PPC.
>
> > The main difference is that we strictly need to pass two 64bit
> > values to system calls because Linux Kernel internally uses
> > `struct __ketnel_timespec` and similar, which consists of two
> > 64bit fields.
> > For this reason many files have been changed to convert
> > timespec-family structures (mixed of 64bit and 32bit values)
> > to the 64bit-only structures for using as system calls args.
> > Now time64 syscalls works properly both for LE (ARM, xtensa)
> > and BE (PPC) memory layouts.
>
> I'd suggest splitting this change into two parts: generic
> arch-independent changes followed by PPC-specific changes.
>
> > Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
> > ---
> >  extra/Configs/Config.in                       |  2 +-
> >  libc/inet/socketcalls.c                       | 16 ++++++++-
> >  libc/misc/sysvipc/sem.c                       | 16 ++++++++-
> >  libc/signal/sigwait.c                         |  3 +-
> >  libc/sysdeps/linux/common/__rt_sigtimedwait.c | 23 ++++++++++--
> >  libc/sysdeps/linux/common/__rt_sigwaitinfo.c  |  2 +-
> >  libc/sysdeps/linux/common/alarm.c             |  2 +-
> >  libc/sysdeps/linux/common/clock_getres.c      | 20 ++++++++++-
> >  libc/sysdeps/linux/common/clock_gettime.c     | 21 ++++++++++-
> >  libc/sysdeps/linux/common/clock_settime.c     | 17 ++++++++-
> >  libc/sysdeps/linux/common/ppoll.c             | 15 +++++++-
> >  libc/sysdeps/linux/common/pselect.c           | 15 +++++++-
> >  libc/sysdeps/linux/common/select.c            | 23 +++++++++---
> >  libc/sysdeps/linux/common/time.c              |  2 +-
> >  libc/sysdeps/linux/common/timerfd.c           | 23 +++++++++++-
> >  libc/sysdeps/linux/common/utimensat.c         | 23 +++++++++++-
> >  libc/sysdeps/linux/powerpc/bits/kernel_stat.h | 28 +++++++++++++--
> >  libc/sysdeps/linux/powerpc/bits/sem.h         | 16 +++++++++
> >  libpthread/nptl/pthread_mutex_timedlock.c     | 20 +++++++++--
> >  .../sysdeps/pthread/pthread_cond_timedwait.c  |  5 +--
> >  .../pthread/pthread_rwlock_timedrdlock.c      |  5 +--
> >  .../pthread/pthread_rwlock_timedwrlock.c      |  5 +--
> >  .../sysdeps/unix/sysv/linux/lowlevellock.c    | 10 +++---
> >  .../sysdeps/unix/sysv/linux/lowlevellock.h    | 35 +++++++++++++++++--
> >  .../unix/sysv/linux/lowlevelrobustlock.c      |  6 ++--
> >  .../sysdeps/unix/sysv/linux/sem_timedwait.c   |  6 ++--
> >  .../sysdeps/unix/sysv/linux/timer_settime.c   | 19 +++++++++-
> >  librt/clock_gettime.c                         | 20 +++++++++--
> >  librt/clock_nanosleep.c                       | 23 ++++++++++--
> >  librt/mq_timedreceive.c                       | 22 ++++++++++--
> >  librt/mq_timedsend.c                          | 20 ++++++++++-
> >  librt/timer_settime.c                         | 28 +++++++++++++--
> >  32 files changed, 435 insertions(+), 56 deletions(-)
> >
> > diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
> > index 9351dffc8..f11a63b79 100644
> > --- a/extra/Configs/Config.in
> > +++ b/extra/Configs/Config.in
> > @@ -1026,7 +1026,7 @@ config UCLIBC_FALLBACK_TO_ETC_LOCALTIME
> >
> >  config UCLIBC_USE_TIME64
> >         bool "Use *time64 syscalls instead of 32bit ones (if possible)"
> > -       depends on TARGET_arm || TARGET_xtensa
> > +       depends on TARGET_arm || TARGET_powerpc || TARGET_xtensa
> >         # TODO: add support for other architectures
> >         default n
> >
> > diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c
> > index eb0983698..7ec439887 100644
> > --- a/libc/inet/socketcalls.c
> > +++ b/libc/inet/socketcalls.c
> > @@ -268,12 +268,26 @@ lt_libc_hidden(recvmsg)
> >  #endif
> >
> >  #ifdef L_recvmmsg
> > +
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
>
> This pattern and a similar pattern with struct its64_struct
> is repeated multiple times in this patch. It seems that this
> repetition can be easily avoided?
>
> > +
> >  #ifdef __ASSUME_RECVMMSG_SYSCALL
> >  static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t
> vlen,
> >                               int flags, struct timespec *tmo)
> >  {
> >  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64)
> > -       return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg,
> vlen, flags, tmo);
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = tmo ? tmo->tv_sec : 0,
> > +               .tv_nsec = tmo ? tmo->tv_nsec : 0
> > +       };
> > +       return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg,
> vlen, flags, tmo ? &__ts64 : 0);
> >  # elif defined(__NR_recvmmsg)
> >         return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen,
> flags, tmo);
> >  # elif __NR_socketcall
> > diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c
> > index cd541761c..d0bd0ba28 100644
> > --- a/libc/misc/sysvipc/sem.c
> > +++ b/libc/misc/sysvipc/sem.c
> > @@ -96,7 +96,21 @@ int semop (int semid, struct sembuf *sops, size_t
> nsops)
> >  #ifdef L_semtimedop
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_semtimedop_time64)
> > -_syscall4_time64(int, semtimedop, int, semid, struct sembuf *, sops,
> size_t, nsops, const struct timespec *, timeout)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +int semtimedop(int semid, struct sembuf *sops, size_t nsops, const
> struct timespec *timeout) {
> > +    struct ts64_struct __ts64 = {
> > +        .tv_sec = timeout ? timeout->tv_sec : 0,
> > +        .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +    };
> > +
> > +    return INLINE_SYSCALL(semtimedop_time64, 4, semid, sops, nsops,
> timeout ? &__ts64 : 0);
> > +}
> > +
> >  #elif defined(__NR_semtimedop)
> >  _syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t,
> nsops, const struct timespec *, timeout)
> >
> > diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c
> > index 3557a039e..b237534cd 100644
> > --- a/libc/signal/sigwait.c
> > +++ b/libc/signal/sigwait.c
> > @@ -24,7 +24,8 @@
> >  #include <signal.h>
> >  #include <cancel.h>
> >
> > -#if defined __NR_rt_sigtimedwait && defined __UCLIBC_HAS_REALTIME__
> > +#if (defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__)
> && defined(__NR_rt_sigtimedwait_time64))) && \
> > +    defined(__UCLIBC_HAS_REALTIME__)
> >
> >  #include <string.h>
> >
> > diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> > index bd82ca6d5..cd25fe177 100644
> > --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> > +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
> > @@ -9,7 +9,7 @@
> >
> >  #include <sys/syscall.h>
> >
> > -#ifdef __NR_rt_sigtimedwait
> > +#if defined(__NR_rt_sigtimedwait) ||
> (defined(__NR_rt_sigtimedwait_time64) && defined(__UCLIBC_USE_TIME64__))
> >  # include <signal.h>
> >  # include <cancel.h>
> >  # ifdef __UCLIBC_HAS_THREADS_NATIVE__
> > @@ -21,6 +21,15 @@
> >  #  include <string.h>
> >  # endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
> >                        const struct timespec *timeout)
> >  {
> > @@ -53,8 +62,12 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t
> *info,
> >            real size of the user-level sigset_t.  */
> >         /* on uClibc we use the kernel sigset_t size */
> >  # if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_rt_sigtimedwait_time64)
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = timeout ? timeout->tv_sec : 0,
> > +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +       };
> >         result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
> > -                                   timeout, __SYSCALL_SIGSET_T_SIZE);
> > +                                   timeout ? &__ts64 : 0,
> __SYSCALL_SIGSET_T_SIZE);
> >  # else
> >         result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
> >                                     timeout, __SYSCALL_SIGSET_T_SIZE);
> > @@ -71,8 +84,12 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t
> *info,
> >  # else
> >         /* on uClibc we use the kernel sigset_t size */
> >  # if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_rt_sigtimedwait_time64)
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = timeout ? timeout->tv_sec : 0,
> > +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +       };
> >         return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
> > -                             timeout, __SYSCALL_SIGSET_T_SIZE);
> > +                             timeout ? &__ts64 : 0,
> __SYSCALL_SIGSET_T_SIZE);
> >  # else
> >         return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
> >                               timeout, __SYSCALL_SIGSET_T_SIZE);
> > diff --git a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> > index d2d176a64..7830b2e2c 100644
> > --- a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> > +++ b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
> > @@ -9,7 +9,7 @@
> >
> >  #include <sys/syscall.h>
> >
> > -#ifdef __NR_rt_sigtimedwait
> > +#if defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_rt_sigtimedwait_time64))
> >  # define __need_NULL
> >  # include <stddef.h>
> >  # include <signal.h>
> > diff --git a/libc/sysdeps/linux/common/alarm.c
> b/libc/sysdeps/linux/common/alarm.c
> > index 4e6e2215b..861f6ad8e 100644
> > --- a/libc/sysdeps/linux/common/alarm.c
> > +++ b/libc/sysdeps/linux/common/alarm.c
> > @@ -9,7 +9,7 @@
> >  #include <sys/syscall.h>
> >  #include <unistd.h>
> >
> > -#ifdef __NR_alarm && !defined(__UCLIBC_USE_TIME64__)
> > +#if defined(__NR_alarm) && !defined(__UCLIBC_USE_TIME64__)
> >  _syscall1(unsigned int, alarm, unsigned int, seconds)
> >  #else
> >  # include <sys/time.h>
> > diff --git a/libc/sysdeps/linux/common/clock_getres.c
> b/libc/sysdeps/linux/common/clock_getres.c
> > index d4b989958..c72b0a21c 100644
> > --- a/libc/sysdeps/linux/common/clock_getres.c
> > +++ b/libc/sysdeps/linux/common/clock_getres.c
> > @@ -10,9 +10,27 @@
> >  #include <sys/syscall.h>
> >  #include <time.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64)
> > -_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct
> timespec*, res)
> > +int clock_getres(clockid_t clock_id, struct timespec *res)
> > +{
> > +       struct ts64_struct __ts64;
> > +       int __ret = INLINE_SYSCALL(clock_getres_time64, 2, clock_id,
> &__ts64);
> > +       if (__ret == 0 && res) {
> > +               res->tv_sec = __ts64.tv_sec;
> > +               res->tv_nsec = __ts64.tv_nsec;
> > +       };
> > +
> > +       return __ret;
> > +}
> >  #elif defined(__NR_clock_getres)
> >  _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
> >  #else
> > diff --git a/libc/sysdeps/linux/common/clock_gettime.c
> b/libc/sysdeps/linux/common/clock_gettime.c
> > index a595bd691..dbb767c94 100644
> > --- a/libc/sysdeps/linux/common/clock_gettime.c
> > +++ b/libc/sysdeps/linux/common/clock_gettime.c
> > @@ -11,8 +11,27 @@
> >  #include <sys/syscall.h>
> >  #include <time.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
> > -_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*,
> tp)
> > +int clock_gettime(clockid_t clock_id, struct timespec *tp)
> > +{
> > +       struct ts64_struct __ts64;
> > +       int __ret = INLINE_SYSCALL(clock_gettime64, 2, clock_id,
> &__ts64);
> > +       if (tp) {
> > +               tp->tv_sec = __ts64.tv_sec;
> > +               tp->tv_nsec = __ts64.tv_nsec;
> > +       }
> > +
> > +       return __ret;
> > +}
> >  #elif defined(__NR_clock_gettime)
> >  _syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
> >  #else
> > diff --git a/libc/sysdeps/linux/common/clock_settime.c
> b/libc/sysdeps/linux/common/clock_settime.c
> > index 89550af5a..54bfa20e8 100644
> > --- a/libc/sysdeps/linux/common/clock_settime.c
> > +++ b/libc/sysdeps/linux/common/clock_settime.c
> > @@ -12,7 +12,22 @@
> >
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64)
> > -_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct
> timespec*, tp)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +int clock_settime(clockid_t clock_id, const struct timespec *tp)
> > +{
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = tp->tv_sec,
> > +               .tv_nsec = tp->tv_nsec
> > +       };
> > +
> > +       return INLINE_SYSCALL(clock_settime64, 2, clock_id, &__ts64);
> > +}
> > +
> >  #elif defined(__NR_clock_settime)
> >  _syscall2(int, clock_settime, clockid_t, clock_id, const struct
> timespec*, tp)
> >  #else
> > diff --git a/libc/sysdeps/linux/common/ppoll.c
> b/libc/sysdeps/linux/common/ppoll.c
> > index cb36149c5..16d836b6f 100644
> > --- a/libc/sysdeps/linux/common/ppoll.c
> > +++ b/libc/sysdeps/linux/common/ppoll.c
> > @@ -26,6 +26,15 @@
> >  #include <sys/poll.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +   __S64_TYPE tv_sec;
> > +   __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  static int
> >  __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec
> *timeout,
> >             const sigset_t *sigmask)
> > @@ -38,7 +47,11 @@ __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const
> struct timespec *timeout,
> >                 timeout = &tval;
> >         }
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64)
> > -       return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout,
> sigmask, __SYSCALL_SIGSET_T_SIZE);
> > +   struct ts64_struct __ts64 = {
> > +      .tv_sec = timeout ? timeout->tv_sec : 0,
> > +      .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +   };
> > +       return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout ?
> &__ts64 : 0, sigmask, __SYSCALL_SIGSET_T_SIZE);
> >  #else
> >         return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask,
> __SYSCALL_SIGSET_T_SIZE);
> >  #endif
> > diff --git a/libc/sysdeps/linux/common/pselect.c
> b/libc/sysdeps/linux/common/pselect.c
> > index 23bdab5cf..a189624ec 100644
> > --- a/libc/sysdeps/linux/common/pselect.c
> > +++ b/libc/sysdeps/linux/common/pselect.c
> > @@ -26,6 +26,15 @@
> >  #include <signal.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
> >                          fd_set *exceptfds, const struct timespec
> *timeout,
> >                          const sigset_t *sigmask)
> > @@ -57,7 +66,11 @@ static int __NC(pselect)(int nfds, fd_set *readfds,
> fd_set *writefds,
> >                 sigmask = (void *)&data;
> >         }
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
> > -       return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds,
> writefds, exceptfds, timeout, sigmask);
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = timeout ? timeout->tv_sec : 0,
> > +               .tv_nsec = timeout ? timeout->tv_nsec : 0
> > +       };
> > +       return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds,
> writefds, exceptfds, timeout ? &__ts64 : 0, sigmask);
> >  #else
> >         return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds,
> exceptfds, timeout, sigmask);
> >  #endif
> > diff --git a/libc/sysdeps/linux/common/select.c
> b/libc/sysdeps/linux/common/select.c
> > index 3132a109c..a55a61df1 100644
> > --- a/libc/sysdeps/linux/common/select.c
> > +++ b/libc/sysdeps/linux/common/select.c
> > @@ -15,17 +15,22 @@
> >  # define __NR_select __NR__newselect
> >  #endif
> >
> > -#if !defined __NR_select && defined __NR_pselect6
> > +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
> >  # include <stdint.h>
> >  # define USEC_PER_SEC 1000000L
> >  #endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +#endif
> > +
> >  int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set
> *exceptfds,
> >                  struct timeval *timeout)
> >  {
> > -#ifdef __NR_select
> > -       return INLINE_SYSCALL(select, 5, n, readfds, writefds,
> exceptfds, timeout);
> > -#elif defined __NR_pselect6
> > +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
> >         struct timespec _ts, *ts = 0;
> >         if (timeout) {
> >                 uint32_t usec;
> > @@ -47,8 +52,18 @@ int __NC(select)(int n, fd_set *readfds, fd_set
> *writefds, fd_set *exceptfds,
> >
> >                 ts = &_ts;
> >         }
> > +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = ts ? ts->tv_sec : 0,
> > +               .tv_nsec = ts ? ts->tv_nsec : 0
> > +       };
> > +       return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds,
> exceptfds, timeout ? &__ts64 : 0, 0);
> > +#else
> >         return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds,
> exceptfds, ts, 0);
> >  #endif
> > +#elif defined(__NR_select)
> > +       return INLINE_SYSCALL(select, 5, n, readfds, writefds,
> exceptfds, timeout);
> > +#endif
> >  }
> >  /* we should guard it, but we need it in other files, so let it fail
> >   * if we miss any of the syscalls */
> > diff --git a/libc/sysdeps/linux/common/time.c
> b/libc/sysdeps/linux/common/time.c
> > index 22403f174..d084ffaad 100644
> > --- a/libc/sysdeps/linux/common/time.c
> > +++ b/libc/sysdeps/linux/common/time.c
> > @@ -9,7 +9,7 @@
> >  #include <sys/syscall.h>
> >  #include <time.h>
> >
> > -#ifdef __NR_time
> > +#if defined(__NR_time) && !defined(__UCLIBC_USE_TIME64__)
> >  _syscall_noerr1(time_t, time, time_t *, t)
> >  #else
> >  # include <sys/time.h>
> > diff --git a/libc/sysdeps/linux/common/timerfd.c
> b/libc/sysdeps/linux/common/timerfd.c
> > index 0f19b44ed..04db6ed00 100644
> > --- a/libc/sysdeps/linux/common/timerfd.c
> > +++ b/libc/sysdeps/linux/common/timerfd.c
> > @@ -16,12 +16,33 @@
> >  _syscall2(int, timerfd_create, int, clockid, int, flags)
> >  #endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct its64_struct {
> > +    __S64_TYPE interval_tv_sec;
> > +    __S64_TYPE interval_tv_nsec;
> > +    __S64_TYPE value_tv_sec;
> > +    __S64_TYPE value_tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  /*
> >   * timerfd_settime()
> >   */
> >  #if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64)
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64)
> > -_syscall4_64(int, timerfd_settime, int, ufd, int, flags, const struct
> itimerspec *, utmr, struct itimerspec *, otmr)
> > +int timerfd_settime(int ufd, int flags, const struct itimerspec *utmr,
> struct itimerspec *otmr)
> > +{
> > +    struct its64_struct __its64 = {
> > +        .interval_tv_sec = utmr->it_interval.tv_sec,
> > +        .interval_tv_nsec = utmr->it_interval.tv_nsec,
> > +        .value_tv_sec = utmr->it_value.tv_sec,
> > +        .value_tv_nsec = utmr->it_value.tv_nsec,
> > +    };
> > +
> > +    return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, &__its64,
> otmr);
> > +}
> >  #else
> >  _syscall4(int, timerfd_settime, int, ufd, int, flags, const struct
> itimerspec *, utmr, struct itimerspec *, otmr)
> >  #endif
> > diff --git a/libc/sysdeps/linux/common/utimensat.c
> b/libc/sysdeps/linux/common/utimensat.c
> > index 6a78ebb4f..0c87b5c45 100644
> > --- a/libc/sysdeps/linux/common/utimensat.c
> > +++ b/libc/sysdeps/linux/common/utimensat.c
> > @@ -9,9 +9,30 @@
> >  #include <sys/syscall.h>
> >  #include <sys/stat.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct uts64_struct {
> > +    __S64_TYPE tv_sec1;
> > +    __S64_TYPE tv_nsec1;
> > +    __S64_TYPE tv_sec2;
> > +    __S64_TYPE tv_nsec2;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__NR_utimensat) || defined(__NR_utimensat_time64)
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64)
> > -_syscall4_time64(int, utimensat, int, fd, const char *, path, const
> struct timespec *, times, int, flags)
> > +int utimensat(int fd, const char *path, const struct timespec times[2],
> int flags)
> > +{
> > +    struct uts64_struct __uts64 = {
> > +        .tv_sec1 = times ? times[0].tv_sec : 0,
> > +        .tv_nsec1 = times ? times[0].tv_nsec : 0,
> > +        .tv_sec2 = times ? times[1].tv_sec : 0,
> > +        .tv_nsec2 = times ? times[1].tv_nsec : 0
> > +    };
> > +
> > +    return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ?
> &__uts64 : 0, flags);
> > +}
> >  #else
> >  _syscall4(int, utimensat, int, fd, const char *, path, const struct
> timespec *, times, int, flags)
> >  #endif
> > diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> > index ce62b2ba2..0e76120ab 100644
> > --- a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> > +++ b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
> > @@ -5,6 +5,16 @@
> >   * struct kernel_stat should look like...  It turns out each arch has a
> >   * different opinion on the subject... */
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +#include <bits/types.h>
> > +
> > +struct ts32_struct {
> > +       __S32_TYPE tv_sec;
> > +       __S32_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if __WORDSIZE == 64
> >  #define kernel_stat kernel_stat64
> >  #else
> > @@ -19,9 +29,15 @@ struct kernel_stat {
> >         __kernel_off_t  st_size;
> >         unsigned long   st_blksize;
> >         unsigned long   st_blocks;
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +       struct ts32_struct __st_atim32;
> > +       struct ts32_struct __st_mtim32;
> > +       struct ts32_struct __st_ctim32;
> > +#else
> >         struct timespec st_atim;
> >         struct timespec st_mtim;
> >         struct timespec st_ctim;
> > +#endif
> >         unsigned long   __unused4;
> >         unsigned long   __unused5;
> >  };
> > @@ -39,9 +55,15 @@ struct kernel_stat64 {
> >         long long st_size;              /* Size of file, in bytes.  */
> >         long st_blksize;                /* Optimal block size for I/O.
> */
> >         long long st_blocks;            /* Number 512-byte blocks
> allocated. */
> > -       struct timespec st_atim;        /* Time of last access.  */
> > -       struct timespec st_mtim;        /* Time of last modification.  */
> > -       struct timespec st_ctim;        /* Time of last status change.
> */
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +       struct ts32_struct __st_atim32;
> > +       struct ts32_struct __st_mtim32;
> > +       struct ts32_struct __st_ctim32;
> > +#else
> > +       struct timespec st_atim;
> > +       struct timespec st_mtim;
> > +       struct timespec st_ctim;
> > +#endif
> >         unsigned long int __uclibc_unused4;
> >         unsigned long int __uclibc_unused5;
> >  };
> > diff --git a/libc/sysdeps/linux/powerpc/bits/sem.h
> b/libc/sysdeps/linux/powerpc/bits/sem.h
> > index a9d895374..8d338eac0 100644
> > --- a/libc/sysdeps/linux/powerpc/bits/sem.h
> > +++ b/libc/sysdeps/linux/powerpc/bits/sem.h
> > @@ -35,6 +35,7 @@
> >  #define SETALL         17              /* set all semval's */
> >
> >
> > +
> >  /* Data structure describing a set of semaphores.  */
> >  struct semid_ds
> >  {
> > @@ -42,16 +43,31 @@ struct semid_ds
> >  #if __WORDSIZE == 32
> >    unsigned int __uclibc_unused1;
> >  #endif
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +  unsigned long int __sem_otime_internal_1; /* last semop() time */
> > +  unsigned long int __sem_otime_internal_2;
> > +#else
> >    __time_t sem_otime;                  /* last semop() time */
> > +#endif
> >  #if __WORDSIZE == 32
> >    unsigned int __uclibc_unused2;
> >  #endif
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +  unsigned long int __sem_ctime_internal_1; /* last time changed by
> semctl() */
> > +  unsigned long int __sem_ctime_internal_2;
> > +#else
> >    __time_t sem_ctime;                  /* last time changed by semctl()
> */
> > +#endif
> >    unsigned long int sem_nsems;         /* number of semaphores in set */
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +  __time_t sem_otime;
> > +  __time_t sem_ctime;
> > +#endif
> >    unsigned long __uclibc_unused3;
> >    unsigned long __uclibc_unused4;
> >  };
> >
> > +
> >  /* The user should define a union like the following to use it for
> arguments
> >     for `semctl'.
> >
> > diff --git a/libpthread/nptl/pthread_mutex_timedlock.c
> b/libpthread/nptl/pthread_mutex_timedlock.c
> > index 25f9ec3b2..d55495683 100644
> > --- a/libpthread/nptl/pthread_mutex_timedlock.c
> > +++ b/libpthread/nptl/pthread_mutex_timedlock.c
> > @@ -23,6 +23,15 @@
> >  #include <lowlevellock.h>
> >  #include <not-cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  /* We need to build this function with optimization to avoid
> >   * lll_timedlock erroring out with
> >   * error: can't find a register in class ‘GENERAL_REGS’ while reloading
> ‘asm’
> > @@ -265,10 +274,14 @@ pthread_mutex_timedlock (
> >             INTERNAL_SYSCALL_DECL (__err);
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> > +           struct ts64_struct __ts64 = {
> > +               .tv_sec = abstime ? abstime->tv_sec : 0,
> > +               .tv_nsec = abstime ? abstime->tv_nsec : 0
> > +           };
> >             int e = INTERNAL_SYSCALL (futex_time64, __err, 4,
> &mutex->__data.__lock,
> >                                       __lll_private_flag (FUTEX_LOCK_PI,
> >                                                           private), 1,
> > -                                     abstime);
> > +                                     &__ts64);
> >  #else
> >             int e = INTERNAL_SYSCALL (futex, __err, 4,
> &mutex->__data.__lock,
> >                                       __lll_private_flag (FUTEX_LOCK_PI,
> > @@ -454,7 +467,7 @@ pthread_mutex_timedlock (
> >                       }
> >
> >                     struct timeval tv;
> > -                   struct timespec rt;
> > +                   struct timespec rt, *rtp;
> >
> >                     /* Get the current time.  */
> >                     (void) gettimeofday (&tv, NULL);
> > @@ -475,8 +488,9 @@ pthread_mutex_timedlock (
>
> Starting from this hunk...
>
> >                         goto failpp;
> >                       }
> >
> > +                   rtp = &rt;
> >                     lll_futex_timed_wait (&mutex->__data.__lock,
> > -                                         ceilval | 2, &rt,
> > +                                         ceilval | 2, rtp,
> >                                           PTHREAD_MUTEX_PSHARED (mutex));
> >                   }
> >               }
> > diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> > index 49aab0293..1ea2a888a 100644
> > --- a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> > +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
> > @@ -95,7 +95,7 @@ __pthread_cond_timedwait (
> >
> >    while (1)
> >      {
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        {
> >  #ifdef __NR_clock_gettime
> >         INTERNAL_SYSCALL_DECL (err);
> > @@ -164,8 +164,9 @@ __pthread_cond_timedwait (
> >        cbuffer.oldtype = __pthread_enable_asynccancel ();
> >
> >        /* Wait until woken by signal or broadcast.  */
> > +      rtp = &rt;
> >        err = lll_futex_timed_wait (&cond->__data.__futex,
> > -                                 futex_val, &rt, pshared);
> > +                                 futex_val, rtp, pshared);
> >
> >        /* Disable asynchronous cancellation.  */
> >        __pthread_disable_asynccancel (cbuffer.oldtype);
> > diff --git
> a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> > index 596f5df51..379e92b43 100644
> > --- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> > +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
> > @@ -81,7 +81,7 @@ pthread_rwlock_timedrdlock (
> >        (void) gettimeofday (&tv, NULL);
> >
> >        /* Convert the absolute timeout value to a relative timeout.  */
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
> >        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
> >        if (rt.tv_nsec < 0)
> > @@ -112,8 +112,9 @@ pthread_rwlock_timedrdlock (
> >        lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
> >
> >        /* Wait for the writer to finish.  */
> > +      rtp = &rt;
> >        err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
> > -                                 waitval, &rt, rwlock->__data.__shared);
> > +                                 waitval, rtp, rwlock->__data.__shared);
> >        /* Get the lock.  */
> >        lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
> > diff --git
> a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> > index 0b04b357a..3ce9f9b13 100644
> > --- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> > +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
> > @@ -72,7 +72,7 @@ pthread_rwlock_timedwrlock (
> >        (void) gettimeofday (&tv, NULL);
> >
> >        /* Convert the absolute timeout value to a relative timeout.  */
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
> >        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
> >        if (rt.tv_nsec < 0)
> > @@ -102,8 +102,9 @@ pthread_rwlock_timedwrlock (
> >        lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
> >
> >        /* Wait for the writer or reader(s) to finish.  */
> > +      rtp = &rt;
> >        err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup,
> > -                                 waitval, &rt, rwlock->__data.__shared);
> > +                                 waitval, rtp, rwlock->__data.__shared);
> >
> >        /* Get the lock.  */
> >        lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> > index 4294a20b0..5f7301976 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
> > @@ -63,7 +63,7 @@ __lll_timedlock_wait (int *futex, const struct
> timespec *abstime, int private)
> >        (void) gettimeofday (&tv, NULL);
> >
> >        /* Compute relative timeout.  */
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        rt.tv_sec = abstime->tv_sec - tv.tv_sec;
> >        rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
> >        if (rt.tv_nsec < 0)
> > @@ -76,7 +76,8 @@ __lll_timedlock_wait (int *futex, const struct
> timespec *abstime, int private)
> >         return ETIMEDOUT;
> >
> >        /* Wait.  */
> > -      lll_futex_timed_wait (futex, 2, &rt, private);
> > +      rtp = &rt;
> > +      lll_futex_timed_wait (futex, 2, rtp, private);
> >      }
> >
> >    return 0;
> > @@ -95,7 +96,7 @@ __lll_timedwait_tid (int *tidp, const struct timespec
> *abstime)
> >    while ((tid = *tidp) != 0)
> >      {
> >        struct timeval tv;
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >
> >        /* Get the current time.  */
> >        (void) __gettimeofday (&tv, NULL);
> > @@ -115,7 +116,8 @@ __lll_timedwait_tid (int *tidp, const struct
> timespec *abstime)
> >
> >        /* Wait until thread terminates.  The kernel so far does not use
> >          the private futex operations for this.  */
> > -      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) ==
> -ETIMEDOUT)
> > +      rtp = &rt;
> > +      if (lll_futex_timed_wait (tidp, tid, rtp, LLL_SHARED) ==
> -ETIMEDOUT)
> >         return ETIMEDOUT;
> >      }
> >
>
> ...and up to here: why are all these changes adding an intermediate
> pointer needed?
>
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> > index e72fe5234..4209a21d3 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
> > @@ -71,18 +71,49 @@
> >  # endif
> >  #endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> > +
> >  #define lll_futex_wait(futexp, val, private) \
> > -  lll_futex_timed_wait(futexp, val, NULL, private)
> > +  ({
>      \
> > +    INTERNAL_SYSCALL_DECL (__err);
>      \
> > +    long int __ret;
>       \
> > +    __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),
>               \
> > +                             __lll_private_flag (FUTEX_WAIT, private),
>      \
> > +                             (val), NULL);                           \
> > +    __ret;
>      \
> > +  })
> > +
> > +#else
> > +
> > +#define lll_futex_wait(futexp, val, private) \
> > +  ({
>      \
> > +    INTERNAL_SYSCALL_DECL (__err);
>      \
> > +    long int __ret;
>       \
> > +    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),
>      \
> > +                             __lll_private_flag (FUTEX_WAIT, private),
>      \
> > +                             (val), NULL);                           \
> > +    __ret;
>      \
> > +  })
> > +
> > +#endif
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
> >
> > +struct __ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#define ptr_timespec_to_ts64(ts) \
> > +  (&(struct __ts64_struct) {.tv_sec = ts->tv_sec, .tv_nsec =
> ts->tv_nsec})
> > +
> >  #define lll_futex_timed_wait(futexp, val, timespec, private) \
> >    ({
>      \
> >      INTERNAL_SYSCALL_DECL (__err);
>      \
> >      long int __ret;
>       \
> >      __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),
>               \
> >                               __lll_private_flag (FUTEX_WAIT, private),
>      \
> > -                             (val), (timespec));
>      \
> > +                             (val), (ptr_timespec_to_ts64(timespec)));
>                      \
> >      __ret;
>      \
> >    })
> >
> > diff --git
> a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> > index 7b4e84343..5781359fb 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
> > @@ -73,7 +73,7 @@ __lll_robust_timedlock_wait (int *futex, const struct
> timespec *abstime,
> >    do
> >      {
> >        struct timeval tv;
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >
> >        /* Get the current time.  */
> >        (void) __gettimeofday (&tv, NULL);
> > @@ -99,8 +99,8 @@ __lll_robust_timedlock_wait (int *futex, const struct
> timespec *abstime,
> >        if (oldval != newval
> >           && atomic_compare_and_exchange_bool_acq (futex, newval,
> oldval))
> >         continue;
> > -
> > -      lll_futex_timed_wait (futex, newval, &rt, private);
> > +      rtp = &rt;
> > +      lll_futex_timed_wait (futex, newval, rtp, private);
> >
> >      try:
> >        ;
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> > index 8c3ef47c5..05ba5bc13 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
> > @@ -51,7 +51,7 @@ sem_timedwait (sem_t *sem, const struct timespec
> *abstime)
> >    while (1)
> >      {
> >        struct timeval tv;
> > -      struct timespec rt;
> > +      struct timespec rt, *rtp;
> >        int sec, nsec;
> >
> >        /* Get the current time.  */
> > @@ -79,10 +79,12 @@ sem_timedwait (sem_t *sem, const struct timespec
> *abstime)
> >        rt.tv_sec = sec;
> >        rt.tv_nsec = nsec;
> >
> > +      rtp = &rt;
> > +
> >        /* Enable asynchronous cancellation.  Required by the standard.
> */
> >        int oldtype = __pthread_enable_asynccancel ();
> >
> > -      err = lll_futex_timed_wait (&isem->value, 0, &rt,
> > +      err = lll_futex_timed_wait (&isem->value, 0, rtp,
> >                                   isem->private ^ FUTEX_PRIVATE_FLAG);
> >
> >        /* Disable asynchronous cancellation.  */
> > diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> > index 80d242f21..d7c2aa804 100644
> > --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> > +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
> > @@ -38,6 +38,17 @@ static int compat_timer_settime (timer_t timerid, int
> flags,
> >  #  define timer_settime timer_settime_alias
> >  # endif
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct its64_struct {
> > +    __S64_TYPE interval_tv_sec;
> > +    __S64_TYPE interval_tv_nsec;
> > +    __S64_TYPE value_tv_sec;
> > +    __S64_TYPE value_tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >
> >  int
> >  timer_settime (
> > @@ -55,8 +66,14 @@ timer_settime (
> >
> >        /* Delete the kernel timer object.  */
> >  # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
> > +      struct its64_struct __its64 = {
> > +            .interval_tv_sec = value->it_interval.tv_sec,
> > +            .interval_tv_nsec = value->it_interval.tv_nsec,
> > +            .value_tv_sec = value->it_value.tv_sec,
> > +            .value_tv_nsec = value->it_value.tv_nsec,
> > +      };
> >        int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
> > -                               value, ovalue);
> > +                               value ? &__its64 : 0, ovalue);
> >  # else
> >        int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
> >                                 value, ovalue);
> > diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c
> > index b66b60231..eff40d68f 100644
> > --- a/librt/clock_gettime.c
> > +++ b/librt/clock_gettime.c
> > @@ -22,10 +22,26 @@
> >  #include <sys/time.h>
> >  #include "kernel-posix-cpu-timers.h"
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +  __S64_TYPE tv_sec;
> > +  __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
> >  #define SYSCALL_GETTIME \
> > -  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
> > -  break
> > +  { \
> > +  struct ts64_struct __ts64; \
> > +  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, &__ts64); \
> > +  if (tp) { \
> > +    tp->tv_sec = __ts64.tv_sec; \
> > +    tp->tv_nsec = __ts64.tv_nsec; \
> > +  } \
> > +  break; \
> > +  }
> >  #else
> >  #define SYSCALL_GETTIME \
> >    retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
> > diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c
> > index eaae75720..786f7eede 100644
> > --- a/librt/clock_nanosleep.c
> > +++ b/librt/clock_nanosleep.c
> > @@ -21,6 +21,14 @@
> >
> >  #include "kernel-posix-cpu-timers.h"
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +    __S64_TYPE tv_sec;
> > +    __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> >
> >  /* We can simply use the syscall.  The CPU clocks are not supported
> >     with this function.  */
> > @@ -36,18 +44,27 @@ clock_nanosleep (clockid_t clock_id, int flags,
> const struct timespec *req,
> >    if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
> >      clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
> >
> > -  if (SINGLE_THREAD_P)
> > +  if (SINGLE_THREAD_P) {
> >  #if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_clock_nanosleep_time64)
> > -    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req, rem);
> > +    struct ts64_struct __ts64 = {
> > +      .tv_sec = req ? req->tv_sec : 0,
> > +      .tv_nsec = req ? req->tv_nsec : 0
> > +    };
> > +    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req ? &__ts64 : 0, rem);
> >  #else
> >      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
> req, rem);
> >  #endif
> > +  }
> >    else
> >      {
> >  #ifdef __NEW_THREADS
> >        int oldstate = LIBC_CANCEL_ASYNC ();
> >  #if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_clock_nanosleep_time64)
> > -      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req, rem);
> > +      struct ts64_struct __ts64_2 = {
> > +        .tv_sec = req ? req->tv_sec : 0,
> > +        .tv_nsec = req ? req->tv_nsec : 0
> > +      };
> > +      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id,
> flags, req ? &__ts64_2 : 0, rem);
> >  #else
> >        r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
> req,
> >                             rem);
> > diff --git a/librt/mq_timedreceive.c b/librt/mq_timedreceive.c
> > index db1ae1aa8..818f54faa 100644
> > --- a/librt/mq_timedreceive.c
> > +++ b/librt/mq_timedreceive.c
> > @@ -8,13 +8,29 @@
> >  #include <unistd.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) &&
> defined(__NR_mq_timedreceive_time64)
> > -#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64
> > +int _NC(mq_timedreceive)(mqd_t mqdes, char *restrict msg_ptr, size_t
> msg_len, unsigned int *restrict msq_prio, const struct timespec *restrict
> abs_timeout)
> > +{
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
> > +               .tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
> > +       };
> > +
> > +       return INLINE_SYSCALL(mq_timedreceive_time64, 5, mqdes, msg_ptr,
> msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
> > +}
> >  #else
> >  #define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive
> > -#endif
> > -
> >  _syscall5(ssize_t, __NC(mq_timedreceive), mqd_t, mqdes, char
> *__restrict, msg_ptr, size_t, msg_len, unsigned int *__restrict, msq_prio,
> const struct timespec *__restrict, abs_timeout)
> > +#endif
> >
> >  CANCELLABLE_SYSCALL(ssize_t, mq_timedreceive, (mqd_t mqdes, char
> *__restrict msg_ptr, size_t msq_len, unsigned int *__restrict msq_prio,
> const struct timespec *__restrict abs_timeout),
> >                     (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
> > diff --git a/librt/mq_timedsend.c b/librt/mq_timedsend.c
> > index 6afaf5157..e8deea9cb 100644
> > --- a/librt/mq_timedsend.c
> > +++ b/librt/mq_timedsend.c
> > @@ -8,13 +8,31 @@
> >  #include <unistd.h>
> >  #include <cancel.h>
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct ts64_struct {
> > +       __S64_TYPE tv_sec;
> > +       __S64_TYPE tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64)
> >  #define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64
> > +int _NC(mq_timedsend)(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
> unsigned int msq_prio, const struct timespec *abs_timeout)
> > +{
> > +       struct ts64_struct __ts64 = {
> > +               .tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
> > +               .tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
> > +       };
> > +
> > +       return INLINE_SYSCALL(mq_timedsend_time64, 5, mqdes, msg_ptr,
> msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
> > +}
> >  #else
> >  #define __NR___mq_timedsend_nocancel __NR_mq_timedsend
> > +_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr,
> size_t, msg_len, unsigned int, msq_prio, const struct timespec *,
> abs_timeout)
> >  #endif
> >
> > -_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr,
> size_t, msg_len, unsigned int, msq_prio, const struct timespec *,
> abs_timeout)
> >  CANCELLABLE_SYSCALL(int, mq_timedsend, (mqd_t mqdes, const char
> *msg_ptr, size_t msq_len, unsigned int msq_prio, const struct timespec
> *abs_timeout),
> >                     (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
> >  lt_libc_hidden(mq_timedsend)
> > diff --git a/librt/timer_settime.c b/librt/timer_settime.c
> > index 022880297..31202b07a 100644
> > --- a/librt/timer_settime.c
> > +++ b/librt/timer_settime.c
> > @@ -9,13 +9,36 @@
> >
> >  #include "kernel-posix-timers.h"
> >
> > +#if defined(__UCLIBC_USE_TIME64__)
> > +
> > +struct its64_struct {
> > +    __S64_TYPE interval_tv_sec;
> > +    __S64_TYPE interval_tv_nsec;
> > +    __S64_TYPE value_tv_sec;
> > +    __S64_TYPE value_tv_nsec;
> > +};
> > +
> > +#endif
> > +
> >  #if defined(__NR_timer_settime) || defined(__NR_timer_settime64)
> >
> >  #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
> > -#define __NR___syscall_timer_settime __NR_timer_settime64
> > +int timer_settime(timer_t timerid, int flags, const struct itimerspec
> *value, struct itimerspec *ovalue)
> > +{
> > +       struct timer *kt = (struct timer *)timerid;
> > +
> > +    struct its64_struct __its64 = {
> > +        .interval_tv_sec = value->it_interval.tv_sec,
> > +        .interval_tv_nsec = value->it_interval.tv_nsec,
> > +        .value_tv_sec = value->it_value.tv_sec,
> > +        .value_tv_nsec = value->it_value.tv_nsec,
> > +    };
> > +
> > +       return INLINE_SYSCALL(timer_settime64, 4, kt->ktimerid, flags,
> value ? &__its64: 0, ovalue);
> > +}
> >  #else
> > +
> >  #define __NR___syscall_timer_settime __NR_timer_settime
> > -#endif
> >
> >  static __inline__ _syscall4(int, __syscall_timer_settime,
> kernel_timer_t, ktimerid,
> >                         int, flags, const void *, value, void *, ovalue);
> > @@ -31,3 +54,4 @@ int timer_settime(timer_t timerid, int flags, const
> struct itimerspec *value,
> >  }
> >
> >  #endif
> > +#endif
> > --
> > 2.43.2
> >
> > _______________________________________________
> > devel mailing list -- devel@uclibc-ng.org
> > To unsubscribe send an email to devel-leave@uclibc-ng.org
>
>
>
> --
> Thanks.
> -- Max
>
Max Filippov Feb. 24, 2024, 7:03 p.m. UTC | #4
On Sat, Feb 24, 2024 at 10:29 AM Dmitriy Chestnykh
<dm.chestnykh@gmail.com> wrote:
>
> Patch is splitted, intermediate pointers removed.

Something isn't right with the submission, I can see multiple copies
of the patch 1/2, but no 2/2.
Also please add version tag to the subject line, i.e. 'PATCH v3' for
the next submission round.
diff mbox series

Patch

diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 9351dffc8..f11a63b79 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -1026,7 +1026,7 @@  config UCLIBC_FALLBACK_TO_ETC_LOCALTIME
 
 config UCLIBC_USE_TIME64
 	bool "Use *time64 syscalls instead of 32bit ones (if possible)"
-	depends on TARGET_arm || TARGET_xtensa
+	depends on TARGET_arm || TARGET_powerpc || TARGET_xtensa
 	# TODO: add support for other architectures
 	default n
 
diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c
index eb0983698..7ec439887 100644
--- a/libc/inet/socketcalls.c
+++ b/libc/inet/socketcalls.c
@@ -268,12 +268,26 @@  lt_libc_hidden(recvmsg)
 #endif
 
 #ifdef L_recvmmsg
+
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+
+#endif
+
 #ifdef __ASSUME_RECVMMSG_SYSCALL
 static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen,
 			      int flags, struct timespec *tmo)
 {
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64)
-	return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo);
+	struct ts64_struct __ts64 = {
+		.tv_sec = tmo ? tmo->tv_sec : 0,
+		.tv_nsec = tmo ? tmo->tv_nsec : 0
+	};
+	return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo ? &__ts64 : 0);
 # elif defined(__NR_recvmmsg)
 	return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen, flags, tmo);
 # elif __NR_socketcall
diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c
index cd541761c..d0bd0ba28 100644
--- a/libc/misc/sysvipc/sem.c
+++ b/libc/misc/sysvipc/sem.c
@@ -96,7 +96,21 @@  int semop (int semid, struct sembuf *sops, size_t nsops)
 #ifdef L_semtimedop
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_semtimedop_time64)
-_syscall4_time64(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout)
+
+struct ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+
+int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout) {
+    struct ts64_struct __ts64 = {
+        .tv_sec = timeout ? timeout->tv_sec : 0,
+        .tv_nsec = timeout ? timeout->tv_nsec : 0
+    };
+
+    return INLINE_SYSCALL(semtimedop_time64, 4, semid, sops, nsops, timeout ? &__ts64 : 0);
+}
+
 #elif defined(__NR_semtimedop)
 _syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout)
 
diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c
index 3557a039e..b237534cd 100644
--- a/libc/signal/sigwait.c
+++ b/libc/signal/sigwait.c
@@ -24,7 +24,8 @@ 
 #include <signal.h>
 #include <cancel.h>
 
-#if defined __NR_rt_sigtimedwait && defined __UCLIBC_HAS_REALTIME__
+#if (defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64))) && \
+    defined(__UCLIBC_HAS_REALTIME__)
 
 #include <string.h>
 
diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
index bd82ca6d5..cd25fe177 100644
--- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c
+++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c
@@ -9,7 +9,7 @@ 
 
 #include <sys/syscall.h>
 
-#ifdef __NR_rt_sigtimedwait
+#if defined(__NR_rt_sigtimedwait) || (defined(__NR_rt_sigtimedwait_time64) && defined(__UCLIBC_USE_TIME64__))
 # include <signal.h>
 # include <cancel.h>
 # ifdef __UCLIBC_HAS_THREADS_NATIVE__
@@ -21,6 +21,15 @@ 
 #  include <string.h>
 # endif
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+	__S64_TYPE tv_sec;
+	__S64_TYPE tv_nsec;
+};
+
+#endif
+
 int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
 		       const struct timespec *timeout)
 {
@@ -53,8 +62,12 @@  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
 	   real size of the user-level sigset_t.  */
 	/* on uClibc we use the kernel sigset_t size */
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)
+	struct ts64_struct __ts64 = {
+		.tv_sec = timeout ? timeout->tv_sec : 0,
+		.tv_nsec = timeout ? timeout->tv_nsec : 0
+	};
 	result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
-				    timeout, __SYSCALL_SIGSET_T_SIZE);
+				    timeout ? &__ts64 : 0, __SYSCALL_SIGSET_T_SIZE);
 # else
 	result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
 				    timeout, __SYSCALL_SIGSET_T_SIZE);
@@ -71,8 +84,12 @@  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
 # else
 	/* on uClibc we use the kernel sigset_t size */
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)
+	struct ts64_struct __ts64 = {
+		.tv_sec = timeout ? timeout->tv_sec : 0,
+		.tv_nsec = timeout ? timeout->tv_nsec : 0
+	};
 	return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
-			      timeout, __SYSCALL_SIGSET_T_SIZE);
+			      timeout ? &__ts64 : 0, __SYSCALL_SIGSET_T_SIZE);
 # else
 	return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
 			      timeout, __SYSCALL_SIGSET_T_SIZE);
diff --git a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
index d2d176a64..7830b2e2c 100644
--- a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
+++ b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c
@@ -9,7 +9,7 @@ 
 
 #include <sys/syscall.h>
 
-#ifdef __NR_rt_sigtimedwait
+#if defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64))
 # define __need_NULL
 # include <stddef.h>
 # include <signal.h>
diff --git a/libc/sysdeps/linux/common/alarm.c b/libc/sysdeps/linux/common/alarm.c
index 4e6e2215b..861f6ad8e 100644
--- a/libc/sysdeps/linux/common/alarm.c
+++ b/libc/sysdeps/linux/common/alarm.c
@@ -9,7 +9,7 @@ 
 #include <sys/syscall.h>
 #include <unistd.h>
 
-#ifdef __NR_alarm && !defined(__UCLIBC_USE_TIME64__)
+#if defined(__NR_alarm) && !defined(__UCLIBC_USE_TIME64__)
 _syscall1(unsigned int, alarm, unsigned int, seconds)
 #else
 # include <sys/time.h>
diff --git a/libc/sysdeps/linux/common/clock_getres.c b/libc/sysdeps/linux/common/clock_getres.c
index d4b989958..c72b0a21c 100644
--- a/libc/sysdeps/linux/common/clock_getres.c
+++ b/libc/sysdeps/linux/common/clock_getres.c
@@ -10,9 +10,27 @@ 
 #include <sys/syscall.h>
 #include <time.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+	__S64_TYPE tv_sec;
+	__S64_TYPE tv_nsec;
+};
+
+#endif
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64)
-_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
+int clock_getres(clockid_t clock_id, struct timespec *res)
+{
+	struct ts64_struct __ts64;
+	int __ret = INLINE_SYSCALL(clock_getres_time64, 2, clock_id, &__ts64);
+	if (__ret == 0 && res) {
+		res->tv_sec = __ts64.tv_sec;
+		res->tv_nsec = __ts64.tv_nsec;
+	};
+
+	return __ret;
+}
 #elif defined(__NR_clock_getres)
 _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
 #else
diff --git a/libc/sysdeps/linux/common/clock_gettime.c b/libc/sysdeps/linux/common/clock_gettime.c
index a595bd691..dbb767c94 100644
--- a/libc/sysdeps/linux/common/clock_gettime.c
+++ b/libc/sysdeps/linux/common/clock_gettime.c
@@ -11,8 +11,27 @@ 
 #include <sys/syscall.h>
 #include <time.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+	__S64_TYPE tv_sec;
+	__S64_TYPE tv_nsec;
+};
+
+#endif
+
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
-_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
+int clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+	struct ts64_struct __ts64;
+	int __ret = INLINE_SYSCALL(clock_gettime64, 2, clock_id, &__ts64);
+	if (tp) {
+		tp->tv_sec = __ts64.tv_sec;
+		tp->tv_nsec = __ts64.tv_nsec;
+	}
+
+	return __ret;
+}
 #elif defined(__NR_clock_gettime)
 _syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
 #else
diff --git a/libc/sysdeps/linux/common/clock_settime.c b/libc/sysdeps/linux/common/clock_settime.c
index 89550af5a..54bfa20e8 100644
--- a/libc/sysdeps/linux/common/clock_settime.c
+++ b/libc/sysdeps/linux/common/clock_settime.c
@@ -12,7 +12,22 @@ 
 
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64)
-_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp)
+
+struct ts64_struct {
+	__S64_TYPE tv_sec;
+	__S64_TYPE tv_nsec;
+};
+
+int clock_settime(clockid_t clock_id, const struct timespec *tp)
+{
+	struct ts64_struct __ts64 = {
+		.tv_sec = tp->tv_sec,
+		.tv_nsec = tp->tv_nsec
+	};
+
+	return INLINE_SYSCALL(clock_settime64, 2, clock_id, &__ts64);
+}
+
 #elif defined(__NR_clock_settime)
 _syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp)
 #else
diff --git a/libc/sysdeps/linux/common/ppoll.c b/libc/sysdeps/linux/common/ppoll.c
index cb36149c5..16d836b6f 100644
--- a/libc/sysdeps/linux/common/ppoll.c
+++ b/libc/sysdeps/linux/common/ppoll.c
@@ -26,6 +26,15 @@ 
 #include <sys/poll.h>
 #include <cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+   __S64_TYPE tv_sec;
+   __S64_TYPE tv_nsec;
+};
+
+#endif
+
 static int
 __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
 	    const sigset_t *sigmask)
@@ -38,7 +47,11 @@  __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
 		timeout = &tval;
 	}
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64)
-	return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE);
+   struct ts64_struct __ts64 = {
+      .tv_sec = timeout ? timeout->tv_sec : 0,
+      .tv_nsec = timeout ? timeout->tv_nsec : 0
+   };
+	return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout ? &__ts64 : 0, sigmask, __SYSCALL_SIGSET_T_SIZE);
 #else
 	return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE);
 #endif
diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c
index 23bdab5cf..a189624ec 100644
--- a/libc/sysdeps/linux/common/pselect.c
+++ b/libc/sysdeps/linux/common/pselect.c
@@ -26,6 +26,15 @@ 
 #include <signal.h>
 #include <cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+
+#endif
+
 static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
 			 fd_set *exceptfds, const struct timespec *timeout,
 			 const sigset_t *sigmask)
@@ -57,7 +66,11 @@  static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
 		sigmask = (void *)&data;
 	}
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
-	return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask);
+	struct ts64_struct __ts64 = {
+		.tv_sec = timeout ? timeout->tv_sec : 0,
+		.tv_nsec = timeout ? timeout->tv_nsec : 0
+	};
+	return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout ? &__ts64 : 0, sigmask);
 #else
 	return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask);
 #endif
diff --git a/libc/sysdeps/linux/common/select.c b/libc/sysdeps/linux/common/select.c
index 3132a109c..a55a61df1 100644
--- a/libc/sysdeps/linux/common/select.c
+++ b/libc/sysdeps/linux/common/select.c
@@ -15,17 +15,22 @@ 
 # define __NR_select __NR__newselect
 #endif
 
-#if !defined __NR_select && defined __NR_pselect6
+#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
 # include <stdint.h>
 # define USEC_PER_SEC 1000000L
 #endif
 
+#if defined(__UCLIBC_USE_TIME64__)
+struct ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+#endif
+
 int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 		 struct timeval *timeout)
 {
-#ifdef __NR_select
-	return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout);
-#elif defined __NR_pselect6
+#if defined(__NR_pselect6) || defined(__NR_pselect6_time64)
 	struct timespec _ts, *ts = 0;
 	if (timeout) {
 		uint32_t usec;
@@ -47,8 +52,18 @@  int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 
 		ts = &_ts;
 	}
+#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64)
+	struct ts64_struct __ts64 = {
+		.tv_sec = ts ? ts->tv_sec : 0,
+		.tv_nsec = ts ? ts->tv_nsec : 0
+	};
+	return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds, exceptfds, timeout ? &__ts64 : 0, 0);
+#else
 	return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds, exceptfds, ts, 0);
 #endif
+#elif defined(__NR_select)
+	return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout);
+#endif
 }
 /* we should guard it, but we need it in other files, so let it fail
  * if we miss any of the syscalls */
diff --git a/libc/sysdeps/linux/common/time.c b/libc/sysdeps/linux/common/time.c
index 22403f174..d084ffaad 100644
--- a/libc/sysdeps/linux/common/time.c
+++ b/libc/sysdeps/linux/common/time.c
@@ -9,7 +9,7 @@ 
 #include <sys/syscall.h>
 #include <time.h>
 
-#ifdef __NR_time
+#if defined(__NR_time) && !defined(__UCLIBC_USE_TIME64__)
 _syscall_noerr1(time_t, time, time_t *, t)
 #else
 # include <sys/time.h>
diff --git a/libc/sysdeps/linux/common/timerfd.c b/libc/sysdeps/linux/common/timerfd.c
index 0f19b44ed..04db6ed00 100644
--- a/libc/sysdeps/linux/common/timerfd.c
+++ b/libc/sysdeps/linux/common/timerfd.c
@@ -16,12 +16,33 @@ 
 _syscall2(int, timerfd_create, int, clockid, int, flags)
 #endif
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct its64_struct {
+    __S64_TYPE interval_tv_sec;
+    __S64_TYPE interval_tv_nsec;
+    __S64_TYPE value_tv_sec;
+    __S64_TYPE value_tv_nsec;
+};
+
+#endif
+
 /*
  * timerfd_settime()
  */
 #if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64)
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64)
-_syscall4_64(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr)
+int timerfd_settime(int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)
+{
+    struct its64_struct __its64 = {
+        .interval_tv_sec = utmr->it_interval.tv_sec,
+        .interval_tv_nsec = utmr->it_interval.tv_nsec,
+        .value_tv_sec = utmr->it_value.tv_sec,
+        .value_tv_nsec = utmr->it_value.tv_nsec,
+    };
+
+    return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, &__its64, otmr);
+}
 #else
 _syscall4(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr)
 #endif
diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c
index 6a78ebb4f..0c87b5c45 100644
--- a/libc/sysdeps/linux/common/utimensat.c
+++ b/libc/sysdeps/linux/common/utimensat.c
@@ -9,9 +9,30 @@ 
 #include <sys/syscall.h>
 #include <sys/stat.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct uts64_struct {
+    __S64_TYPE tv_sec1;
+    __S64_TYPE tv_nsec1;
+    __S64_TYPE tv_sec2;
+    __S64_TYPE tv_nsec2;
+};
+
+#endif
+
 #if defined(__NR_utimensat) || defined(__NR_utimensat_time64)
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64)
-_syscall4_time64(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
+int utimensat(int fd, const char *path, const struct timespec times[2], int flags)
+{
+    struct uts64_struct __uts64 = {
+        .tv_sec1 = times ? times[0].tv_sec : 0,
+        .tv_nsec1 = times ? times[0].tv_nsec : 0,
+        .tv_sec2 = times ? times[1].tv_sec : 0,
+        .tv_nsec2 = times ? times[1].tv_nsec : 0
+    };
+
+    return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? &__uts64 : 0, flags);
+}
 #else
 _syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
 #endif
diff --git a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
index ce62b2ba2..0e76120ab 100644
--- a/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
+++ b/libc/sysdeps/linux/powerpc/bits/kernel_stat.h
@@ -5,6 +5,16 @@ 
  * struct kernel_stat should look like...  It turns out each arch has a
  * different opinion on the subject... */
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include <bits/types.h>
+
+struct ts32_struct {
+	__S32_TYPE tv_sec;
+	__S32_TYPE tv_nsec;
+};
+
+#endif
+
 #if __WORDSIZE == 64
 #define kernel_stat kernel_stat64
 #else
@@ -19,9 +29,15 @@  struct kernel_stat {
 	__kernel_off_t	st_size;
 	unsigned long  	st_blksize;
 	unsigned long  	st_blocks;
+#if defined(__UCLIBC_USE_TIME64__)
+	struct ts32_struct __st_atim32;
+	struct ts32_struct __st_mtim32;
+	struct ts32_struct __st_ctim32;
+#else
 	struct timespec	st_atim;
 	struct timespec	st_mtim;
 	struct timespec	st_ctim;
+#endif
 	unsigned long  	__unused4;
 	unsigned long  	__unused5;
 };
@@ -39,9 +55,15 @@  struct kernel_stat64 {
 	long long st_size;		/* Size of file, in bytes.  */
 	long st_blksize;		/* Optimal block size for I/O.  */
 	long long st_blocks;		/* Number 512-byte blocks allocated. */
-	struct timespec st_atim;	/* Time of last access.  */
-	struct timespec st_mtim;	/* Time of last modification.  */
-	struct timespec st_ctim;	/* Time of last status change.  */
+#if defined(__UCLIBC_USE_TIME64__)
+	struct ts32_struct __st_atim32;
+	struct ts32_struct __st_mtim32;
+	struct ts32_struct __st_ctim32;
+#else
+	struct timespec	st_atim;
+	struct timespec	st_mtim;
+	struct timespec	st_ctim;
+#endif
 	unsigned long int __uclibc_unused4;
 	unsigned long int __uclibc_unused5;
 };
diff --git a/libc/sysdeps/linux/powerpc/bits/sem.h b/libc/sysdeps/linux/powerpc/bits/sem.h
index a9d895374..8d338eac0 100644
--- a/libc/sysdeps/linux/powerpc/bits/sem.h
+++ b/libc/sysdeps/linux/powerpc/bits/sem.h
@@ -35,6 +35,7 @@ 
 #define SETALL         17              /* set all semval's */
 
 
+
 /* Data structure describing a set of semaphores.  */
 struct semid_ds
 {
@@ -42,16 +43,31 @@  struct semid_ds
 #if __WORDSIZE == 32
   unsigned int __uclibc_unused1;
 #endif
+#if defined(__UCLIBC_USE_TIME64__)
+  unsigned long int __sem_otime_internal_1; /* last semop() time */
+  unsigned long int __sem_otime_internal_2;
+#else
   __time_t sem_otime;                  /* last semop() time */
+#endif
 #if __WORDSIZE == 32
   unsigned int __uclibc_unused2;
 #endif
+#if defined(__UCLIBC_USE_TIME64__)
+  unsigned long int __sem_ctime_internal_1; /* last time changed by semctl() */
+  unsigned long int __sem_ctime_internal_2;
+#else
   __time_t sem_ctime;                  /* last time changed by semctl() */
+#endif
   unsigned long int sem_nsems;         /* number of semaphores in set */
+#if defined(__UCLIBC_USE_TIME64__)
+  __time_t sem_otime;
+  __time_t sem_ctime;
+#endif
   unsigned long __uclibc_unused3;
   unsigned long __uclibc_unused4;
 };
 
+
 /* The user should define a union like the following to use it for arguments
    for `semctl'.
 
diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c
index 25f9ec3b2..d55495683 100644
--- a/libpthread/nptl/pthread_mutex_timedlock.c
+++ b/libpthread/nptl/pthread_mutex_timedlock.c
@@ -23,6 +23,15 @@ 
 #include <lowlevellock.h>
 #include <not-cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+
+#endif
+
 /* We need to build this function with optimization to avoid
  * lll_timedlock erroring out with
  * error: can't find a register in class ‘GENERAL_REGS’ while reloading ‘asm’
@@ -265,10 +274,14 @@  pthread_mutex_timedlock (
 	    INTERNAL_SYSCALL_DECL (__err);
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
+	    struct ts64_struct __ts64 = {
+	        .tv_sec = abstime ? abstime->tv_sec : 0,
+	        .tv_nsec = abstime ? abstime->tv_nsec : 0
+	    };
 	    int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock,
 				      __lll_private_flag (FUTEX_LOCK_PI,
 							  private), 1,
-				      abstime);
+				      &__ts64);
 #else
 	    int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
 				      __lll_private_flag (FUTEX_LOCK_PI,
@@ -454,7 +467,7 @@  pthread_mutex_timedlock (
 		      }
 
 		    struct timeval tv;
-		    struct timespec rt;
+		    struct timespec rt, *rtp;
 
 		    /* Get the current time.  */
 		    (void) gettimeofday (&tv, NULL);
@@ -475,8 +488,9 @@  pthread_mutex_timedlock (
 			goto failpp;
 		      }
 
+		    rtp = &rt;
 		    lll_futex_timed_wait (&mutex->__data.__lock,
-					  ceilval | 2, &rt,
+					  ceilval | 2, rtp,
 					  PTHREAD_MUTEX_PSHARED (mutex));
 		  }
 	      }
diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
index 49aab0293..1ea2a888a 100644
--- a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
+++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c
@@ -95,7 +95,7 @@  __pthread_cond_timedwait (
 
   while (1)
     {
-      struct timespec rt;
+      struct timespec rt, *rtp;
       {
 #ifdef __NR_clock_gettime
 	INTERNAL_SYSCALL_DECL (err);
@@ -164,8 +164,9 @@  __pthread_cond_timedwait (
       cbuffer.oldtype = __pthread_enable_asynccancel ();
 
       /* Wait until woken by signal or broadcast.  */
+      rtp = &rt;
       err = lll_futex_timed_wait (&cond->__data.__futex,
-				  futex_val, &rt, pshared);
+				  futex_val, rtp, pshared);
 
       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (cbuffer.oldtype);
diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
index 596f5df51..379e92b43 100644
--- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
+++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c
@@ -81,7 +81,7 @@  pthread_rwlock_timedrdlock (
       (void) gettimeofday (&tv, NULL);
 
       /* Convert the absolute timeout value to a relative timeout.  */
-      struct timespec rt;
+      struct timespec rt, *rtp;
       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
       if (rt.tv_nsec < 0)
@@ -112,8 +112,9 @@  pthread_rwlock_timedrdlock (
       lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
 
       /* Wait for the writer to finish.  */
+      rtp = &rt;
       err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
-				  waitval, &rt, rwlock->__data.__shared);
+				  waitval, rtp, rwlock->__data.__shared);
 
       /* Get the lock.  */
       lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
index 0b04b357a..3ce9f9b13 100644
--- a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
+++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c
@@ -72,7 +72,7 @@  pthread_rwlock_timedwrlock (
       (void) gettimeofday (&tv, NULL);
 
       /* Convert the absolute timeout value to a relative timeout.  */
-      struct timespec rt;
+      struct timespec rt, *rtp;
       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
       if (rt.tv_nsec < 0)
@@ -102,8 +102,9 @@  pthread_rwlock_timedwrlock (
       lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared);
 
       /* Wait for the writer or reader(s) to finish.  */
+      rtp = &rt;
       err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup,
-				  waitval, &rt, rwlock->__data.__shared);
+				  waitval, rtp, rwlock->__data.__shared);
 
       /* Get the lock.  */
       lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
index 4294a20b0..5f7301976 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
@@ -63,7 +63,7 @@  __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
       (void) gettimeofday (&tv, NULL);
 
       /* Compute relative timeout.  */
-      struct timespec rt;
+      struct timespec rt, *rtp;
       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
       if (rt.tv_nsec < 0)
@@ -76,7 +76,8 @@  __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
 	return ETIMEDOUT;
 
       /* Wait.  */
-      lll_futex_timed_wait (futex, 2, &rt, private);
+      rtp = &rt;
+      lll_futex_timed_wait (futex, 2, rtp, private);
     }
 
   return 0;
@@ -95,7 +96,7 @@  __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
   while ((tid = *tidp) != 0)
     {
       struct timeval tv;
-      struct timespec rt;
+      struct timespec rt, *rtp;
 
       /* Get the current time.  */
       (void) __gettimeofday (&tv, NULL);
@@ -115,7 +116,8 @@  __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
 
       /* Wait until thread terminates.  The kernel so far does not use
 	 the private futex operations for this.  */
-      if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
+      rtp = &rt;
+      if (lll_futex_timed_wait (tidp, tid, rtp, LLL_SHARED) == -ETIMEDOUT)
 	return ETIMEDOUT;
     }
 
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
index e72fe5234..4209a21d3 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
@@ -71,18 +71,49 @@ 
 # endif	      
 #endif
 
+#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
+
 #define lll_futex_wait(futexp, val, private) \
-  lll_futex_timed_wait(futexp, val, NULL, private)
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAIT, private),	      \
+			      (val), NULL);			      \
+    __ret;								      \
+  })
+
+#else
+
+#define lll_futex_wait(futexp, val, private) \
+  ({									      \
+    INTERNAL_SYSCALL_DECL (__err);					      \
+    long int __ret;							      \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),		      \
+			      __lll_private_flag (FUTEX_WAIT, private),	      \
+			      (val), NULL);			      \
+    __ret;								      \
+  })
+
+#endif
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64)
 
+struct __ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+
+#define ptr_timespec_to_ts64(ts) \
+  (&(struct __ts64_struct) {.tv_sec = ts->tv_sec, .tv_nsec = ts->tv_nsec})
+
 #define lll_futex_timed_wait(futexp, val, timespec, private) \
   ({									      \
     INTERNAL_SYSCALL_DECL (__err);					      \
     long int __ret;							      \
     __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),		      \
 			      __lll_private_flag (FUTEX_WAIT, private),	      \
-			      (val), (timespec));			      \
+			      (val), (ptr_timespec_to_ts64(timespec)));			      \
     __ret;								      \
   })
 
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
index 7b4e84343..5781359fb 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c
@@ -73,7 +73,7 @@  __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime,
   do
     {
       struct timeval tv;
-      struct timespec rt;
+      struct timespec rt, *rtp;
 
       /* Get the current time.  */
       (void) __gettimeofday (&tv, NULL);
@@ -99,8 +99,8 @@  __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime,
       if (oldval != newval
 	  && atomic_compare_and_exchange_bool_acq (futex, newval, oldval))
 	continue;
-
-      lll_futex_timed_wait (futex, newval, &rt, private);
+      rtp = &rt;
+      lll_futex_timed_wait (futex, newval, rtp, private);
 
     try:
       ;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index 8c3ef47c5..05ba5bc13 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
@@ -51,7 +51,7 @@  sem_timedwait (sem_t *sem, const struct timespec *abstime)
   while (1)
     {
       struct timeval tv;
-      struct timespec rt;
+      struct timespec rt, *rtp;
       int sec, nsec;
 
       /* Get the current time.  */
@@ -79,10 +79,12 @@  sem_timedwait (sem_t *sem, const struct timespec *abstime)
       rt.tv_sec = sec;
       rt.tv_nsec = nsec;
 
+      rtp = &rt;
+
       /* Enable asynchronous cancellation.  Required by the standard.  */
       int oldtype = __pthread_enable_asynccancel ();
 
-      err = lll_futex_timed_wait (&isem->value, 0, &rt,
+      err = lll_futex_timed_wait (&isem->value, 0, rtp,
 				  isem->private ^ FUTEX_PRIVATE_FLAG);
 
       /* Disable asynchronous cancellation.  */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
index 80d242f21..d7c2aa804 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
@@ -38,6 +38,17 @@  static int compat_timer_settime (timer_t timerid, int flags,
 #  define timer_settime timer_settime_alias
 # endif
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct its64_struct {
+    __S64_TYPE interval_tv_sec;
+    __S64_TYPE interval_tv_nsec;
+    __S64_TYPE value_tv_sec;
+    __S64_TYPE value_tv_nsec;
+};
+
+#endif
+
 
 int
 timer_settime (
@@ -55,8 +66,14 @@  timer_settime (
 
       /* Delete the kernel timer object.  */
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
+      struct its64_struct __its64 = {
+            .interval_tv_sec = value->it_interval.tv_sec,
+            .interval_tv_nsec = value->it_interval.tv_nsec,
+            .value_tv_sec = value->it_value.tv_sec,
+            .value_tv_nsec = value->it_value.tv_nsec,
+      };
       int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
-				value, ovalue);
+				value ? &__its64 : 0, ovalue);
 # else
       int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
 				value, ovalue);
diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c
index b66b60231..eff40d68f 100644
--- a/librt/clock_gettime.c
+++ b/librt/clock_gettime.c
@@ -22,10 +22,26 @@ 
 #include <sys/time.h>
 #include "kernel-posix-cpu-timers.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+  __S64_TYPE tv_sec;
+  __S64_TYPE tv_nsec;
+};
+
+#endif
+
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
 #define SYSCALL_GETTIME \
-  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
-  break
+  { \
+  struct ts64_struct __ts64; \
+  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, &__ts64); \
+  if (tp) { \
+    tp->tv_sec = __ts64.tv_sec; \
+    tp->tv_nsec = __ts64.tv_nsec; \
+  } \
+  break; \
+  }
 #else
 #define SYSCALL_GETTIME \
   retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c
index eaae75720..786f7eede 100644
--- a/librt/clock_nanosleep.c
+++ b/librt/clock_nanosleep.c
@@ -21,6 +21,14 @@ 
 
 #include "kernel-posix-cpu-timers.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+    __S64_TYPE tv_sec;
+    __S64_TYPE tv_nsec;
+};
+
+#endif
 
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
@@ -36,18 +44,27 @@  clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
   if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
     clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
 
-  if (SINGLE_THREAD_P)
+  if (SINGLE_THREAD_P) {
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64)
-    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem);
+    struct ts64_struct __ts64 = {
+      .tv_sec = req ? req->tv_sec : 0,
+      .tv_nsec = req ? req->tv_nsec : 0
+    };
+    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req ? &__ts64 : 0, rem);
 #else
     r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
 #endif
+  }
   else
     {
 #ifdef __NEW_THREADS
       int oldstate = LIBC_CANCEL_ASYNC ();
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64)
-      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem);
+      struct ts64_struct __ts64_2 = {
+        .tv_sec = req ? req->tv_sec : 0,
+        .tv_nsec = req ? req->tv_nsec : 0
+      };
+      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req ? &__ts64_2 : 0, rem);
 #else
       r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req,
 			    rem);
diff --git a/librt/mq_timedreceive.c b/librt/mq_timedreceive.c
index db1ae1aa8..818f54faa 100644
--- a/librt/mq_timedreceive.c
+++ b/librt/mq_timedreceive.c
@@ -8,13 +8,29 @@ 
 #include <unistd.h>
 #include <cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+	__S64_TYPE tv_sec;
+	__S64_TYPE tv_nsec;
+};
+
+#endif
+
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedreceive_time64)
-#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64
+int _NC(mq_timedreceive)(mqd_t mqdes, char *restrict msg_ptr, size_t msg_len, unsigned int *restrict msq_prio, const struct timespec *restrict abs_timeout)
+{
+	struct ts64_struct __ts64 = {
+		.tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
+		.tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
+	};
+
+	return INLINE_SYSCALL(mq_timedreceive_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
+}
 #else
 #define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive
-#endif
-
 _syscall5(ssize_t, __NC(mq_timedreceive), mqd_t, mqdes, char *__restrict, msg_ptr, size_t, msg_len, unsigned int *__restrict, msq_prio, const struct timespec *__restrict, abs_timeout)
+#endif
 
 CANCELLABLE_SYSCALL(ssize_t, mq_timedreceive, (mqd_t mqdes, char *__restrict msg_ptr, size_t msq_len, unsigned int *__restrict msq_prio, const struct timespec *__restrict abs_timeout),
 		    (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
diff --git a/librt/mq_timedsend.c b/librt/mq_timedsend.c
index 6afaf5157..e8deea9cb 100644
--- a/librt/mq_timedsend.c
+++ b/librt/mq_timedsend.c
@@ -8,13 +8,31 @@ 
 #include <unistd.h>
 #include <cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct ts64_struct {
+	__S64_TYPE tv_sec;
+	__S64_TYPE tv_nsec;
+};
+
+#endif
+
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64)
 #define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64
+int _NC(mq_timedsend)(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msq_prio, const struct timespec *abs_timeout)
+{
+	struct ts64_struct __ts64 = {
+		.tv_sec = abs_timeout ? abs_timeout->tv_sec : 0,
+		.tv_nsec = abs_timeout ? abs_timeout->tv_nsec : 0,
+	};
+
+	return INLINE_SYSCALL(mq_timedsend_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, abs_timeout ? &__ts64 : 0);
+}
 #else
 #define __NR___mq_timedsend_nocancel __NR_mq_timedsend
+_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout)
 #endif
 
-_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout)
 CANCELLABLE_SYSCALL(int, mq_timedsend, (mqd_t mqdes, const char *msg_ptr, size_t msq_len, unsigned int msq_prio, const struct timespec *abs_timeout),
 		    (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout))
 lt_libc_hidden(mq_timedsend)
diff --git a/librt/timer_settime.c b/librt/timer_settime.c
index 022880297..31202b07a 100644
--- a/librt/timer_settime.c
+++ b/librt/timer_settime.c
@@ -9,13 +9,36 @@ 
 
 #include "kernel-posix-timers.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+
+struct its64_struct {
+    __S64_TYPE interval_tv_sec;
+    __S64_TYPE interval_tv_nsec;
+    __S64_TYPE value_tv_sec;
+    __S64_TYPE value_tv_nsec;
+};
+
+#endif
+
 #if defined(__NR_timer_settime) || defined(__NR_timer_settime64)
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
-#define __NR___syscall_timer_settime __NR_timer_settime64
+int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue)
+{
+	struct timer *kt = (struct timer *)timerid;
+
+    struct its64_struct __its64 = {
+        .interval_tv_sec = value->it_interval.tv_sec,
+        .interval_tv_nsec = value->it_interval.tv_nsec,
+        .value_tv_sec = value->it_value.tv_sec,
+        .value_tv_nsec = value->it_value.tv_nsec,
+    };
+
+	return INLINE_SYSCALL(timer_settime64, 4, kt->ktimerid, flags, value ? &__its64: 0, ovalue);
+}
 #else
+
 #define __NR___syscall_timer_settime __NR_timer_settime
-#endif
 
 static __inline__ _syscall4(int, __syscall_timer_settime, kernel_timer_t, ktimerid,
 			int, flags, const void *, value, void *, ovalue);
@@ -31,3 +54,4 @@  int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
 }
 
 #endif
+#endif