This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH v4] y2038: linux: Provide ___gettimeofday64 implementation
- From: Lukasz Majewski <lukma at denx dot de>
- To: Joseph Myers <joseph at codesourcery dot com>, Paul Eggert <eggert at cs dot ucla dot edu>, Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- Cc: Alistair Francis <alistair23 at gmail dot com>, Alistair Francis <alistair dot francis at wdc dot com>, GNU C Library <libc-alpha at sourceware dot org>, Siddhesh Poyarekar <siddhesh at gotplt dot org>, Florian Weimer <fweimer at redhat dot com>, Florian Weimer <fw at deneb dot enyo dot de>, Zack Weinberg <zackw at panix dot com>, Carlos O'Donell <carlos at redhat dot com>, Andreas Schwab <schwab at suse dot de>, Lukasz Majewski <lukma at denx dot de>
- Date: Mon, 10 Feb 2020 12:01:07 +0100
- Subject: [PATCH v4] y2038: linux: Provide ___gettimeofday64 implementation
In the glibc the gettimeofday can use vDSO (on power and x86 the
USE_IFUNC_GETTIMEOFDAY is defined), gettimeofday syscall or 'default'
___gettimeofday() from ./time/gettime.c (as a fallback).
In this patch the last function (___gettimeofday) has been refactored and
moved to ./sysdeps/unix/sysv/linux/gettimeofday.c to be Linux specific.
The new __gettimeofday64 explicit 64 bit function for getting 64 bit time from
the kernel (by internally calling __clock_gettime64) has been introduced.
Moreover, a 32 bit version - __gettimeofday has been refactored to internally
use __gettimeofday64.
The __gettimeofday is now supposed to be used on systems still supporting 32
bit time (__TIMESIZE != 64) - hence the necessary check for time_t potential
overflow and conversion of struct __timeval64 to 32 bit struct timespec.
The alpha port is a bit problematic for this change - it supports 64 bit time
and can safely use gettimeofday implementation from ./time/gettimeofday.c as it
has ./sysdeps/unix/sysv/linux/alpha/gettimeofday.c, which includes
./time/gettimeofday.c, so the Linux specific one can be avoided.
For that reason the code to set default gettimeofday symbol has not been moved
to ./sysdeps/unix/sysv/linux/gettimeofday.c as only alpha defines
VERSION_gettimeofday.
The USE_IFUNC_GETTIMEOFDAY for powerpc and i686 has been undefined on
purpose. Due to that the support for gettimeofday vDSO on them has been
traded for Y2038 safeness (as this syscall is going to be obsolete).
Build tests:
./src/scripts/build-many-glibcs.py glibcs
Run-time tests:
- 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
Above tests were performed with Y2038 redirection applied as well as without
to test proper usage of both ___gettimeofday64 and __gettimeofday.
---
Changes for v4:
- Rename ___gettimeofday{64} to __gettimeofday{64} as '___' prefix is not
needed for our implementation
- Correctly handle the case when tv is NULL (also in __gettimeofday).
- Do not define USE_IFUNC_GETTIMEOFDAY for 32 bit archs - namely powerpc and
i686.
Changes for v3:
- New patch
---
include/time.h | 4 ++
sysdeps/unix/sysv/linux/gettimeofday.c | 44 ++++++++++++++++++-
.../unix/sysv/linux/powerpc/gettimeofday.c | 4 +-
sysdeps/unix/sysv/linux/x86/gettimeofday.c | 4 +-
4 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/include/time.h b/include/time.h
index 73f66277ac..61806658e7 100644
--- a/include/time.h
+++ b/include/time.h
@@ -227,10 +227,14 @@ libc_hidden_proto (__sched_rr_get_interval64);
#if __TIMESIZE == 64
# define __settimeofday64 __settimeofday
+# define __gettimeofday64 __gettimeofday
#else
extern int __settimeofday64 (const struct __timeval64 *tv,
const struct timezone *tz);
libc_hidden_proto (__settimeofday64)
+extern int __gettimeofday64 (struct __timeval64 *restrict tv,
+ void *restrict tz);
+libc_hidden_proto (__gettimeofday64)
#endif
/* Compute the `struct tm' representation of T,
diff --git a/sysdeps/unix/sysv/linux/gettimeofday.c b/sysdeps/unix/sysv/linux/gettimeofday.c
index d5cdb22495..7e77b4cfad 100644
--- a/sysdeps/unix/sysv/linux/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/gettimeofday.c
@@ -54,5 +54,47 @@ __gettimeofday (struct timeval *restrict tv, void *restrict tz)
# endif
weak_alias (__gettimeofday, gettimeofday)
#else /* USE_IFUNC_GETTIMEOFDAY */
-# include <time/gettimeofday.c>
+/* Conversion of gettimeofday function to support 64 bit time on archs
+ with __WORDSIZE == 32 and __TIMESIZE == 32/64 */
+#include <errno.h>
+
+int
+__gettimeofday64 (struct __timeval64 *restrict tv, void *restrict tz)
+{
+ if (__glibc_unlikely (tz != 0))
+ memset (tz, 0, sizeof (struct timezone));
+
+ struct __timespec64 ts64;
+ int ret = __clock_gettime64 (CLOCK_REALTIME, &ts64);
+
+ if (ret == 0 && tv)
+ *tv = timespec64_to_timeval64 (ts64);
+
+ return ret;
+}
+
+# if __TIMESIZE != 64
+libc_hidden_def (__gettimeofday64)
+
+int
+__gettimeofday (struct timeval *restrict tv, void *restrict tz)
+{
+ struct __timeval64 tv64;
+ int ret = __gettimeofday64 (tv ? &tv64 : NULL, tz);
+
+ if (ret == 0 && tv)
+ {
+ if (! in_time_t_range (tv64.tv_sec))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ *tv = valid_timeval64_to_timeval (tv64);
+ }
+
+ return ret;
+}
+# endif
+weak_alias (__gettimeofday, gettimeofday)
#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 183fb0ac70..2d6978f333 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -15,5 +15,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define USE_IFUNC_GETTIMEOFDAY
+#ifdef __powerpc64__
+# define USE_IFUNC_GETTIMEOFDAY
+#endif
#include <sysdeps/unix/sysv/linux/gettimeofday.c>
diff --git a/sysdeps/unix/sysv/linux/x86/gettimeofday.c b/sysdeps/unix/sysv/linux/x86/gettimeofday.c
index 1b7aa880a2..0c1779dc83 100644
--- a/sysdeps/unix/sysv/linux/x86/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/x86/gettimeofday.c
@@ -16,5 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define USE_IFUNC_GETTIMEOFDAY
+#ifdef __x86_64__
+# define USE_IFUNC_GETTIMEOFDAY
+#endif
#include <sysdeps/unix/sysv/linux/gettimeofday.c>
--
2.20.1