diff mbox series

[uclibc-ng-devel,v4] Add support for using time64 on big-endian machines.

Message ID 20240225115234.401891-1-dm.chestnykh@gmail.com
State Accepted
Headers show
Series [uclibc-ng-devel,v4] Add support for using time64 on big-endian machines. | expand

Commit Message

Dmitry Chestnykh Feb. 25, 2024, 11:52 a.m. UTC
For BE architectures there is one significant difference
in comparison with time64 support for little-endian
architectures like ARMv7.
The difference is that we strictly need to pass two 64bit
values to system calls because Linux Kernel internally uses
`struct __kernel_timespec` and similar, which consists of two
64bit fields.
For this reason many files have been changed to convert
pointers to timespec-family structures (mixed of 64bit and 32bit values)
to the pointer of the similar but 64bit-only structures
for using as system calls args.
This is general prerequisite for any BE architecture.

Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
---
Added newline to the end of time64_helpers.h.
Yes, we can use the old definition of lll_futex_wait() macro
because i reworked a little TO_TS64_P().
 include/internal/time64_helpers.h             | 31 +++++++++++++++++++
 libc/inet/socketcalls.c                       |  6 +++-
 libc/misc/sysvipc/sem.c                       |  9 +++++-
 libc/signal/sigwait.c                         |  3 +-
 libc/sysdeps/linux/common/__rt_sigtimedwait.c | 10 ++++--
 libc/sysdeps/linux/common/__rt_sigwaitinfo.c  |  2 +-
 libc/sysdeps/linux/common/alarm.c             |  2 +-
 libc/sysdeps/linux/common/clock_getres.c      | 15 +++++++--
 libc/sysdeps/linux/common/clock_gettime.c     | 14 ++++++++-
 libc/sysdeps/linux/common/clock_settime.c     |  7 ++++-
 libc/sysdeps/linux/common/ppoll.c             |  6 +++-
 libc/sysdeps/linux/common/pselect.c           |  6 +++-
 libc/sysdeps/linux/common/select.c            | 16 +++++++---
 libc/sysdeps/linux/common/time.c              |  2 +-
 libc/sysdeps/linux/common/timerfd.c           |  9 +++++-
 libc/sysdeps/linux/common/utimensat.c         | 20 +++++++++++-
 libpthread/nptl/pthread_mutex_timedlock.c     |  6 +++-
 .../sysdeps/unix/sysv/linux/lowlevellock.h    |  6 +++-
 .../sysdeps/unix/sysv/linux/timer_settime.c   |  5 ++-
 librt/clock_gettime.c                         | 17 ++++++++--
 librt/clock_nanosleep.c                       |  7 +++--
 librt/mq_timedreceive.c                       | 10 ++++--
 librt/mq_timedsend.c                          |  9 ++++--
 librt/timer_settime.c                         | 11 +++++--
 24 files changed, 193 insertions(+), 36 deletions(-)
 create mode 100644 include/internal/time64_helpers.h

Comments

Max Filippov Feb. 25, 2024, 12:05 p.m. UTC | #1
On Sun, Feb 25, 2024 at 3:52 AM Dmitry Chestnykh <dm.chestnykh@gmail.com> wrote:
>
> For BE architectures there is one significant difference
> in comparison with time64 support for little-endian
> architectures like ARMv7.
> The difference is that we strictly need to pass two 64bit
> values to system calls because Linux Kernel internally uses
> `struct __kernel_timespec` and similar, which consists of two
> 64bit fields.
> For this reason many files have been changed to convert
> pointers to timespec-family structures (mixed of 64bit and 32bit values)
> to the pointer of the similar but 64bit-only structures
> for using as system calls args.
> This is general prerequisite for any BE architecture.
>
> Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>
> ---
> Added newline to the end of time64_helpers.h.
> Yes, we can use the old definition of lll_futex_wait() macro
> because i reworked a little TO_TS64_P().
>  include/internal/time64_helpers.h             | 31 +++++++++++++++++++
>  libc/inet/socketcalls.c                       |  6 +++-
>  libc/misc/sysvipc/sem.c                       |  9 +++++-
>  libc/signal/sigwait.c                         |  3 +-
>  libc/sysdeps/linux/common/__rt_sigtimedwait.c | 10 ++++--
>  libc/sysdeps/linux/common/__rt_sigwaitinfo.c  |  2 +-
>  libc/sysdeps/linux/common/alarm.c             |  2 +-
>  libc/sysdeps/linux/common/clock_getres.c      | 15 +++++++--
>  libc/sysdeps/linux/common/clock_gettime.c     | 14 ++++++++-
>  libc/sysdeps/linux/common/clock_settime.c     |  7 ++++-
>  libc/sysdeps/linux/common/ppoll.c             |  6 +++-
>  libc/sysdeps/linux/common/pselect.c           |  6 +++-
>  libc/sysdeps/linux/common/select.c            | 16 +++++++---
>  libc/sysdeps/linux/common/time.c              |  2 +-
>  libc/sysdeps/linux/common/timerfd.c           |  9 +++++-
>  libc/sysdeps/linux/common/utimensat.c         | 20 +++++++++++-
>  libpthread/nptl/pthread_mutex_timedlock.c     |  6 +++-
>  .../sysdeps/unix/sysv/linux/lowlevellock.h    |  6 +++-
>  .../sysdeps/unix/sysv/linux/timer_settime.c   |  5 ++-
>  librt/clock_gettime.c                         | 17 ++++++++--
>  librt/clock_nanosleep.c                       |  7 +++--
>  librt/mq_timedreceive.c                       | 10 ++++--
>  librt/mq_timedsend.c                          |  9 ++++--
>  librt/timer_settime.c                         | 11 +++++--
>  24 files changed, 193 insertions(+), 36 deletions(-)
>  create mode 100644 include/internal/time64_helpers.h

