summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>2017-09-08 00:41:35 +0200
committerAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>2018-04-18 06:54:13 +0200
commit3ed0b55d9fc353077ef0a4b2c0d5803f1242ab00 (patch)
treec363343d61d19ae459c397139fc78c58463f218a
parentb19bc975ec8cde199c7c4a124eebde814306600b (diff)
downloadglibc-3ed0b55d9fc353077ef0a4b2c0d5803f1242ab00.tar.gz
Y2038: add function __clock_settime64
-rw-r--r--include/time.h2
-rw-r--r--sysdeps/unix/clock_settime.c56
-rw-r--r--sysdeps/unix/sysv/linux/clock_settime.c60
-rw-r--r--time/Versions1
4 files changed, 118 insertions, 1 deletions
diff --git a/include/time.h b/include/time.h
index e085fa5162..8101b638c6 100644
--- a/include/time.h
+++ b/include/time.h
@@ -35,6 +35,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..15626ee3e9 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -68,8 +68,62 @@ hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
}
#endif
+/* Set CLOCK to value TP, 64-bit Y2038-safe version. */
+int
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
+{
+ 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 \
+ do { \
+ struct timeval tv; \
+ TIMESPEC_TO_TIMEVAL (&tv, tp); \
+ \
+ retval = __settimeofday (&tv, NULL); \
+ } while (0)
+
+#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;
+}
-/* Set CLOCK to value TP. */
+/* Set CLOCK to value TP, 64-bit Y2038-unsafe version. */
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..70ddb9e5ff 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -35,4 +35,64 @@
#define SYSDEP_SETTIME_CPU \
retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
+/* 64-bit time version */
+
+#ifdef __NR_clock_settime64
+/* We know the clock_gettime64 syscall, so use it or else clock_gettime */
+
+extern int __y2038_linux_support;
+
+#define SYSDEP_SETTIME64 \
+ SYSDEP_SETTIME64_CPUTIME; \
+ case CLOCK_REALTIME: \
+ if (__y2038_linux_support) \
+ { \
+ 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); \
+ } \
+ else \
+ { \
+ retval = -1; \
+ __set_errno (EOVERFLOW); \
+ } \
+ if (retval == -1 && errno == ENOSYS) \
+ { \
+ if (! fits_in_time_t(tp->tv_sec)) \
+ { \
+ __set_errno (EOVERFLOW); \
+ } \
+ else \
+ { \
+ valid_timespec64_to_timespec(tp, &ts32); \
+ retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32); \
+ } \
+ } \
+ break
+#define SYSDEP_SETTIME64_CPUTIME \
+ struct __timespec64 ts64; \
+ struct timespec ts32;
+
+#else
+/* We don't know the clock_gettime64 syscall, so only use clock_gettime */
+
+#define SYSDEP_SETTIME64 \
+ SYSDEP_SETTIME64_CPUTIME; \
+ case CLOCK_REALTIME: \
+ if (! fits_in_time_t(tp->tv_sec)) \
+ { \
+ __set_errno (EOVERFLOW); \
+ } \
+ else \
+ { \
+ valid_timespec64_to_timespec(tp, &ts32); \
+ retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32); \
+ } \
+ break
+#define SYSDEP_SETTIME64_CPUTIME \
+ struct timespec ts32;
+
+#endif
+
#include <sysdeps/unix/clock_settime.c>
diff --git a/time/Versions b/time/Versions
index 27c46fc023..a00184daae 100644
--- a/time/Versions
+++ b/time/Versions
@@ -75,5 +75,6 @@ libc {
__clock_gettime64;
__vdso_clock_gettime64;
__y2038_kernel_support;
+ __clock_settime64;
}
}