This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 6/6] y2038: linux: Provide __clock_nanosleep64 implementation


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]