Y2038: add function __clock_settime64

Message ID 20180919073553.28153-1-albert.aribaud@3adev.fr
State New
Headers show
Series
  • Y2038: add function __clock_settime64
Related show

Commit Message

Albert ARIBAUD Sept. 19, 2018, 7:35 a.m.
* include/time.h (__clock_settime64): Add.
* sysdeps/unix/clock_settime.c (__clock_settime64): Add.
* sysdeps/unix/sysv/linux/clock_settime.c (DO_CLOCK_SETTIME_32): Add.
* sysdeps/unix/sysv/linux/clock_settime.c (DO_CLOCK_SETTIME_64): Add.
* sysdeps/unix/sysv/linux/clock_settime.c (SYSDEP_SETTIME64_CPUTIME): Add.
* sysdeps/unix/sysv/linux/clock_settime.c (SYSDEP_SETTIME64): Add.
---

This patch is part of the Y2038 patch series, which is available at
<https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/aaribaud/y2038>.
Warning: this branch may be rebased on current master and/or updated based on
feedback from the list at any time.

 include/time.h                          |  2 +
 sysdeps/unix/clock_settime.c            | 60 ++++++++++++++++++++++++-
 sysdeps/unix/sysv/linux/clock_settime.c | 58 ++++++++++++++++++++++++
 3 files changed, 119 insertions(+), 1 deletion(-)

Comments

Joseph Myers Sept. 19, 2018, 1:15 p.m. | #1
On Wed, 19 Sep 2018, Albert ARIBAUD (3ADEV) wrote:

> +  if (! IS_VALID_NANOSECONDS(tp->tv_nsec))

Missing space.

> +  if (! fits_in_time_t(tp->tv_sec))					\

Likewise.

> +      valid_timespec64_to_timespec(tp, &ts32);  			\

Likewise.

> +      if (retval == 1 && errno==ENOSYS)					\

Likewise, around the ==.

Please check and fix the whole patch series for such coding style issues.

Patch

diff --git a/include/time.h b/include/time.h
index 9efd153b83..5a658223ce 100644
--- a/include/time.h
+++ b/include/time.h
@@ -26,6 +26,8 @@  extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
 extern int __clock_gettime64 (clockid_t __clock_id,
 			      struct __timespec64 *__tp) __THROW;
+extern int __clock_settime64 (clockid_t __clock_id,
+			       const struct __timespec64 *__tp) __THROW;
 
 /* Now define the internal interfaces.  */
 struct tm;
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 38813eddf7..13abe31023 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -68,8 +68,66 @@  hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
 }
 #endif
 
-
 /* Set CLOCK to value TP.  */
+int
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
+{
+#ifndef HANDLED_REALTIME
+  struct timeval tv32;
+#endif
+  int retval = -1;
+
+  /* Make sure the time cvalue is OK.  */
+  if (! IS_VALID_NANOSECONDS(tp->tv_nsec))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  switch (clock_id)
+    {
+#define HANDLE_REALTIME64 \
+      if (timespec64_to_timeval (tp, &tv32))				\
+        {								\
+	  retval = __settimeofday (&tv32, NULL);			\
+      else								\
+        {								\
+          __set_errno (EOVERFLOW);					\
+	  retval = -1;							\
+        }
+
+#ifdef SYSDEP_SETTIME64
+      SYSDEP_SETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      HANDLE_REALTIME64;
+      break;
+#endif
+
+    default:
+#ifdef SYSDEP_SETTIME64_CPU
+      SYSDEP_SETTIME64_CPU;
+#endif
+#ifndef HANDLED_CPUTIME
+# if HP_TIMING_AVAIL
+      if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
+	  || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_settime (clock_id, tp);
+      else
+# endif
+	{
+	  __set_errno (EINVAL);
+	  retval = -1;
+	}
+#endif
+      break;
+    }
+
+  return retval;
+}
+
 int
 __clock_settime (clockid_t clock_id, const struct timespec *tp)
 {
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 5f3f22f74b..5913dd69d5 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -18,6 +18,7 @@ 
 #include <errno.h>
 #include <sysdep.h>
 #include <time.h>
+#include <y2038-support.h>
 
 #include "kernel-posix-cpu-timers.h"
 
@@ -35,4 +36,61 @@ 
 #define SYSDEP_SETTIME_CPU \
   retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
 
+/* 64-bit time version */
+
+# define DO_CLOCK_SETTIME_32 \
+  if (! fits_in_time_t(tp->tv_sec))					\
+    {									\
+      __set_errno (EOVERFLOW);						\
+      retval = -1;							\
+    }									\
+  else									\
+    {									\
+      valid_timespec64_to_timespec(tp, &ts32);  			\
+      retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32);	\
+    }
+
+#ifdef __NR_clock_settime64
+
+/* We are building with a 64-bit-time clock_gettime syscall */
+
+# define DO_CLOCK_SETTIME_64 \
+  if (__y2038_linux_support > 0)					\
+    {									\
+      ts64.tv_sec = tp->tv_sec;						\
+      ts64.tv_nsec = tp->tv_nsec;						\
+      ts64.tv_pad = 0;							\
+      retval = INLINE_SYSCALL (clock_settime64, 2, clock_id, &ts64);	\
+      if (retval == 1 && errno==ENOSYS)					\
+	{								\
+	  __y2038_linux_support = -1;					\
+	  DO_CLOCK_SETTIME_32;						\
+	}								\
+    }									\
+  else									\
+    {									\
+      DO_CLOCK_SETTIME_32;						\
+    }
+
+# define SYSDEP_SETTIME64_CPUTIME \
+  struct __timespec64 ts64;						\
+  struct timespec ts32
+
+#else
+
+/* We are building without a 64-bit-time clock_gettime syscall */
+
+# define DO_CLOCK_SETTIME_64 DO_CLOCK_SETTIME_32
+
+# define SYSDEP_SETTIME64_CPUTIME \
+  struct timespec ts32
+
+#endif
+
+#define SYSDEP_SETTIME64 \
+  SYSDEP_SETTIME64_CPUTIME;						\
+  case CLOCK_REALTIME:							\
+    DO_CLOCK_SETTIME_64;						\
+    break
+
 #include <sysdeps/unix/clock_settime.c>