This version looks good to me.
Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>

--
Thanks.
-- Max
Waldemar Brodkorb Feb. 26, 2024, 8:31 a.m. UTC | #2
Hi Dmitry,
Dmitry Chestnykh wrote,

> For BE architectures there is one significant difference
> in comparison with time64 support for little-endian
> architectures like ARMv7.
> The difference is that we strictly need to pass two 64bit
> values to system calls because Linux Kernel internally uses
> `struct __kernel_timespec` and similar, which consists of two
> 64bit fields.
> For this reason many files have been changed to convert
> pointers to timespec-family structures (mixed of 64bit and 32bit values)
> to the pointer of the similar but 64bit-only structures
> for using as system calls args.
> This is general prerequisite for any BE architecture.
> 
> Signed-off-by: Dmitry Chestnykh <dm.chestnykh@gmail.com>

Thanks!
Applied and pushed.
 best regards
  Waldemar
diff mbox series

Patch

diff --git a/include/internal/time64_helpers.h b/include/internal/time64_helpers.h
new file mode 100644
index 000000000..7a78e8388
--- /dev/null
+++ b/include/internal/time64_helpers.h
@@ -0,0 +1,31 @@ 
+#ifndef _TIME64_HELPERS_H
+#define _TIME64_HELPERS_H
+
+#include <bits/types.h>
+#include <time.h>
+#include <stddef.h>
+
+struct __ts64_struct {
+   __S64_TYPE tv_sec;
+   __S64_TYPE tv_nsec;
+};
+
+#define TO_TS64_P(__ts) (((struct timespec *)(__ts)) ? \
+                        (&(struct __ts64_struct) {.tv_sec = ((struct timespec *)(__ts))->tv_sec, \
+                                                  .tv_nsec = ((struct timespec *)(__ts))->tv_nsec}) : NULL)
+
+struct __its64_struct {
+    __S64_TYPE interval_tv_sec;
+    __S64_TYPE interval_tv_nsec;
+    __S64_TYPE value_tv_sec;
+    __S64_TYPE value_tv_nsec;
+};
+
+#define TO_ITS64_P(__its) (((struct itimerspec *)(__its)) ? \ 
+                          (&(struct __its64_struct) {.interval_tv_sec = ((struct itimerspec *)(__its))->it_interval.tv_sec, \
+                                                     .interval_tv_nsec = ((struct itimerspec *)(__its))->it_interval.tv_nsec, \
+                                                     .value_tv_sec = ((struct itimerspec *)(__its))->it_value.tv_sec, \
+                                                     .value_tv_nsec = ((struct itimerspec *)(__its))->it_value.tv_nsec}) : NULL)
+
+
+#endif /* _TIME64_HELPERS_H */
diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c
index eb0983698..774ed6091 100644
--- a/libc/inet/socketcalls.c
+++ b/libc/inet/socketcalls.c
@@ -10,6 +10,10 @@ 
 #include <cancel.h>
 #include <bits/kernel-features.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
+
 #ifdef __NR_socketcall
 /* Various socketcall numbers */
 #define SYS_SOCKET      1
@@ -273,7 +277,7 @@  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);
+	return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, TO_TS64_P(tmo));
 # 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..07076eff7 100644
