This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC v2 03/20] y2038: linux: Provide __clock_settime64 implementation
- From: Alistair Francis <alistair dot francis at wdc dot com>
- To: libc-alpha at sourceware dot org
- Cc: arnd at arndb dot de, adhemerval dot zanella at linaro dot org, fweimer at redhat dot com, palmer at sifive dot com, macro at wdc dot com, zongbox at gmail dot com, zong at andestech dot com, alistair dot francis at wdc dot com, alistair23 at gmail dot com
- Date: Mon, 24 Jun 2019 17:08:52 -0700
- Subject: [RFC v2 03/20] y2038: linux: Provide __clock_settime64 implementation
- Ironport-sdr: 5vWzNiXFiuHEjWl3nkzPdi7SdlA4DG734FakzqWNCGAgBr4H5UH1JbImR6kgOVpcHKSnOdPQih fFlx6Xbi2ec07f/gVsNDFSKMGivLsPj4d8K2bE341ij9KPrCG9WVggPNCV3sF5NInxQ8Nh4z5g gzdb0sUO5D+V4qv4EV7mqqrVkMOgl4DC2IzxLhYnsgtmNdsQzo3SDqHUoEcqE3VcOKmNMk2wCQ BtkLd7O+Bcqhup66Qi983lpStAvjq38w3lN7riNXkoEqBAQu+v748x1IUMqVRvALS+m8qXXDeO Ny7MK+sPVNvjEEe2Db5PJCUi
- Ironport-sdr: ShHySskeDXDN2h+4L23CWsA9cWMrFEZN2Hc6vbjYjJEQpuTxHOCg4+Q5Nfy1b16pZshmnDmMbG 29eCzO6ytKhpjGBtmzltF8K8l1NeQczO75FNs8YegkRBdrqn+v9dfh766ZPihwCceP/3fTOD3L fx9FI9MuJHbbV1ctSmZjeUj9hHnlqc9mTD/MOUnLwA4Y3Gr0X2Llu/mzB/uXVOSGG0EQ+cwZne 91Q9Zu8oUD3vSLH6I0l4Vhs2mnqPebsIM6zHBwvkqtjRVtO49FrrQsmUBETIPF9k/WY50sIxTg 3sg=
- References: <cover.1561421042.git.alistair.francis@wdc.com>
From: Lukasz Majewski <lukma@denx.de>
This patch provides new __clock_settime64 explicit 64 bit function for
setting the time. Moreover, a 32 bit version - __clock_settime - has been
refactored to internally use __clock_settime64.
The __clock_settime is now supposed to be used on systems still supporting
32 bit time (__TIMESIZE != 64) - hence the necessary conversion to 64 bit
struct timespec.
The new clock_settime64 syscall available from Linux 5.1+ has been used,
when applicable.
The __ASSUME_TIME64_SYSCALLS flag indicates if the Linux kernel supports
64 bit version of clock_settime (i.e. clock_settime64).
If this flag is not defined, the fallback with legacy clock_settime
supporting 32 bit time is used.
When working on 32 bit systems without Y2038 time support the
clock_settime64 returns error when one wants to set time with wrong
(overflowed) tv_sec value. Moreover, the correctness of tv_nsec is also
checked.
In this patch the internal padding (tv_pad) of struct __timespec64 is
left untouched (on systems with __WORDSIZE == 32) as Linux kernel ignores
upper 32 bits of tv_nsec.
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_settime64):
Add __clock_settime alias according to __TIMESIZE define
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime):
Refactor this function to be used only on 32 bit machines as a wrapper
on __clock_settime64.
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64): Add
* sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime64):
Use clock_settime64 kernel syscall (available from 5.1-rc1+ Linux)
---
include/time.h | 8 ++++++
sysdeps/unix/sysv/linux/clock_settime.c | 37 ++++++++++++++++++++++---
2 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/include/time.h b/include/time.h
index 1b38d019c8..7155b2e4db 100644
--- a/include/time.h
+++ b/include/time.h
@@ -127,6 +127,14 @@ extern __time64_t __timegm64 (struct tm *__tp) __THROW;
libc_hidden_proto (__timegm64)
#endif
+#if __TIMESIZE == 64
+# define __clock_settime64 __clock_settime
+#else
+extern int __clock_settime64 (clockid_t clock_id,
+ const struct __timespec64 *tp);
+libc_hidden_proto (__clock_settime64)
+#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_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index d837e3019c..7274f01846 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -19,11 +19,9 @@
#include <sysdep.h>
#include <time.h>
-#include "kernel-posix-cpu-timers.h"
-
/* Set CLOCK to value TP. */
int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
{
/* Make sure the time cvalue is OK. */
if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
@@ -32,6 +30,37 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp)
return -1;
}
- return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp);
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_clock_settime64
+# define __NR_clock_settime64 __NR_clock_settime
+# endif
+ return INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
+#else
+# ifdef __NR_clock_settime64
+ int ret = INLINE_SYSCALL_CALL (clock_settime64, clock_id, tp);
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+# endif
+ if (! in_time_t_range (tp->tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ struct timespec ts32;
+ valid_timespec64_to_timespec (tp, &ts32);
+ return INLINE_SYSCALL_CALL (clock_settime, clock_id, &ts32);
+#endif
}
weak_alias (__clock_settime, clock_settime)
+
+#if __TIMESIZE != 64
+int
+__clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+ struct __timespec64 ts64;
+
+ valid_timespec_to_timespec64 (tp, &ts64);
+ return __clock_settime64 (clock_id, &ts64);
+}
+#endif
--
2.22.0