[RFC,10/52] Y2038: add function __clock_nanosleep64
Commit Message
Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
include/time.h | 3 ++
sysdeps/unix/sysv/linux/arm/Versions | 1 +
sysdeps/unix/sysv/linux/clock_nanosleep.c | 87 ++++++++++++++++++++++++++++++-
3 files changed, 90 insertions(+), 1 deletion(-)
@@ -54,6 +54,9 @@ extern int __clock_settime64 (clockid_t __clock_id,
const struct __timespec64 *__tp) __THROW;
extern int __clock_getres64 (clockid_t __clock_id,
struct __timespec64 *__res) __THROW;
+extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
+ const struct __timespec64 *__req,
+ struct __timespec64 *__rem);
/* Now define the internal interfaces. */
struct tm;
@@ -32,5 +32,6 @@ libc {
__y2038_kernel_support;
__clock_settime64;
__clock_getres64;
+ __clock_nanosleep64;
}
}
@@ -21,7 +21,6 @@
#include <sysdep-cancel.h>
#include "kernel-posix-cpu-timers.h"
-
/* We can simply use the syscall. The CPU clocks are not supported
with this function. */
int
@@ -52,3 +51,89 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
weak_alias (__clock_nanosleep, clock_nanosleep)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+ const struct __timespec64 *req,
+ struct __timespec64 *rem)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ int r;
+ struct __timespec64 req64;
+ struct timespec req32, rem32;
+
+ if (clock_id == CLOCK_THREAD_CPUTIME_ID)
+ return EINVAL;
+ if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
+ clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
+
+ if (SINGLE_THREAD_P)
+ {
+ if (__y2038_linux_support)
+ {
+ req64.tv_sec = req->tv_sec;
+ req64.tv_nsec = req->tv_nsec;
+ req64.tv_pad = 0;
+ r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+ &req64, rem);
+ }
+ else if (req->tv_sec > INT_MAX)
+ r = EOVERFLOW;
+ else
+ {
+ req32.tv_sec = req->tv_sec;
+ req32.tv_nsec = req->tv_nsec;
+ r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+ &req32, &rem32);
+ if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+ {
+ rem->tv_sec = rem32.tv_sec;
+ rem->tv_nsec = rem32.tv_nsec;
+ rem->tv_pad = 0;
+ }
+ }
+ }
+ else
+ {
+ int oldstate = LIBC_CANCEL_ASYNC ();
+
+ if (__y2038_linux_support)
+ {
+ req64.tv_sec = req->tv_sec;
+ req64.tv_nsec = req->tv_nsec;
+ req64.tv_pad = 0;
+ r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+ &req64, rem);
+ }
+ else if (req->tv_sec > INT_MAX)
+ r = EOVERFLOW;
+ else
+ {
+ req32.tv_sec = req->tv_sec;
+ req32.tv_nsec = req->tv_nsec;
+ r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+ &req32, &rem32);
+ if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+ {
+ rem->tv_sec = rem32.tv_sec;
+ rem->tv_nsec = rem32.tv_nsec;
+ rem->tv_pad = 0;
+ }
+ }
+
+ LIBC_CANCEL_RESET (oldstate);
+ }
+
+ if (INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ return INTERNAL_SYSCALL_ERRNO (r, err);
+ }
+ else
+ {
+ return 0;
+ }
+}