This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation
- From: Lukasz Majewski <lukma at denx dot de>
- To: libc-alpha at sourceware dot org
- Cc: Paul Eggert <eggert at cs dot ucla dot edu>, Joseph Myers <joseph at codesourcery dot com>, Lukasz Majewski <lukma at denx dot de>
- Date: Mon, 15 Apr 2019 00:08:41 +0200
- Subject: [PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation
- References: <20190414220841.20243-1-lukma@denx.de>
This patch provides new __clock_nanosleep64 explicit 64 bit function
for sleeping specified time on specified clock ID. Moreover, a
32 bit version - __clock_nanosleep has been refactored to internally
use __clock_nanosleep64.
The __clock_nanosleep is now supposed to be used on 32 bit systems -
hence the necessary checks and conversions to 64 bit type. After this
change it is intrinsically Y2038 safe.
The new 64 bit syscall (clock_nanosleep_time64) available from Linux
5.1+ has been used when applicable on 32 bit systems.
The execution path on 64 bit systems has not been changed or affected
in any way.
Tests:
- The code has been tested with x86_64/x86 (native compilation):
make PARALLELMFLAGS="-j8" && make xcheck PARALLELMFLAGS="-j8"
- Run specific tests on ARM/x86 32bit systems (qemu):
https://github.com/lmajewski/meta-y2038
and run tests:
https://github.com/lmajewski/y2038-tests/commits/master
on kernels with and without 64 bit time support.
No regressions were observed.
* include/time.h (__clock_nanosleep64):
Add __clock_nanosleep alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep):
Refactor this function to be used only on 32 bit machines as a
wrapper on __clock_nanosleep64.
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep64):
Add
* sysdeps/unix/sysv/linux/clock_nanosleep.c (__clock_nanosleep64):
Use clock_nanosleep_time64 kernel syscall (available from
5.1-rc1+ Linux) by 32 bit Y2038 safe systems
---
include/time.h | 9 ++++++
sysdeps/unix/sysv/linux/clock_nanosleep.c | 52 ++++++++++++++++++++++++++++---
2 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/include/time.h b/include/time.h
index 7176ddbb84..75f3456017 100644
--- a/include/time.h
+++ b/include/time.h
@@ -148,6 +148,15 @@ extern int __clock_getres64 (clockid_t clock_id,
libc_hidden_proto (__clock_getres64);
#endif
+#if __TIMESIZE == 64
+# define __clock_nanosleep64 __clock_nanosleep
+#else
+extern int __clock_nanosleep64 (clockid_t clock_id, int flags,
+ const struct __timespec64 *req,
+ struct __timespec64 *rem);
+libc_hidden_proto (__clock_nanosleep64);
+#endif
+
/* Compute the `struct tm' representation of T,
offset OFFSET seconds east of UTC,
and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 0cb6614dc9..3f99b5df00 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -25,8 +25,8 @@
/* We can simply use the syscall. The CPU clocks are not supported
with this function. */
int
-__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
- struct timespec *rem)
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+ const struct __timespec64 *req, struct __timespec64 *rem)
{
if (clock_id == CLOCK_THREAD_CPUTIME_ID)
return EINVAL;
@@ -36,9 +36,53 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
/* If the call is interrupted by a signal handler or encounters an error,
it returns a positive value similar to errno. */
INTERNAL_SYSCALL_DECL (err);
+#if defined (__TIMESIZE) && __TIMESIZE != 64
+# if defined __NR_clock_nanosleep_time64
+ struct __timespec64 ts = *req;
+ ts.tv_pad = 0;
+ int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
+ flags, &ts, rem);
+# else
+ struct timespec req32, rem32;
+ valid_timespec64_to_timespec(req, &req32);
+ int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
+ &req32, &rem32);
+
+ if (! INTERNAL_SYSCALL_ERROR_P (r, err))
+ valid_timespec_to_timespec64(&rem32, rem);
+# endif
+#else
int r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep, err, clock_id, flags,
- req, rem);
+ req, rem);
+#endif
return (INTERNAL_SYSCALL_ERROR_P (r, err)
- ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
+ ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
}
weak_alias (__clock_nanosleep, clock_nanosleep)
+
+#if __TIMESIZE != 64
+int
+__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
+ struct timespec *rem)
+{
+ struct __timespec64 req64, rem64;
+ int retval;
+
+ if (! in_time_t_range (req->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ valid_timespec_to_timespec64 (req, &req64);
+ retval = __clock_nanosleep64 (clock_id, flags, &req64, &rem64);
+
+ if (! retval && rem && ! timespec64_to_timespec (&rem64, rem))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ return retval;
+}
+#endif
--
2.11.0