--- a/libc/misc/sysvipc/sem.c
+++ b/libc/misc/sysvipc/sem.c
@@ -23,6 +23,9 @@ 
 
 #include "ipc.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
 
 #ifdef L_semctl
 /* Return identifier for array of NSEMS semaphores associated with
@@ -96,7 +99,11 @@  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)
+int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout)
+{
+    return INLINE_SYSCALL(semtimedop_time64, 4, semid, sops, nsops, TO_TS64_P(timeout));
+}
+
 #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..aff5299a1 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,10 @@ 
 #  include <string.h>
 # endif
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
+
 int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
 		       const struct timespec *timeout)
 {
@@ -54,7 +58,7 @@  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
 	/* on uClibc we use the kernel sigset_t size */
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)
 	result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
-				    timeout, __SYSCALL_SIGSET_T_SIZE);
+				    TO_TS64_P(timeout), __SYSCALL_SIGSET_T_SIZE);
 # else
 	result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
 				    timeout, __SYSCALL_SIGSET_T_SIZE);
@@ -72,7 +76,7 @@  int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
 	/* on uClibc we use the kernel sigset_t size */
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)
 	return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info,
-			      timeout, __SYSCALL_SIGSET_T_SIZE);
+			      TO_TS64_P(timeout), __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..fd0f8c14c 100644
--- a/libc/sysdeps/linux/common/clock_getres.c
+++ b/libc/sysdeps/linux/common/clock_getres.c
@@ -10,9 +10,20 @@ 
 #include <sys/syscall.h>
 #include <time.h>
 
-
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64)
-_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct timespec*, res)
+#include "internal/time64_helpers.h"
+
+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..4d787b9b7 100644
--- a/libc/sysdeps/linux/common/clock_gettime.c
+++ b/libc/sysdeps/linux/common/clock_gettime.c
@@ -12,7 +12,19 @@ 
 #include <time.h>
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
-_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp)
+#include "internal/time64_helpers.h"
+
+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..3abc5f49b 100644
--- a/libc/sysdeps/linux/common/clock_settime.c
+++ b/libc/sysdeps/linux/common/clock_settime.c
@@ -12,7 +12,12 @@ 
 
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64)
-_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp)
+#include "internal/time64_helpers.h"
+
+int clock_settime(clockid_t clock_id, const struct timespec *tp)
+{
+	return INLINE_SYSCALL(clock_settime64, 2, clock_id, TO_TS64_P(tp));
+}
 #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..870717bd7 100644
--- a/libc/sysdeps/linux/common/ppoll.c
+++ b/libc/sysdeps/linux/common/ppoll.c
@@ -26,6 +26,10 @@ 
 #include <sys/poll.h>
 #include <cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
+
 static int
 __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
 	    const sigset_t *sigmask)
@@ -38,7 +42,7 @@  __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);
+	return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, TO_TS64_P(timeout), 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..7a446a589 100644
--- a/libc/sysdeps/linux/common/pselect.c
+++ b/libc/sysdeps/linux/common/pselect.c
@@ -26,6 +26,10 @@ 
 #include <signal.h>
 #include <cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#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 +61,7 @@  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);
+	return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, TO_TS64_P(timeout), 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..84016dd0b 100644
--- a/libc/sysdeps/linux/common/select.c
+++ b/libc/sysdeps/linux/common/select.c
@@ -15,17 +15,19 @@ 
 # 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__)
+#include "internal/time64_helpers.h"
+#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 +49,14 @@  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)
+	return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds, exceptfds, TO_TS64_P(ts), 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, ts);
+#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..b4a9e1a93 100644
--- a/libc/sysdeps/linux/common/timerfd.c
+++ b/libc/sysdeps/linux/common/timerfd.c
@@ -9,6 +9,10 @@ 
 #include <sys/syscall.h>
 #include <sys/timerfd.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
+
 /*
  * timerfd_create()
  */
@@ -21,7 +25,10 @@  _syscall2(int, timerfd_create, int, clockid, int, flags)
  */
 #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)
+{
+    return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, TO_ITS64_P(utmr), 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..fa6f90e55 100644
--- a/libc/sysdeps/linux/common/utimensat.c
+++ b/libc/sysdeps/linux/common/utimensat.c
@@ -9,9 +9,27 @@ 
 #include <sys/syscall.h>
 #include <sys/stat.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#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 __ts64_struct __times64[2] = {
+        {
+            .tv_sec = times ? times[0].tv_sec : 0,
+            .tv_nsec = times ? times[0].tv_nsec : 0
+        },
+        {
+            .tv_sec = times ? times[1].tv_sec : 0,
+            .tv_nsec = times ? times[1].tv_nsec : 0
+        }
+    };
+
+    return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? &__times64 : 0, flags);
+}
 #else
 _syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags)
 #endif
diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c
index 25f9ec3b2..d54983315 100644
--- a/libpthread/nptl/pthread_mutex_timedlock.c
+++ b/libpthread/nptl/pthread_mutex_timedlock.c
@@ -23,6 +23,10 @@ 
 #include <lowlevellock.h>
 #include <not-cancel.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#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’
@@ -268,7 +272,7 @@  pthread_mutex_timedlock (
 	    int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock,
 				      __lll_private_flag (FUTEX_LOCK_PI,
 							  private), 1,
-				      abstime);
+				      TO_TS64_P(abstime));
 #else
 	    int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
 				      __lll_private_flag (FUTEX_LOCK_PI,
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
index e72fe5234..6ecc23e25 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h
@@ -24,6 +24,10 @@ 
 #include <sysdep.h>
 #include <bits/kernel-features.h>
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
+
 #define FUTEX_WAIT		0
 #define FUTEX_WAKE		1
 #define FUTEX_REQUEUE		3
@@ -82,7 +86,7 @@ 
     long int __ret;							      \
     __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp),		      \
 			      __lll_private_flag (FUTEX_WAIT, private),	      \
-			      (val), (timespec));			      \
+			      (val), (TO_TS64_P(timespec)));			      \
     __ret;								      \
   })
 
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
index 80d242f21..1cccf57cb 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c
@@ -23,6 +23,9 @@ 
 #include <bits/kernel-features.h>
 #include "kernel-posix-timers.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
 
 #ifdef __NR_timer_settime
 # ifndef __ASSUME_POSIX_TIMERS
@@ -56,7 +59,7 @@  timer_settime (
       /* Delete the kernel timer object.  */
 # if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64)
       int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
-				value, ovalue);
+				TO_ITS64_P(value), 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..eab9a3343 100644
--- a/librt/clock_gettime.c
+++ b/librt/clock_gettime.c
@@ -22,10 +22,21 @@ 
 #include <sys/time.h>
 #include "kernel-posix-cpu-timers.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
+
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
-#define SYSCALL_GETTIME \
-  retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \
-  break
+#define SYSCALL_GETTIME           \
+  {                               \
+  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..ef59369df 100644
--- a/librt/clock_nanosleep.c
+++ b/librt/clock_nanosleep.c
@@ -21,6 +21,9 @@ 
 
 #include "kernel-posix-cpu-timers.h"
 
+#if defined(__UCLIBC_USE_TIME64__)
+#include "internal/time64_helpers.h"
+#endif
 
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
@@ -38,7 +41,7 @@  clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 
   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);
+    r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, TO_TS64_P(req), rem);
 #else
     r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
 #endif
@@ -47,7 +50,7 @@  clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 #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);
+      r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, TO_TS64_P(req), 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..f89b4c36b 100644
--- a/librt/mq_timedreceive.c
+++ b/librt/mq_timedreceive.c
@@ -9,12 +9,16 @@ 
 #include <cancel.h>
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedreceive_time64)
-#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64
+#include "internal/time64_helpers.h"
+
+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)
+{
+	return INLINE_SYSCALL(mq_timedreceive_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, TO_TS64_P(abs_timeout));
+}
 #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..b081ac0ce 100644
--- a/librt/mq_timedsend.c
+++ b/librt/mq_timedsend.c
@@ -9,12 +9,17 @@ 
 #include <cancel.h>
 
 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64)
-#define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64
+#include "internal/time64_helpers.h"
+
+int _NC(mq_timedsend)(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msq_prio, const struct timespec *abs_timeout)
+{
+	return INLINE_SYSCALL(mq_timedsend_time64, 5, mqdes, msg_ptr, msg_len, msq_prio, TO_TS64_P(abs_timeout));
+}
 #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..425cd7ee9 100644
--- a/librt/timer_settime.c
+++ b/librt/timer_settime.c
@@ -12,10 +12,16 @@ 
 #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
+#include "internal/time64_helpers.h"
+
+int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue)
+{
+	struct timer *kt = (struct timer *)timerid;
+
+	return INLINE_SYSCALL(timer_settime64, 4, kt->ktimerid, flags, TO_ITS64_P(value), 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 +37,4 @@  int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
 }
 
 #endif
+#endif