This is the mail archive of the glibc-cvs@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]

GNU C Library master sources branch aaribaud/y2038 created. glibc-2.27.9000-616-g4281cfe


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, aaribaud/y2038 has been created
        at  4281cfe90e50c229498055a443a27d7fadd5d6c5 (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4281cfe90e50c229498055a443a27d7fadd5d6c5

commit 4281cfe90e50c229498055a443a27d7fadd5d6c5
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Sep 6 10:00:42 2017 +0200

    Y2038: add _TIME_BITS support
    
    This makes all previously defined Y2038-proof API types, functions and
    implementations the default when _TIME_BITS==64 and __WORDSIZE==32 (so
    that 64-bit architectures are unaffected).
    
    Note: it is assumed that the API is consistent, i.e. for each API type
    which is enabled here, all API functions which depend on this type are
    enabled and mapped to Y2038-proof implementations.

diff --git a/include/features.h b/include/features.h
index d22c32e..993cb21 100644
--- a/include/features.h
+++ b/include/features.h
@@ -364,6 +364,25 @@
 # define __USE_FILE_OFFSET64	1
 #endif
 
+/* we need to know the word size in order to check the time size */
+#include <bits/wordsize.h>
+
+#if defined _TIME_BITS
+# if _TIME_BITS == 64
+#  if ! defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
+#   error _TIME_BIT==64 is allowed only when _FILE_OFFSET_BITS==64
+#  elif __WORDSIZE == 32
+#   define __USE_TIME_BITS64	1
+#  endif
+# elif __TIME_BITS == 32
+#  if __WORDSIZE > 32
+#   error __TIME_BITS=32 is not compatible with __WORDSIZE > 32
+#  endif
+# else
+#  error Invalid _TIME_BITS value (can only be 32 or 64)
+# endif
+#endif
+
 #if defined _DEFAULT_SOURCE
 # define __USE_MISC	1
 #endif
diff --git a/io/sys/stat.h b/io/sys/stat.h
index cc05fe8..e778946 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -211,14 +211,27 @@ extern int stat (const char *__restrict __file,
 extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2));
 #else
 # ifdef __REDIRECT_NTH
+#  ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
+				  struct stat *__restrict __buf), __stat64_time64)
+     __nonnull ((1, 2));
+extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), __fstat64_time64)
+     __nonnull ((2));
+#  else
 extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
 				  struct stat *__restrict __buf), stat64)
      __nonnull ((1, 2));
 extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), fstat64)
      __nonnull ((2));
+#  endif
 # else
-#  define stat stat64
-#  define fstat fstat64
+#  ifdef __USE_TIME_BITS64
+#   define stat stat64_time64
+#   define fstat fstat64_time64
+#  else
+#   define stat stat64
+#   define fstat fstat64
+#  endif
 # endif
 #endif
 #ifdef __USE_LARGEFILE64
@@ -261,12 +274,23 @@ extern int lstat (const char *__restrict __file,
 		  struct stat *__restrict __buf) __THROW __nonnull ((1, 2));
 # else
 #  ifdef __REDIRECT_NTH
+#   ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (lstat,
+			   (const char *__restrict __file,
+			    struct stat *__restrict __buf), __lstat64_time64)
+     __nonnull ((1, 2));
+#   else
 extern int __REDIRECT_NTH (lstat,
 			   (const char *__restrict __file,
 			    struct stat *__restrict __buf), lstat64)
      __nonnull ((1, 2));
+#   endif
 #  else
-#   define lstat lstat64
+#   ifdef __USE_TIME_BITS64
+#    define lstat __lstat64_time64
+#   else
+#    define lstat lstat64
+#   endif
 #  endif
 # endif
 # ifdef __USE_LARGEFILE64
@@ -358,6 +382,15 @@ extern int mkfifoat (int __fd, const char *__path, __mode_t __mode)
 #ifdef __USE_ATFILE
 /* Set file access and modification times relative to directory file
    descriptor.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utimensat, (int __fd, const char *__path,
+           const struct timespec __times[2], int __flags),
+           __utimensat64) __THROW __nonnull((2));
+# else
+# define utimensat __utimensat64
+# endif
+#endif
 extern int utimensat (int __fd, const char *__path,
 		      const struct timespec __times[2],
 		      int __flags)
@@ -366,6 +399,14 @@ extern int utimensat (int __fd, const char *__path,
 
 #ifdef __USE_XOPEN2K8
 /* Set file access and modification times of the file associated with FD.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (futimens, (int __fd, const struct timespec __times[2]),
+           __futimens64) __THROW;
+# else
+# define futimens __futimens64
+# endif
+#endif
 extern int futimens (int __fd, const struct timespec __times[2]) __THROW;
 #endif
 
@@ -404,6 +445,21 @@ extern int __fxstatat (int __ver, int __fildes, const char *__filename,
      __THROW __nonnull ((3, 4));
 #else
 # ifdef __REDIRECT_NTH
+#  ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
+				      struct stat *__stat_buf), __fxstat64_time64)
+     __nonnull ((3));
+extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
+				     struct stat *__stat_buf), __xstat64_time64)
+     __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
+				      struct stat *__stat_buf), __lxstat64_time64)
+     __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
+					const char *__filename,
+					struct stat *__stat_buf, int __flag),
+			   __fxstatat64_time64) __nonnull ((3, 4));
+#  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
      __nonnull ((3));
@@ -417,11 +473,18 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 					const char *__filename,
 					struct stat *__stat_buf, int __flag),
 			   __fxstatat64) __nonnull ((3, 4));
+#  endif
 
 # else
-#  define __fxstat __fxstat64
-#  define __xstat __xstat64
-#  define __lxstat __lxstat64
+#  ifdef __USE_TIME_BITS64
+#   define __fxstat __fxstat64_time64
+#   define __xstat __xstat64_time64
+#   define __lxstat __lxstat64_time64
+#  else
+#   define __fxstat __fxstat64
+#   define __xstat __xstat64
+#   define __lxstat __lxstat64
+#  endif
 # endif
 #endif
 
diff --git a/io/utime.h b/io/utime.h
index 8409ba4..0068e2f 100644
--- a/io/utime.h
+++ b/io/utime.h
@@ -27,20 +27,30 @@
 __BEGIN_DECLS
 
 #include <bits/types.h>
+#include <bits/types/time_t.h>
 
 #if defined __USE_XOPEN || defined __USE_XOPEN2K
 # include <bits/types/time_t.h>
 #endif
 
-/* Structure describing file times.  */
+/* Structure describing file times, 32- or 64-bit time.  */
 struct utimbuf
   {
-    __time_t actime;		/* Access time.  */
-    __time_t modtime;		/* Modification time.  */
+    time_t actime;		/* Access time.  */
+    time_t modtime;		/* Modification time.  */
   };
 
 /* Set the access and modification times of FILE to those given in
    *FILE_TIMES.  If FILE_TIMES is NULL, set them to the current time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utime, (const char *__file,
+     const struct utimbuf *__file_times),
+     __utime64) __THROW __nonnull ((1));
+# else
+# define utime __utime64
+# endif
+#endif
 extern int utime (const char *__file,
 		  const struct utimbuf *__file_times)
      __THROW __nonnull ((1));
diff --git a/manual/creature.texi b/manual/creature.texi
index 8876b2a..10b7111 100644
--- a/manual/creature.texi
+++ b/manual/creature.texi
@@ -165,6 +165,34 @@ This macro was introduced as part of the Large File Support extension
 (LFS).
 @end defvr
 
+@defvr Macro _TIME_BITS
+This macro determines the bit size of @code{time_t} (and therefore the
+bit size of all @code{time_t} derived types and the prototypes of all
+related functions). If @code{_TIME_BITS} is undefined, the bit size of
+time_t equals the bit size of the architecture.
+
+If @code{_TIME_BITS} is undefined, or if @code{_TIME_BITS} is defined
+to the value @code{32} and @code{__WORDSIZE} is defined to the value
+@code{32}, or or if @code{_TIME_BITS} is defined to the value @code{64}
+and @code{__WORDSIZE} is defined to the value @code{64}, nothing changes.
+
+If @code{_TIME_BITS} is defined to the value @code{64} and if
+@code{__WORDSIZE} is defined to the value @code{32}, then the @w{64 bit}
+time API and implementation are used even though the architecture word
+size is @code{32}. Also, if the kernel provides @w{64 bit} time support,
+it is used; otherwise, the @w{32 bit} kernel time support is used (with
+no provision to address kernel Y2038 shortcomings).
+
+If @code{_TIME_BITS} is defined to the value @code{32} and if
+@code{__WORDSIZE} is defined to the value @code{64}, then a compile-time
+error is emitted.
+
+If @code{_TIME_BITS} is defined to a value different from both @code{32}
+and @code{64}, then a compile-time error is emitted.
+
+This macro was introduced as part of the Y2038 support.
+@end defvr
+
 @defvr Macro _ISOC99_SOURCE
 @standards{GNU, (none)}
 If this macro is defined, features from ISO C99 are included.  Since
diff --git a/misc/sys/select.h b/misc/sys/select.h
index 060e7f4..d289175 100644
--- a/misc/sys/select.h
+++ b/misc/sys/select.h
@@ -100,6 +100,18 @@ __BEGIN_DECLS
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (select, (int __nfds,
+                                fd_set *__restrict __readfds,
+                                fd_set *__restrict __writefds,
+                                fd_set *__restrict __exceptfds,
+                                struct timeval *__restrict __timeout),
+                       __select64);
+# else
+# define select __select64
+# endif
+#endif
 extern int select (int __nfds, fd_set *__restrict __readfds,
 		   fd_set *__restrict __writefds,
 		   fd_set *__restrict __exceptfds,
@@ -112,6 +124,19 @@ extern int select (int __nfds, fd_set *__restrict __readfds,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (pselect, (int __nfds,
+                                 fd_set *__restrict __readfds,
+                                 fd_set *__restrict __writefds,
+                                 fd_set *__restrict __exceptfds,
+                                 const struct timespec *__restrict __timeout,
+                                 const __sigset_t *__restrict __sigmask),
+                       __pselect64);
+# else
+# define pselect __pselect64
+# endif
+#endif
 extern int pselect (int __nfds, fd_set *__restrict __readfds,
 		    fd_set *__restrict __writefds,
 		    fd_set *__restrict __exceptfds,
diff --git a/posix/sched.h b/posix/sched.h
index 732c12b..3ed9713 100644
--- a/posix/sched.h
+++ b/posix/sched.h
@@ -75,6 +75,15 @@ extern int sched_get_priority_max (int __algorithm) __THROW;
 extern int sched_get_priority_min (int __algorithm) __THROW;
 
 /* Get the SCHED_RR interval for the named process.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (sched_rr_get_interval,
+                       (__pid_t __pid, struct timespec *__t),
+                       __sched_rr_get_interval_time64) __THROW;
+# else
+# define sched_rr_get_interval __sched_rr_get_interval_time64
+# endif
+#endif
 extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW;
 
 
diff --git a/resource/sys/resource.h b/resource/sys/resource.h
index 881db39..5363adf 100644
--- a/resource/sys/resource.h
+++ b/resource/sys/resource.h
@@ -84,6 +84,15 @@ extern int setrlimit64 (__rlimit_resource_t __resource,
 
 /* Return resource usage information on process indicated by WHO
    and put it in *USAGE.  Returns 0 for success, -1 for failure.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (getrusage, (__rusage_who_t __who,
+				   struct rusage *__usage),
+     __getrusage64) __THROW;
+# else
+# define getrusage __getrusage64
+# endif
+#endif
 extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __THROW;
 
 /* Return the highest priority of any process specified by WHICH and WHO
diff --git a/rt/mqueue.h b/rt/mqueue.h
index 39e2a24..051c730 100644
--- a/rt/mqueue.h
+++ b/rt/mqueue.h
@@ -74,6 +74,17 @@ extern int mq_send (mqd_t __mqdes, const char *__msg_ptr, size_t __msg_len,
 #ifdef __USE_XOPEN2K
 /* Receive the oldest from highest priority messages in message queue
    MQDES, stop waiting if ABS_TIMEOUT expires.  */
+# ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern ssize_t __REDIRECT (mq_timedreceive, (mqd_t __mqdes,
+                           char *__restrict __msg_ptr, size_t __msg_len,
+                           unsigned int *__restrict __msg_prio,
+                           const struct timespec *__restrict __abs_timeout),
+     __mq_timedreceive64) __nonnull((2, 5));
+#  else
+#   define mq_timedreceive __mq_timedreceive64
+#  endif
+# endif
 extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr,
 				size_t __msg_len,
 				unsigned int *__restrict __msg_prio,
@@ -82,6 +93,17 @@ extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr,
 
 /* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
    on full message queue if ABS_TIMEOUT expires.  */
+# ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern int __REDIRECT (mq_timedsend, (mqd_t __mqdes,
+                       const char *__msg_ptr, size_t __msg_len,
+                       unsigned int __msg_prio,
+                       const struct timespec *__abs_timeout),
+     __mq_timedsend64) __nonnull((2, 5));
+#  else
+#   define mq_timedsend __mq_timedsend64
+#  endif
+# endif
 extern int mq_timedsend (mqd_t __mqdes, const char *__msg_ptr,
 			 size_t __msg_len, unsigned int __msg_prio,
 			 const struct timespec *__abs_timeout)
diff --git a/signal/signal.h b/signal/signal.h
index caa2915..9596184 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -267,6 +267,16 @@ extern int sigwaitinfo (const sigset_t *__restrict __set,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (sigtimedwait, (const sigset_t *__restrict __set,
+			 siginfo_t *__restrict __info,
+			 const struct timespec *__restrict __timeout),
+     __sigtimedwait64) __nonnull ((1));
+# else
+# define sigtimedwait __sigtimedwait64
+# endif
+#endif
 extern int sigtimedwait (const sigset_t *__restrict __set,
 			 siginfo_t *__restrict __info,
 			 const struct timespec *__restrict __timeout)
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index 41b915e..59b4abe 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -766,6 +766,17 @@ extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
 
 #ifdef __USE_XOPEN2K
 /* Wait until lock becomes available, or specified time passes. */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (pthread_mutex_timedlock,
+		       (pthread_mutex_t *__restrict __mutex,
+			const struct timespec *__restrict __abstime),
+		       __pthread_mutex_timedlock64)
+	__THROWNL __nonnull ((1, 2));
+# else
+# define pthread_mutex_timedlock __pthread_mutex_timedlock64
+# endif
+#endif
 extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
 				    const struct timespec *__restrict
 				    __abstime) __THROWNL __nonnull ((1, 2));
@@ -905,6 +916,17 @@ extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
 
 # ifdef __USE_XOPEN2K
 /* Try to acquire read lock for RWLOCK or return after specfied time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (pthread_rwlock_timedrdlock,
+		       (pthread_rwlock_t *__restrict __rwlock,
+			const struct timespec *__restrict __abstime),
+		       __pthread_rwlock_timedrdlock64)
+	__THROWNL __nonnull ((1, 2));
+# else
+# define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock64
+# endif
+#endif
 extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
 				       const struct timespec *__restrict
 				       __abstime) __THROWNL __nonnull ((1, 2));
@@ -920,6 +942,17 @@ extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
 
 # ifdef __USE_XOPEN2K
 /* Try to acquire write lock for RWLOCK or return after specfied time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (pthread_rwlock_timedwrlock,
+		       (pthread_rwlock_t *__restrict __rwlock,
+			const struct timespec *__restrict __abstime),
+		       __pthread_rwlock_timedwrlock64)
+	__THROWNL __nonnull ((1, 2));
+# else
+# define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock64
+# endif
+#endif
 extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
 				       const struct timespec *__restrict
 				       __abstime) __THROWNL __nonnull ((1, 2));
@@ -999,6 +1032,18 @@ extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (pthread_cond_timedwait,
+		       (pthread_cond_t *__restrict __cond,
+			pthread_mutex_t *__restrict __mutex,
+			const struct timespec *__restrict __abstime),
+		       __pthread_cond_timedwait64)
+	__nonnull ((1, 2, 3));
+# else
+# define pthread_cond_timedwait __pthread_cond_timedwait64
+# endif
+#endif
 extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
 				   pthread_mutex_t *__restrict __mutex,
 				   const struct timespec *__restrict __abstime)
diff --git a/sysdeps/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
index 312433f..b286c06 100644
--- a/sysdeps/pthread/semaphore.h
+++ b/sysdeps/pthread/semaphore.h
@@ -58,6 +58,16 @@ extern int sem_wait (sem_t *__sem);
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (sem_timedwait,
+                               (sem_t *__restrict __sem,
+                                const struct timespec *__restrict __abstime),
+       __sem_timedwait64);
+# else
+# define sem_timedwait __sem_timedwait64
+# endif
+#endif
 extern int sem_timedwait (sem_t *__restrict __sem,
 			  const struct timespec *__restrict __abstime);
 #endif
diff --git a/sysdeps/unix/sysv/linux/bits/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
index 3195210..c3a12c0 100644
--- a/sysdeps/unix/sysv/linux/bits/msq.h
+++ b/sysdeps/unix/sysv/linux/bits/msq.h
@@ -35,6 +35,22 @@ typedef unsigned long int msglen_t;
 
 /* Structure of record for one message inside the kernel.
    The type `struct msg' is opaque.  */
+#ifdef __USE_TIME_BITS64
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  __time64_t msg_rtime;		/* time of last msgrcv command */
+  __time64_t msg_ctime;		/* time of last change */
+  unsigned long int __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  unsigned long int __glibc_reserved4;
+  unsigned long int __glibc_reserved5;
+};
+#else
 struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
@@ -52,6 +68,7 @@ struct msqid_ds
   unsigned long int __glibc_reserved4;
   unsigned long int __glibc_reserved5;
 };
+#endif
 
 #ifdef __USE_MISC
 
diff --git a/sysdeps/unix/sysv/linux/bits/stat.h b/sysdeps/unix/sysv/linux/bits/stat.h
index 48ef82d..fde673e 100644
--- a/sysdeps/unix/sysv/linux/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/bits/stat.h
@@ -119,11 +119,11 @@ struct stat64
     struct timespec st_mtim;		/* Time of last modification.  */
     struct timespec st_ctim;		/* Time of last status change.  */
 # else
-    __time_t st_atime;			/* Time of last access.  */
+    time_t st_atime;			/* Time of last access.  */
     unsigned long int st_atimensec;	/* Nscecs of last access.  */
-    __time_t st_mtime;			/* Time of last modification.  */
+    time_t st_mtime;			/* Time of last modification.  */
     unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
-    __time_t st_ctime;			/* Time of last status change.  */
+    time_t st_ctime;			/* Time of last status change.  */
     unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
 # endif
     __ino64_t st_ino;			/* File serial number.		*/
diff --git a/sysdeps/unix/sysv/linux/sys/timerfd.h b/sysdeps/unix/sysv/linux/sys/timerfd.h
index 37490cf..58d632e 100644
--- a/sysdeps/unix/sysv/linux/sys/timerfd.h
+++ b/sysdeps/unix/sysv/linux/sys/timerfd.h
@@ -44,11 +44,30 @@ extern int timerfd_create (__clockid_t __clock_id, int __flags) __THROW;
 /* Set next expiration time of interval timer source UFD to UTMR.  If
    FLAGS has the TFD_TIMER_ABSTIME flag set the timeout value is
    absolute.  Optionally return the old expiration time in OTMR.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timerfd_settime, (int __ufd, int __flags,
+                       const struct itimerspec *__utmr,
+                       struct itimerspec *__otmr),__timerfd_settime64)
+                       __THROW;
+# else
+# define timerfd_settime __timerfd_settime64
+# endif
+#endif
 extern int timerfd_settime (int __ufd, int __flags,
 			    const struct itimerspec *__utmr,
 			    struct itimerspec *__otmr) __THROW;
 
 /* Return the next expiration time of UFD.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timerfd_gettime, (int __ufd,
+                       struct itimerspec *__otmr),__timerfd_gettime64)
+                       __THROW;
+# else
+# define timerfd_gettime __timerfd_gettime64
+# endif
+#endif
 extern int timerfd_gettime (int __ufd, struct itimerspec *__otmr) __THROW;
 
 __END_DECLS
diff --git a/sysdeps/unix/sysv/linux/sys/timex.h b/sysdeps/unix/sysv/linux/sys/timex.h
index fd45929..d4ddb33 100644
--- a/sysdeps/unix/sysv/linux/sys/timex.h
+++ b/sysdeps/unix/sysv/linux/sys/timex.h
@@ -68,15 +68,43 @@ struct __ntptimeval64
 __BEGIN_DECLS
 
 extern int __adjtimex (struct timex *__ntx) __THROW;
+
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (adjtimex, (struct timex *__ntx),
+     __adjtimex64) __THROW;
+# else
+# define adjtimex __adjtimex64
+# endif
+#endif
 extern int adjtimex (struct timex *__ntx) __THROW;
 
-#ifdef __REDIRECT_NTH
+#if __WORDSIZE > 32 || ! defined(__USE_TIME_BITS64)
+# ifdef __REDIRECT_NTH
 extern int __REDIRECT_NTH (ntp_gettime, (struct ntptimeval *__ntv),
 			   ntp_gettimex);
-#else
+# else
 extern int ntp_gettimex (struct ntptimeval *__ntv) __THROW;
+#  define ntp_gettime ntp_gettimex
+# endif
+#else
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (ntp_gettimex, (struct ntptimeval *__ntv),
+                          __ntp_gettimex64) __THROW;
+# else
+# define ntp_gettimex __ntp_gettimex64
+# endif
 # define ntp_gettime ntp_gettimex
 #endif
+
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (ntp_adjtime, (struct timex *__tntx),
+                       __ntp_adjtime64) __THROW;
+# else
+# define ntp_adjtime __ntp_adjtime64
+# endif
+#endif
 extern int ntp_adjtime (struct timex *__tntx) __THROW;
 
 __END_DECLS
diff --git a/sysvipc/sys/msg.h b/sysvipc/sys/msg.h
index 1635839..92ea7ac 100644
--- a/sysvipc/sys/msg.h
+++ b/sysvipc/sys/msg.h
@@ -58,6 +58,15 @@ struct msgbuf
 __BEGIN_DECLS
 
 /* Message queue control operation.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (msgctl, (int __msqid, int __cmd,
+                       struct msqid_ds *__buf),
+                       __msgctl64) __THROW;
+# else
+# define msgctl __msgctl64
+# endif
+#endif
 extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) __THROW;
 
 /* Get messages queue.  */
diff --git a/time/bits/types/struct_itimerspec.h b/time/bits/types/struct_itimerspec.h
index d36295a..1e4ab51 100644
--- a/time/bits/types/struct_itimerspec.h
+++ b/time/bits/types/struct_itimerspec.h
@@ -5,11 +5,17 @@
 #include <bits/types/struct_timespec.h>
 #include <bits/types/struct_timespec64.h>
 
+/* Use the original definition for 64-bit arches
+   or when 64-bit-time by default has *not* been requested */ 
+#if __WORDSIZE > 32 || ! defined(__USE_TIME_BITS64)
 /* POSIX.1b structure for timer start values and intervals.  */
 struct itimerspec
   {
     struct timespec it_interval;
     struct timespec it_value;
   };
+#else
+# define itimerspec __itimerspec64
+#endif
 
 #endif
diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h
index 5b77c52..f93557f 100644
--- a/time/bits/types/struct_timespec.h
+++ b/time/bits/types/struct_timespec.h
@@ -4,6 +4,9 @@
 
 #include <bits/types.h>
 
+/* Use the original definition for 64-bit arches
+   or when 64-bit-time by default has *not* been requested */ 
+#if __WORDSIZE > 32 || ! defined(__USE_TIME_BITS64)
 /* POSIX.1b structure for a time value.  This is like a `struct timeval' but
    has nanoseconds instead of microseconds.  */
 struct timespec
@@ -11,5 +14,9 @@ struct timespec
   __time_t tv_sec;		/* Seconds.  */
   __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
 };
+#else
+/* Use the 64-bit-time timespec by default */
+#define timespec __timespec64
+# endif
 
 #endif
diff --git a/time/bits/types/struct_timeval.h b/time/bits/types/struct_timeval.h
index 70394ce..e710b37 100644
--- a/time/bits/types/struct_timeval.h
+++ b/time/bits/types/struct_timeval.h
@@ -3,6 +3,9 @@
 
 #include <bits/types.h>
 
+/* Use the original definition for 64-bit arches
+   or when 64-bit-time by default has *not* been requested */ 
+# if __WORDSIZE > 32 || ! defined(__USE_TIME_BITS64)
 /* A time value that is accurate to the nearest
    microsecond but also has a range of years.  */
 struct timeval
@@ -10,4 +13,9 @@ struct timeval
   __time_t tv_sec;		/* Seconds.  */
   __suseconds_t tv_usec;	/* Microseconds.  */
 };
+# else
+/* Use the 64-bit-time timespec by default */
+# define timeval __timeval64
+# endif
+
 #endif
diff --git a/time/bits/types/time_t.h b/time/bits/types/time_t.h
index ab8287c..84d67f6 100644
--- a/time/bits/types/time_t.h
+++ b/time/bits/types/time_t.h
@@ -4,6 +4,10 @@
 #include <bits/types.h>
 
 /* Returned by `time'.  */
+#ifdef __USE_TIME_BITS64
+typedef __time64_t time_t;
+#else
 typedef __time_t time_t;
+#endif
 
 #endif
diff --git a/time/sys/time.h b/time/sys/time.h
index b7fe339..01ac9b6 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -66,12 +66,31 @@ typedef void *__restrict __timezone_ptr_t;
    Returns 0 on success, -1 on errors.
    NOTE: This form of timezone information is obsolete.
    Use the functions and variables declared in <time.h> instead.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (gettimeofday, (struct timeval *__restrict __tv,
+                                   __timezone_ptr_t __tz),
+                    __gettimeofday64) __THROW __nonnull((1));
+# else
+# define gettimeofday __gettimeofday64
+# endif
+#endif
 extern int gettimeofday (struct timeval *__restrict __tv,
 			 __timezone_ptr_t __tz) __THROW __nonnull ((1));
 
 #ifdef __USE_MISC
 /* Set the current time of day and timezone information.
    This call is restricted to the super-user.  */
+#ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern int __REDIRECT (settimeofday,
+                       (const struct timeval *__tv,
+                        const struct timezone *__tz),
+                    __settimeofday64) __THROW;
+#  else
+#   define settimeofday __settimeofday64
+#  endif
+# endif
 extern int settimeofday (const struct timeval *__tv,
 			 const struct timezone *__tz)
      __THROW;
@@ -80,6 +99,16 @@ extern int settimeofday (const struct timeval *__tv,
    If OLDDELTA is not NULL, it is filled in with the amount
    of time adjustment remaining to be done from the last `adjtime' call.
    This call is restricted to the super-user.  */
+#ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern int __REDIRECT (adjtime,
+                       (const struct timeval *__delta,
+                        struct timeval *__olddelta),
+                    __adjtime64) __THROW;
+#  else
+#   define adjtime __adjtime64
+#  endif
+# endif
 extern int adjtime (const struct timeval *__delta,
 		    struct timeval *__olddelta) __THROW;
 #endif
@@ -130,12 +159,31 @@ typedef int __itimer_which_t;
 
 /* Set *VALUE to the current setting of timer WHICH.
    Return 0 on success, -1 on errors.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (getitimer, (__itimer_which_t __which,
+       struct itimerval *__value), __getitimer64)
+       __THROW;
+# else
+# define getitimer __getitimer64
+# endif
+#endif
 extern int getitimer (__itimer_which_t __which,
 		      struct itimerval *__value) __THROW;
 
 /* Set the timer WHICH to *NEW.  If OLD is not NULL,
    set *OLD to the old value of timer WHICH.
    Returns 0 on success, -1 on errors.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (setitimer, (__itimer_which_t __which,
+       const struct itimerval *__restrict __new,
+       struct itimerval *__restrict __old), __setitimer64)
+       __THROW;
+# else
+# define setitimer __setitimer64
+# endif
+#endif
 extern int setitimer (__itimer_which_t __which,
 		      const struct itimerval *__restrict __new,
 		      struct itimerval *__restrict __old) __THROW;
@@ -143,15 +191,41 @@ extern int setitimer (__itimer_which_t __which,
 /* Change the access time of FILE to TVP[0] and the modification time of
    FILE to TVP[1].  If TVP is a null pointer, use the current time instead.
    Returns 0 on success, -1 on errors.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utimes, (const char *__file,
+       const struct timeval __tvp[2]), __utimes64)
+       __THROW __nonnull ((1));
+# else
+# define utimes __utimes64
+# endif
+#endif
 extern int utimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 
 #ifdef __USE_MISC
 /* Same as `utimes', but does not follow symbolic links.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (lutimes, (const char *__file,
+       const struct timeval __tvp[2]), __lutimes64)
+       __THROW __nonnull ((1));
+# else
+# define lutimes __lutimes64
+# endif
+#endif
 extern int lutimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 
 /* Same as `utimes', but takes an open file descriptor instead of a name.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (futimes, (int __fd, const struct timeval __tvp[2]),
+     __futimes64) __THROW;
+# else
+# define futimes __futimes64
+# endif
+#endif
 extern int futimes (int __fd, const struct timeval __tvp[2]) __THROW;
 #endif
 
diff --git a/time/time.h b/time/time.h
index dcc275a..9471c6e 100644
--- a/time/time.h
+++ b/time/time.h
@@ -74,16 +74,38 @@ __BEGIN_DECLS
 extern clock_t clock (void) __THROW;
 
 /* Return the current time and put it in *TIMER if TIMER is not NULL.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (time, (time_t * __timer),
+     __time64) __THROW;
+# else
+# define time __time64
+# endif
+#endif
 extern time_t time (time_t *__timer) __THROW;
 
 /* Return the difference between TIME1 and TIME0.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern double __REDIRECT (difftime, (time_t __time1, time_t __time0),
+     __difftime64) __THROW;
+# else
+# define difftime __difftime64
+# endif
+#endif
 extern double difftime (time_t __time1, time_t __time0)
      __THROW __attribute__ ((__const__));
 
 /* Return the `time_t' representation of TP and normalize TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (mktime, (struct tm *__tp), __mktime64) __THROW;
+# else
+# define mktime __mktime64
+# endif
+#endif
 extern time_t mktime (struct tm *__tp) __THROW;
 
-
 /* Format TP into S according to FORMAT.
    Write no more than MAXSIZE characters and return the number
    of characters written, or 0 if it would exceed MAXSIZE.  */
@@ -118,20 +140,52 @@ extern char *strptime_l (const char *__restrict __s,
 
 /* Return the `struct tm' representation of *TIMER
    in Universal Coordinated Time (aka Greenwich Mean Time).  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (gmtime, (const time_t *__timer),
+       __gmtime64) __THROW;
+# else
+# define gmtime __gmtime64
+# endif
+#endif
 extern struct tm *gmtime (const time_t *__timer) __THROW;
 
 /* Return the `struct tm' representation
    of *TIMER in the local timezone.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (localtime, (const time_t *__timer),
+       __localtime64) __THROW;
+# else
+# define localtime __localtime64
+# endif
+#endif
 extern struct tm *localtime (const time_t *__timer) __THROW;
 
 #ifdef __USE_POSIX
 /* Return the `struct tm' representation of *TIMER in UTC,
    using *TP to store the result.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (gmtime_r, (const time_t *__restrict
+       __timer, struct tm *__restrict __tp), __gmtime64_r) __THROW;
+# else
+# define gmtime_r __gmtime64_r
+# endif
+#endif
 extern struct tm *gmtime_r (const time_t *__restrict __timer,
 			    struct tm *__restrict __tp) __THROW;
 
 /* Return the `struct tm' representation of *TIMER in local time,
    using *TP to store the result.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (localtime_r, (const time_t *__restrict
+       __timer, struct tm *__restrict __tp), __localtime64_r) __THROW;
+# else
+# define localtime_r __localtime64_r
+# endif
+#endif
 extern struct tm *localtime_r (const time_t *__restrict __timer,
 			       struct tm *__restrict __tp) __THROW;
 #endif	/* POSIX */
@@ -141,6 +195,14 @@ extern struct tm *localtime_r (const time_t *__restrict __timer,
 extern char *asctime (const struct tm *__tp) __THROW;
 
 /* Equivalent to `asctime (localtime (timer))'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern char * __REDIRECT (ctime, (const time_t *__timer),
+       __ctime64) __THROW;
+# else
+# define ctime __ctime64
+# endif
+#endif
 extern char *ctime (const time_t *__timer) __THROW;
 
 #ifdef __USE_POSIX
@@ -152,6 +214,14 @@ extern char *asctime_r (const struct tm *__restrict __tp,
 			char *__restrict __buf) __THROW;
 
 /* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern char * __REDIRECT (ctime_r, (const time_t *__restrict __timer,
+       char *__restrict __buf), __ctime64_r) __THROW;
+# else
+# define ctime_r __ctime64_r
+# endif
+#endif
 extern char *ctime_r (const time_t *__restrict __timer,
 		      char *__restrict __buf) __THROW;
 #endif	/* POSIX */
@@ -180,6 +250,14 @@ extern long int timezone;
 #ifdef __USE_MISC
 /* Set the system time to *WHEN.
    This call is restricted to the superuser.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (stime, (const time_t *__when), __stime64)
+           __THROW;
+# else
+# define stime __stime64
+# endif
+#endif
 extern int stime (const time_t *__when) __THROW;
 #endif
 
@@ -195,9 +273,23 @@ extern int stime (const time_t *__when) __THROW;
    localtime package.  These are included only for compatibility.  */
 
 /* Like `mktime', but for TP represents Universal Time, not local time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (timegm, (struct tm *__tp), __timegm64) __THROW;
+# else
+# define timegm __timegm64
+# endif
+#endif
 extern time_t timegm (struct tm *__tp) __THROW;
 
 /* Another name for `mktime'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (timelocal, (struct tm *__tp), __timelocal64) __THROW;
+# else
+# define timelocal __timelocal64
+# endif
+#endif
 extern time_t timelocal (struct tm *__tp) __THROW;
 
 /* Return the number of days in YEAR.  */
@@ -210,17 +302,49 @@ extern int dysize (int __year) __THROW  __attribute__ ((__const__));
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (nanosleep, (const struct timespec *__requested_time,
+		      struct timespec *__remaining), __nanosleep64);
+# else
+# define nanosleep __nanosleep64
+# endif
+#endif
 extern int nanosleep (const struct timespec *__requested_time,
 		      struct timespec *__remaining);
 
 
 /* Get resolution of clock CLOCK_ID.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_getres, (clockid_t __clock_id, struct
+     timespec *__res), __clock_getres64) __THROW;
+# else
+# define clock_getres __clock_getres64
+# endif
+#endif
 extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __THROW;
 
 /* Get current value of clock CLOCK_ID and store it in TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_gettime, (clockid_t __clock_id, struct
+     timespec *__tp), __clock_gettime64) __THROW;
+# else
+# define clock_gettime __clock_gettime64
+# endif
+#endif
 extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
 
 /* Set clock CLOCK_ID to value TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_settime, (clockid_t __clock_id, const struct
+     timespec *__tp), __clock_settime64) __THROW;
+# else
+# define clock_settime __clock_settime64
+# endif
+#endif
 extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
      __THROW;
 
@@ -229,6 +353,15 @@ extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_nanosleep, (clockid_t __clock_id, int __flags,
+     const struct timespec *__req, struct timespec *__rem),
+     __clock_nanosleep64) __THROW;
+# else
+# define clock_nanosleep __clock_nanosleep64
+# endif
+#endif
 extern int clock_nanosleep (clockid_t __clock_id, int __flags,
 			    const struct timespec *__req,
 			    struct timespec *__rem);
@@ -247,11 +380,29 @@ extern int timer_create (clockid_t __clock_id,
 extern int timer_delete (timer_t __timerid) __THROW;
 
 /* Set timer TIMERID to VALUE, returning old value in OVALUE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timer_settime, (timer_t __timerid, int __flags,
+			  const struct itimerspec *__restrict __value,
+			  struct itimerspec *__restrict __ovalue),
+                          __timer_settime64) __THROW;
+# else
+# define timer_settime __timer_settime64
+# endif
+#endif
 extern int timer_settime (timer_t __timerid, int __flags,
 			  const struct itimerspec *__restrict __value,
 			  struct itimerspec *__restrict __ovalue) __THROW;
 
 /* Get current value of timer TIMERID and store it in VALUE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timer_gettime, (timer_t __timerid, struct
+     itimerspec *__value), __timer_gettime64) __THROW __nonnull ((1));
+# else
+# define timer_gettime __timer_gettime64
+# endif
+#endif
 extern int timer_gettime (timer_t __timerid, struct itimerspec *__value)
      __THROW;
 
@@ -262,6 +413,14 @@ extern int timer_getoverrun (timer_t __timerid) __THROW;
 
 #ifdef __USE_ISOC11
 /* Set TS to calendar time based in time base BASE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timespec_get, (struct timespec *__ts, int __base),
+     __timespec_get64) __THROW __nonnull ((1));
+# else
+# define timespec_get __timespec_get64
+# endif
+#endif
 extern int timespec_get (struct timespec *__ts, int __base)
      __THROW __nonnull ((1));
 #endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e45fae916048390fc80eee012fa463f8731f2840

commit e45fae916048390fc80eee012fa463f8731f2840
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Thu Apr 12 20:50:21 2018 +0200

    Y2038: add function __pmap_rmtcall64

diff --git a/sunrpc/pmap_rmt.c b/sunrpc/pmap_rmt.c
index 6b142e5..501da4f 100644
--- a/sunrpc/pmap_rmt.c
+++ b/sunrpc/pmap_rmt.c
@@ -390,3 +390,26 @@ done_broad:
   return stat;
 }
 libc_hidden_nolink_sunrpc (clnt_broadcast, GLIBC_2_0)
+
+/* 64-bit-time version */
+
+/* The 64-bit-time version of pmap_rmtcall.
+ * Only handles 64-bit-time timeouts smaller than 2^^31 seconds.
+ */
+enum clnt_stat
+__pmap_rmtcall64 (struct sockaddr_in *addr, u_long prog, u_long vers,
+		  u_long proc, xdrproc_t xdrargs, caddr_t argsp,
+		  xdrproc_t xdrres, caddr_t resp,
+		  struct __timeval64 tout, u_long *port_ptr)
+{
+  struct timeval tout32;
+  if (tout.tv_sec > INT_MAX)
+  {
+    return RPC_SYSTEMERROR;
+  }
+  tout32.tv_sec = tout.tv_sec;
+  tout32.tv_usec = tout.tv_usec;
+  
+  return pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres,
+                       resp, tout32, port_ptr);
+}
diff --git a/sunrpc/rpc/pmap_clnt.h b/sunrpc/rpc/pmap_clnt.h
index 1cc94b8..b436ebb 100644
--- a/sunrpc/rpc/pmap_clnt.h
+++ b/sunrpc/rpc/pmap_clnt.h
@@ -71,6 +71,21 @@ extern bool_t pmap_set (const u_long __program, const u_long __vers,
 extern bool_t pmap_unset (const u_long __program, const u_long __vers)
      __THROW;
 extern struct pmaplist *pmap_getmaps (struct sockaddr_in *__address) __THROW;
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern enum clnt_stat __REDIRECT (pmap_rmtcall, (struct sockaddr_in *__addr,
+                                                 const u_long __prog,
+                                                 const u_long __vers,
+                                                 const u_long __proc,
+                                                 xdrproc_t __xdrargs,
+                                                 caddr_t __argsp, xdrproc_t __xdrres,
+                                                 caddr_t __resp, struct timeval __tout,
+                                                 u_long *__port_ptr),
+                                  __pmap_rmtcall64) __THROW;
+# else
+# define pmap_rmtcall __pmap_rmtcall64
+# endif
+#endif
 extern enum clnt_stat pmap_rmtcall (struct sockaddr_in *__addr,
 				    const u_long __prog,
 				    const u_long __vers,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5e5516cb861cf691fc0839b6768d3228f8bef79e

commit 5e5516cb861cf691fc0839b6768d3228f8bef79e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Thu Apr 12 20:49:49 2018 +0200

    Y2038: add function __clntudp_bufcreate64

diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index 27a3244..0892ae3 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -663,3 +663,21 @@ __clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
 
   return clntudp_create (raddr, program, version, wait32, sockp);
 }
+
+CLIENT *
+__clntudp_bufcreate64 (struct sockaddr_in *raddr, u_long program, u_long version,
+		       struct __timeval64 wait, int *sockp, u_int sendsz,
+		       u_int recvsz)
+{
+  struct timeval wait32;
+
+  if (wait.tv_sec > INT_MAX)
+  {
+    return NULL;
+  }
+
+  wait32.tv_sec = wait.tv_sec;
+  wait32.tv_usec = wait.tv_usec;
+
+  return clntudp_bufcreate (raddr, program, version, wait32, sockp, sendsz, recvsz);
+}
diff --git a/sunrpc/rpc/clnt.h b/sunrpc/rpc/clnt.h
index b24b5cc..a6dff89 100644
--- a/sunrpc/rpc/clnt.h
+++ b/sunrpc/rpc/clnt.h
@@ -344,6 +344,18 @@ extern CLIENT * __REDIRECT (clntudp_create,(struct sockaddr_in *__raddr,
 extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program,
 			       u_long __version, struct timeval __wait_resend,
 			       int *__sockp) __THROW;
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern CLIENT * __REDIRECT (clntudp_bufcreate,(struct sockaddr_in *__raddr,
+				               u_long __program, u_long __version,
+				               struct __timeval64 __wait_resend,
+					       int *__sockp, u_int __sendsz,
+					       u_int __recvsz),
+                            __clntudp_bufcreate64) __THROW;
+# else
+# define clntudp_bufcreate __clntudp_bufcreate64
+# endif
+#endif
 extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr,
 				  u_long __program, u_long __version,
 				  struct timeval __wait_resend, int *__sockp,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3442707c7e90348f9f24659e697a58fc4c782a60

commit 3442707c7e90348f9f24659e697a58fc4c782a60
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Thu Apr 12 20:46:27 2018 +0200

    Y2038: add function __clntudp_create64

diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index c2436e3..27a3244 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -644,3 +644,22 @@ clntudp_destroy (CLIENT *cl)
   mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
   mem_free ((caddr_t) cl, sizeof (CLIENT));
 }
+
+/* 64-bit time versions */
+
+CLIENT *
+__clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
+		    struct __timeval64 wait, int *sockp)
+{
+  struct timeval wait32;
+
+  if (wait.tv_sec > INT32_MAX || wait.tv_sec < INT32_MIN)
+  {
+    return NULL;
+  }  
+
+  wait32.tv_sec = wait.tv_sec;
+  wait32.tv_usec = wait.tv_usec;
+
+  return clntudp_create (raddr, program, version, wait32, sockp);
+}
diff --git a/sunrpc/rpc/clnt.h b/sunrpc/rpc/clnt.h
index f4d4a94..b24b5cc 100644
--- a/sunrpc/rpc/clnt.h
+++ b/sunrpc/rpc/clnt.h
@@ -329,6 +329,18 @@ extern CLIENT *clnttcp_create (struct sockaddr_in *__raddr, u_long __prog,
  *	u_int sendsz;
  *	u_int recvsz;
  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern CLIENT * __REDIRECT (clntudp_create,(struct sockaddr_in *__raddr,
+                                            u_long __program,
+					    u_long __version,
+					    struct timeval __wait_resend,
+					    int *__sockp),
+                            __clntudp_create64) __THROW;
+# else
+# define clntudp_create __clntudp_create64
+# endif
+#endif
 extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program,
 			       u_long __version, struct timeval __wait_resend,
 			       int *__sockp) __THROW;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=87f08be0870af0a083ec6cf4883d9a3dc6b2d076

commit 87f08be0870af0a083ec6cf4883d9a3dc6b2d076
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 19:49:07 2017 +0200

    Y2038: add function select64

diff --git a/include/sys/select.h b/include/sys/select.h
index ba013a3..9c58a15 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -22,5 +22,10 @@ extern int __pselect64 (int __nfds, fd_set *__readfds,
 			const struct __timespec64 *__timeout,
 			const __sigset_t *__sigmask);
 
+extern int __select64 (int __nfds, fd_set *__restrict __readfds,
+		       fd_set *__restrict __writefds,
+		       fd_set *__restrict __exceptfds,
+		       struct __timeval64 *__restrict __timeout);
+
 #endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
index e4124a1..ba17746 100644
--- a/sysdeps/unix/sysv/linux/select.c
+++ b/sysdeps/unix/sysv/linux/select.c
@@ -21,6 +21,7 @@
 #include <sys/select.h>
 #include <errno.h>
 #include <sysdep-cancel.h>
+#include <y2038-support.h>
 
 /* Check the first NFDS descriptors each in READFDS (if not NULL) for read
    readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
@@ -69,3 +70,73 @@ libc_hidden_def (__select)
 
 weak_alias (__select, select)
 weak_alias (__select, __libc_select)
+
+/* 64-bit time version */
+
+int
+__select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+	      struct __timeval64 *timeout)
+{
+#ifdef __NR_select
+  struct timeval tval32, *timeout32 = NULL;
+#else
+  int result;
+  struct timespec ts32, *tsp32 = NULL;
+#endif
+
+#ifdef __NR_pselect6_time64
+  int res;
+  if (__y2038_linux_support > 0)
+  {
+    res = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds,
+			  exceptfds, timeout, NULL);
+    if (res == 0 || errno != ENOSYS)
+      return res;
+    __y2038_linux_support = -1;
+  }
+#endif
+
+#ifdef __NR_select
+  if (timeout != NULL)
+    {
+      if (timeout->tv_sec > INT_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      tval32.tv_sec = timeout->tv_sec;
+      tval32.tv_usec = timeout->tv_usec;
+      timeout32 = &tval32;
+    }
+
+  return SYSCALL_CANCEL (select, nfds, readfds, writefds, exceptfds,
+			 timeout32);
+#else
+  if (timeout)
+    {
+      if (timeout->tv_sec > INT_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      ts32.tv_sec = timeout->tv_sec;
+      ts32.tv_nsec = timeout->tv_usec * 1000;
+      tsp32 = &ts32;
+    }
+
+  result = SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds, tsp32,
+			   NULL);
+
+  if (timeout)
+    {
+      /* Linux by default will update the timeout after a pselect6 syscall
+         (though the pselect() glibc call suppresses this behavior).
+         Since select() on Linux has the same behavior as the pselect6
+         syscall, we update the timeout here.  */
+      timeout->tv_sec = ts32.tv_sec;
+      timeout->tv_usec = ts32.tv_nsec / 1000;
+    }
+
+  return result;
+#endif
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=765feb09dcfb73274d874b5fa901d292bd4b6137

commit 765feb09dcfb73274d874b5fa901d292bd4b6137
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:16 2017 +0200

    Y2038: add function pselect64

diff --git a/include/sys/select.h b/include/sys/select.h
index 07bb49b..ba013a3 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -3,6 +3,7 @@
 
 #ifndef _ISOMAC
 /* Now define the internal interfaces.  */
+
 extern int __pselect (int __nfds, fd_set *__readfds,
 		      fd_set *__writefds, fd_set *__exceptfds,
 		      const struct timespec *__timeout,
@@ -14,5 +15,12 @@ extern int __select (int __nfds, fd_set *__restrict __readfds,
 		     struct timeval *__restrict __timeout);
 libc_hidden_proto (__select)
 
+/* 64-bit time version */
+
+extern int __pselect64 (int __nfds, fd_set *__readfds,
+			fd_set *__writefds, fd_set *__exceptfds,
+			const struct __timespec64 *__timeout,
+			const __sigset_t *__sigmask);
+
 #endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index 2b052e7..8a77036 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -22,6 +22,7 @@
 #include <sys/poll.h>
 #include <kernel-features.h>
 #include <sysdep-cancel.h>
+#include <y2038-support.h>
 
 
 #ifdef __NR_pselect6
@@ -79,6 +80,71 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 }
 weak_alias (__pselect, pselect)
 
+/* 64-bit time version */
+
+int
+__pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+	       const struct __timespec64 *timeout, const sigset_t *sigmask)
+{
+  struct timespec tval32, *timeout32 = NULL;
+
+  /* Note: the system call expects 7 values but on most architectures
+     we can only pass in 6 directly.  If there is an architecture with
+     support for more parameters a new version of this file needs to
+     be created.  */
+  struct
+  {
+    __syscall_ulong_t ss;
+    __syscall_ulong_t ss_len;
+  } data;
+
+  data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
+  data.ss_len = _NSIG / 8;
+
+  int result;
+
+#ifdef __NR_pselect6_time64
+  if (__y2038_linux_support > 0)
+  {
+    result = SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds,
+			     exceptfds, timeout, &data);
+    if (result == 0 || errno != ENOSYS)
+      return result;
+    __y2038_linux_support = -1;
+  }
+#endif
+
+  /* The Linux kernel can in some situations update the timeout value.
+     We do not want that so use a local variable.  */
+  if (timeout != NULL)
+    {
+      if (timeout->tv_sec > INT_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      tval32.tv_sec = timeout->tv_sec;
+      tval32.tv_nsec = timeout->tv_nsec;
+      timeout32 = &tval32;
+    }
+
+#ifndef CALL_PSELECT6
+# define CALL_PSELECT6(nfds, readfds, writefds, exceptfds, timeout, data) \
+  SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds,	timeout32, data)
+#endif
+
+  result = CALL_PSELECT6 (nfds, readfds, writefds, exceptfds, timeout32,
+			  &data);
+
+# ifndef __ASSUME_PSELECT
+  if (result == -1 && errno == ENOSYS)
+    result = __generic_pselect (nfds, readfds, writefds, exceptfds, timeout32,
+				sigmask);
+# endif
+
+  return result;
+}
+
 # ifndef __ASSUME_PSELECT
 #  define __pselect static __generic_pselect
 # endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=49f34100c8451dab0806b9e64abe122efb4bbb1e

commit 49f34100c8451dab0806b9e64abe122efb4bbb1e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:15 2017 +0200

    Y2038: add struct __timex64

diff --git a/include/time.h b/include/time.h
index 564bfee..03afbfd 100644
--- a/include/time.h
+++ b/include/time.h
@@ -3,6 +3,7 @@
 
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
+# include <bits/types/struct_timeval64.h>
 # include <stdbool.h>
 
 extern __typeof (strftime_l) __strftime_l;
@@ -17,6 +18,37 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+/* 64-bit time version of the current struct timex */
+struct __timex64
+{
+  unsigned int modes;		/* mode selector */
+  __syscall_slong_t offset;	/* time offset (usec) */
+  __syscall_slong_t freq;	/* frequency offset (scaled ppm) */
+  __syscall_slong_t maxerror;	/* maximum error (usec) */
+  __syscall_slong_t esterror;	/* estimated error (usec) */
+  int status;			/* clock command/status */
+  __syscall_slong_t constant;	/* pll time constant */
+  __syscall_slong_t precision;	/* clock precision (usec) (ro) */
+  __syscall_slong_t tolerance;	/* clock frequency tolerance (ppm) (ro) */
+  struct __timeval64 time;	/* (read only, except for ADJ_SETOFFSET) */
+  __syscall_slong_t tick;	/* (modified) usecs between clock ticks */
+  __syscall_slong_t ppsfreq;	/* pps frequency (scaled ppm) (ro) */
+  __syscall_slong_t jitter;	/* pps jitter (us) (ro) */
+  int shift;			/* interval duration (s) (shift) (ro) */
+  __syscall_slong_t stabil;	/* pps stability (scaled ppm) (ro) */
+  __syscall_slong_t jitcnt;	/* jitter limit exceeded (ro) */
+  __syscall_slong_t calcnt;	/* calibration intervals (ro) */
+  __syscall_slong_t errcnt;	/* calibration errors (ro) */
+  __syscall_slong_t stbcnt;	/* stability limit exceeded (ro) */
+
+  int tai;			/* TAI offset (ro) */
+
+  /* ??? */
+  int  :32; int  :32; int  :32; int  :32;
+  int  :32; int  :32; int  :32; int  :32;
+  int  :32; int  :32; int  :32;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bcb098552e905e5d5311d6c7ae0c8325a918ac4d

commit bcb098552e905e5d5311d6c7ae0c8325a918ac4d
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:14 2017 +0200

    Y2038: add function __ntp_gettimex64

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 07a36e8..955d158 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -171,6 +171,7 @@ libc {
     mlock2;
     pkey_alloc; pkey_free; pkey_set; pkey_get; pkey_mprotect;
     __ntp_gettime64;
+    __ntp_gettimex64;
   }
   GLIBC_PRIVATE {
     # functions used in other libraries
diff --git a/sysdeps/unix/sysv/linux/ntp_gettimex.c b/sysdeps/unix/sysv/linux/ntp_gettimex.c
index e491549..abd1c7e 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettimex.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettimex.c
@@ -16,6 +16,7 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <sys/timex.h>
+#include <include/time.h>
 
 #ifndef MOD_OFFSET
 # define modes mode
@@ -40,3 +41,26 @@ ntp_gettimex (struct ntptimeval *ntv)
   ntv->__glibc_reserved4 = 0;
   return result;
 }
+
+/* The 64-bit-time version */
+
+int
+__ntp_gettimex64 (struct __ntptimeval64 *ntv)
+{
+  struct timex tntx;
+  int result;
+
+  tntx.modes = 0;
+  result = __adjtimex (&tntx);
+  ntv->time.tv_sec = tntx.time.tv_sec;
+  ntv->time.tv_usec = tntx.time.tv_usec;
+  ntv->maxerror = tntx.maxerror;
+  ntv->maxerror = tntx.maxerror;
+  ntv->esterror = tntx.esterror;
+  ntv->tai = tntx.tai;
+  ntv->__glibc_reserved1 = 0;
+  ntv->__glibc_reserved2 = 0;
+  ntv->__glibc_reserved3 = 0;
+  ntv->__glibc_reserved4 = 0;
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=acf56c97d60cfb8a134a801d3c917f7cddf29933

commit acf56c97d60cfb8a134a801d3c917f7cddf29933
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:13 2017 +0200

    Y2038: add function __ntp_gettime64

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 336c13b..07a36e8 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -170,6 +170,7 @@ libc {
     memfd_create;
     mlock2;
     pkey_alloc; pkey_free; pkey_set; pkey_get; pkey_mprotect;
+    __ntp_gettime64;
   }
   GLIBC_PRIVATE {
     # functions used in other libraries
diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c b/sysdeps/unix/sysv/linux/ntp_gettime.c
index 18650da..f025263 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettime.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettime.c
@@ -18,6 +18,7 @@
 #define ntp_gettime ntp_gettime_redirect
 
 #include <sys/timex.h>
+#include <include/time.h>
 
 #undef ntp_gettime
 
@@ -39,3 +40,20 @@ ntp_gettime (struct ntptimeval *ntv)
   ntv->esterror = tntx.esterror;
   return result;
 }
+
+/* The 64-bit-time version */
+
+int
+__ntp_gettime64 (struct __ntptimeval64 *ntv)
+{
+  struct timex tntx;
+  int result;
+
+  tntx.modes = 0;
+  result = __adjtimex (&tntx);
+  ntv->time.tv_sec = tntx.time.tv_sec;
+  ntv->time.tv_usec = tntx.time.tv_usec;
+  ntv->maxerror = tntx.maxerror;
+  ntv->esterror = tntx.esterror;
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d4a39f9462a69ef2e8116fe1195506094719eb0b

commit d4a39f9462a69ef2e8116fe1195506094719eb0b
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:12 2017 +0200

    Y2038: add struct __ntp_timeval64

diff --git a/sysdeps/unix/sysv/linux/sys/timex.h b/sysdeps/unix/sysv/linux/sys/timex.h
index 0d652c8..fd45929 100644
--- a/sysdeps/unix/sysv/linux/sys/timex.h
+++ b/sysdeps/unix/sysv/linux/sys/timex.h
@@ -40,6 +40,19 @@ struct ntptimeval
   long int __glibc_reserved4;
 };
 
+struct __ntptimeval64
+{
+  struct __timeval64 time;	/* current time (ro) */
+  long int maxerror;	/* maximum error (us) (ro) */
+  long int esterror;	/* estimated error (us) (ro) */
+  long int tai;		/* TAI offset (ro) */
+
+  long int __glibc_reserved1;
+  long int __glibc_reserved2;
+  long int __glibc_reserved3;
+  long int __glibc_reserved4;
+};
+
 /* Clock states (time_state) */
 #define TIME_OK		0	/* clock synchronized, no leap second */
 #define TIME_INS	1	/* insert leap second */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d54109f35b6177b8287a1701dc7647920048abdd

commit d54109f35b6177b8287a1701dc7647920048abdd
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:11 2017 +0200

    Y2038: add function __getrusage64

diff --git a/resource/Makefile b/resource/Makefile
index bf66294..c482e82 100644
--- a/resource/Makefile
+++ b/resource/Makefile
@@ -23,7 +23,7 @@ headers	  := sys/resource.h bits/resource.h sys/vlimit.h sys/vtimes.h	\
 	     ulimit.h bits/types/struct_rusage.h
 
 routines := getrlimit setrlimit getrlimit64 setrlimit64 getrusage ulimit      \
-	    vlimit vtimes getpriority setpriority nice
+	    vlimit vtimes getpriority setpriority nice getrusage64
 
 tests = tst-getrlimit bug-ulimit1
 
diff --git a/resource/Versions b/resource/Versions
index d6c2cce..c5f8f93 100644
--- a/resource/Versions
+++ b/resource/Versions
@@ -22,6 +22,9 @@ libc {
     # s*
     setrlimit64;
   }
+  GLIBC_2.28 {
+    __getrusage64;
+  }
   GLIBC_PRIVATE {
     __getrlimit;
   }
diff --git a/resource/getrusage64.c b/resource/getrusage64.c
new file mode 100644
index 0000000..f7edb97
--- /dev/null
+++ b/resource/getrusage64.c
@@ -0,0 +1,181 @@
+/* Return resource usage for the current process.
+   
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/resource.h>
+#include <include/time.h>
+#include <sysdep.h>
+#include <sys/syscall.h>
+#include <errno.h>
+
+/* Structure which says how much of each resource has been used.  */
+/* 64-bit time version */
+/* The purpose of all the unions is to have the kernel-compatible layout
+   while keeping the API type as 'long int', and among machines where
+   __syscall_slong_t is not 'long int', this only does the right thing
+   for little-endian ones, like x32.  */
+struct __rusage64
+  {
+    /* Total amount of user time used.  */
+    struct __timeval64 ru_utime;
+    /* Total amount of system time used.  */
+    struct __timeval64 ru_stime;
+    /* Maximum resident set size (in kilobytes).  */
+    __extension__ union
+      {
+	long int ru_maxrss;
+	__syscall_slong_t __ru_maxrss_word;
+      };
+    /* Amount of sharing of text segment memory
+       with other processes (kilobyte-seconds).  */
+    /* Maximum resident set size (in kilobytes).  */
+    __extension__ union
+      {
+	long int ru_ixrss;
+	__syscall_slong_t __ru_ixrss_word;
+      };
+    /* Amount of data segment memory used (kilobyte-seconds).  */
+    __extension__ union
+      {
+	long int ru_idrss;
+	__syscall_slong_t __ru_idrss_word;
+      };
+    /* Amount of stack memory used (kilobyte-seconds).  */
+    __extension__ union
+      {
+	long int ru_isrss;
+	 __syscall_slong_t __ru_isrss_word;
+      };
+    /* Number of soft page faults (i.e. those serviced by reclaiming
+       a page from the list of pages awaiting reallocation.  */
+    __extension__ union
+      {
+	long int ru_minflt;
+	__syscall_slong_t __ru_minflt_word;
+      };
+    /* Number of hard page faults (i.e. those that required I/O).  */
+    __extension__ union
+      {
+	long int ru_majflt;
+	__syscall_slong_t __ru_majflt_word;
+      };
+    /* Number of times a process was swapped out of physical memory.  */
+    __extension__ union
+      {
+	long int ru_nswap;
+	__syscall_slong_t __ru_nswap_word;
+      };
+    /* Number of input operations via the file system.  Note: This
+       and `ru_oublock' do not include operations with the cache.  */
+    __extension__ union
+      {
+	long int ru_inblock;
+	__syscall_slong_t __ru_inblock_word;
+      };
+    /* Number of output operations via the file system.  */
+    __extension__ union
+      {
+	long int ru_oublock;
+	__syscall_slong_t __ru_oublock_word;
+      };
+    /* Number of IPC messages sent.  */
+    __extension__ union
+      {
+	long int ru_msgsnd;
+	__syscall_slong_t __ru_msgsnd_word;
+      };
+    /* Number of IPC messages received.  */
+    __extension__ union
+      {
+	long int ru_msgrcv;
+	__syscall_slong_t __ru_msgrcv_word;
+      };
+    /* Number of signals delivered.  */
+    __extension__ union
+      {
+	long int ru_nsignals;
+	__syscall_slong_t __ru_nsignals_word;
+      };
+    /* Number of voluntary context switches, i.e. because the process
+       gave up the process before it had to (usually to wait for some
+       resource to be available).  */
+    __extension__ union
+      {
+	long int ru_nvcsw;
+	__syscall_slong_t __ru_nvcsw_word;
+      };
+    /* Number of involuntary context switches, i.e. a higher priority process
+       became runnable or the current process used up its time slice.  */
+    __extension__ union
+      {
+	long int ru_nivcsw;
+	__syscall_slong_t __ru_nivcsw_word;
+      };
+  };
+
+int __getrusage64 (__rusage_who_t __who, struct __rusage64 *__usage)
+{
+  int result;
+  struct rusage usage32;
+
+  result = INLINE_SYSCALL(getrusage, 2, __who, &usage32);
+  /* Copy fields from 32-bit into 64-bit rusage structure */
+  /* Total amount of user time used.  */
+  __usage->ru_utime.tv_sec = usage32.ru_utime.tv_sec;
+  __usage->ru_utime.tv_usec = usage32.ru_utime.tv_usec;
+  /* Total amount of system time used.  */
+  __usage->ru_stime.tv_sec = usage32.ru_stime.tv_sec;
+  __usage->ru_stime.tv_usec = usage32.ru_stime.tv_usec;
+  /* Maximum resident set size (in kilobytes).  */
+  __usage->ru_maxrss = usage32.ru_maxrss;
+  /* Amount of sharing of text segment memory
+     with other processes (kilobyte-seconds).  */
+  /* Maximum resident set size (in kilobytes).  */
+  __usage->ru_ixrss = usage32.ru_ixrss;
+  /* Amount of data segment memory used (kilobyte-seconds).  */
+  __usage->ru_idrss = usage32.ru_idrss;
+  /* Amount of stack memory used (kilobyte-seconds).  */
+  __usage->ru_isrss = usage32.ru_isrss;
+  /* Number of soft page faults (i.e. those serviced by reclaiming
+     a page from the list of pages awaiting reallocation.  */
+  __usage->ru_minflt = usage32.ru_minflt;
+  /* Number of hard page faults (i.e. those that required I/O).  */
+  __usage->ru_majflt = usage32.ru_majflt;
+  /* Number of times a process was swapped out of physical memory.  */
+  __usage->ru_nswap = usage32.ru_nswap;
+  /* Number of input operations via the file system.  Note: This
+     and `ru_oublock' do not include operations with the cache.  */
+  __usage->ru_inblock = usage32.ru_inblock;
+  /* Number of output operations via the file system.  */
+  __usage->ru_oublock = usage32.ru_oublock;
+  /* Number of IPC messages sent.  */
+  __usage->ru_msgsnd = usage32.ru_msgsnd;
+  /* Number of IPC messages received.  */
+  __usage->ru_msgrcv = usage32.ru_msgrcv;
+  /* Number of signals delivered.  */
+  __usage->ru_nsignals = usage32.ru_nsignals;
+  /* Number of voluntary context switches, i.e. because the process
+     gave up the process before it had to (usually to wait for some
+     resource to be available).  */
+  __usage->ru_nvcsw = usage32.ru_nvcsw;
+  /* Number of involuntary context switches, i.e. a higher priority process
+     became runnable or the current process used up its time slice.  */
+  __usage->ru_nivcsw = usage32.ru_nivcsw;
+
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7bdf8be291f62c4028fce6b114b73601017ab7df

commit 7bdf8be291f62c4028fce6b114b73601017ab7df
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:10 2017 +0200

    Y2038: add functions using futexes
    
    This creates 64-bit time versions of the following APIs:
    - pthread_rwlock_timedrdlock
    - pthread_rwlock_timedwrlock
    - pthread_mutex_timedlock
    - pthread_cond_timedwait
    - sem_timedwait
    - aio_suspend
    
    It also creates 64-bit time versions of the following
    functions or macros:
    - lll_timedlock_elision
    - lll_timedlock
    - __lll_timedlock_wait
    - futex_reltimed_wait_cancelable
    - lll_futex_timed_wait
    - __pthread_cond_wait_common
    - futex_abstimed_wait_cancelable
    - lll_futex_timed_wait_bitset
    - do_aio_misc_wait
    - AIO_MISC_WAIT
    - __new_sem_wait_slow
    - do_futex_wait
    - __pthread_rwlock_wrlock_full
    - __pthread_rwlock_rdlock_full
    - futex_abstimed_wait

diff --git a/nptl/Versions b/nptl/Versions
index b1c2da0..2747209 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -265,6 +265,14 @@ libpthread {
   GLIBC_2.22 {
   }
 
+  GLIBC_2.28 {
+    __pthread_rwlock_rdlock64;
+    __pthread_rwlock_wrlock64;
+    __pthread_mutex_timedlock64;
+    __sem_timedwait64;
+    __pthread_cond_timedwait64;
+  }
+
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
     __pthread_clock_gettime; __pthread_clock_settime;
diff --git a/nptl/lll_timedlock_wait.c b/nptl/lll_timedlock_wait.c
index 91bf963..6d3aecb 100644
--- a/nptl/lll_timedlock_wait.c
+++ b/nptl/lll_timedlock_wait.c
@@ -57,3 +57,40 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
 
   return 0;
 }
+
+/* 64-bit time version */
+
+int
+__lll_timedlock_wait64 (int *futex, const struct __timespec64 *abstime, int private)
+{
+  /* Reject invalid timeouts.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  /* Try locking.  */
+  while (atomic_exchange_acq (futex, 2) != 0)
+    {
+      struct timeval tv;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      struct timespec rt;
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+        {
+          rt.tv_nsec += 1000000000;
+          --rt.tv_sec;
+        }
+
+      if (rt.tv_sec < 0)
+        return ETIMEDOUT;
+
+      /* If *futex == 2, wait until woken or timeout.  */
+      lll_futex_timed_wait (futex, 2, &rt, private);
+    }
+
+  return 0;
+}
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 3e11054..7b64641 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -647,6 +647,280 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
   return (err != 0) ? err : result;
 }
 
+/* 64-bit time variant */
+
+static __always_inline int
+__pthread_cond_wait_common64 (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    const struct __timespec64 *abstime)
+{
+  const int maxspin = 0;
+  int err;
+  int result = 0;
+
+  LIBC_PROBE (cond_wait, 2, cond, mutex);
+
+  /* Acquire a position (SEQ) in the waiter sequence (WSEQ).  We use an
+     atomic operation because signals and broadcasts may update the group
+     switch without acquiring the mutex.  We do not need release MO here
+     because we do not need to establish any happens-before relation with
+     signalers (see __pthread_cond_signal); modification order alone
+     establishes a total order of waiters/signals.  We do need acquire MO
+     to synchronize with group reinitialization in
+     __condvar_quiesce_and_switch_g1.  */
+  uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);
+  /* Find our group's index.  We always go into what was G2 when we acquired
+     our position.  */
+  unsigned int g = wseq & 1;
+  uint64_t seq = wseq >> 1;
+
+  /* Increase the waiter reference count.  Relaxed MO is sufficient because
+     we only need to synchronize when decrementing the reference count.  */
+  unsigned int flags = atomic_fetch_add_relaxed (&cond->__data.__wrefs, 8);
+  int private = __condvar_get_private (flags);
+
+  /* Now that we are registered as a waiter, we can release the mutex.
+     Waiting on the condvar must be atomic with releasing the mutex, so if
+     the mutex is used to establish a happens-before relation with any
+     signaler, the waiter must be visible to the latter; thus, we release the
+     mutex after registering as waiter.
+     If releasing the mutex fails, we just cancel our registration as a
+     waiter and confirm that we have woken up.  */
+  err = __pthread_mutex_unlock_usercnt (mutex, 0);
+  if (__glibc_unlikely (err != 0))
+    {
+      __condvar_cancel_waiting (cond, seq, g, private);
+      __condvar_confirm_wakeup (cond, private);
+      return err;
+    }
+
+  /* Now wait until a signal is available in our group or it is closed.
+     Acquire MO so that if we observe a value of zero written after group
+     switching in __condvar_quiesce_and_switch_g1, we synchronize with that
+     store and will see the prior update of __g1_start done while switching
+     groups too.  */
+  unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
+
+  do
+    {
+      while (1)
+	{
+	  /* Spin-wait first.
+	     Note that spinning first without checking whether a timeout
+	     passed might lead to what looks like a spurious wake-up even
+	     though we should return ETIMEDOUT (e.g., if the caller provides
+	     an absolute timeout that is clearly in the past).  However,
+	     (1) spurious wake-ups are allowed, (2) it seems unlikely that a
+	     user will (ab)use pthread_cond_wait as a check for whether a
+	     point in time is in the past, and (3) spinning first without
+	     having to compare against the current time seems to be the right
+	     choice from a performance perspective for most use cases.  */
+	  unsigned int spin = maxspin;
+	  while (signals == 0 && spin > 0)
+	    {
+	      /* Check that we are not spinning on a group that's already
+		 closed.  */
+	      if (seq < (__condvar_load_g1_start_relaxed (cond) >> 1))
+		goto done;
+
+	      /* TODO Back off.  */
+
+	      /* Reload signals.  See above for MO.  */
+	      signals = atomic_load_acquire (cond->__data.__g_signals + g);
+	      spin--;
+	    }
+
+	  /* If our group will be closed as indicated by the flag on signals,
+	     don't bother grabbing a signal.  */
+	  if (signals & 1)
+	    goto done;
+
+	  /* If there is an available signal, don't block.  */
+	  if (signals != 0)
+	    break;
+
+	  /* No signals available after spinning, so prepare to block.
+	     We first acquire a group reference and use acquire MO for that so
+	     that we synchronize with the dummy read-modify-write in
+	     __condvar_quiesce_and_switch_g1 if we read from that.  In turn,
+	     in this case this will make us see the closed flag on __g_signals
+	     that designates a concurrent attempt to reuse the group's slot.
+	     We use acquire MO for the __g_signals check to make the
+	     __g1_start check work (see spinning above).
+	     Note that the group reference acquisition will not mask the
+	     release MO when decrementing the reference count because we use
+	     an atomic read-modify-write operation and thus extend the release
+	     sequence.  */
+	  atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
+	  if (((atomic_load_acquire (cond->__data.__g_signals + g) & 1) != 0)
+	      || (seq < (__condvar_load_g1_start_relaxed (cond) >> 1)))
+	    {
+	      /* Our group is closed.  Wake up any signalers that might be
+		 waiting.  */
+	      __condvar_dec_grefs (cond, g, private);
+	      goto done;
+	    }
+
+	  // Now block.
+	  struct _pthread_cleanup_buffer buffer;
+	  struct _condvar_cleanup_buffer cbuffer;
+	  cbuffer.wseq = wseq;
+	  cbuffer.cond = cond;
+	  cbuffer.mutex = mutex;
+	  cbuffer.private = private;
+	  __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
+
+	  if (abstime == NULL)
+	    {
+	      /* Block without a timeout.  */
+	      err = futex_wait_cancelable (
+		  cond->__data.__g_signals + g, 0, private);
+	    }
+	  else
+	    {
+	      /* Block, but with a timeout.
+		 Work around the fact that the kernel rejects negative timeout
+		 values despite them being valid.  */
+	      if (__glibc_unlikely (abstime->tv_sec < 0))
+	        err = ETIMEDOUT;
+
+	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
+		{
+		  /* CLOCK_MONOTONIC is requested.  */
+		  struct timespec rt;
+		  struct __timespec64 rt64;
+		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
+		    __libc_fatal ("clock_gettime does not support "
+				  "CLOCK_MONOTONIC");
+		  /* Convert the absolute timeout value to a relative
+		     timeout.  */
+		  rt64.tv_sec = abstime->tv_sec - rt.tv_sec;
+		  rt64.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
+		  if (rt64.tv_nsec < 0)
+		    {
+		      rt64.tv_nsec += 1000000000;
+		      --rt64.tv_sec;
+		    }
+		  /* Did we already time out?  */
+		  if (__glibc_unlikely (rt64.tv_sec < 0))
+		    err = ETIMEDOUT;
+		  else
+		    err = futex_reltimed_wait_cancelable64
+			(cond->__data.__g_signals + g, 0, &rt64, private);
+		}
+	      else
+		{
+		  /* Use CLOCK_REALTIME.  */
+		  err = futex_abstimed_wait_cancelable64
+		      (cond->__data.__g_signals + g, 0, abstime, private);
+		}
+	    }
+
+	  __pthread_cleanup_pop (&buffer, 0);
+
+	  if (__glibc_unlikely (err == ETIMEDOUT))
+	    {
+	      __condvar_dec_grefs (cond, g, private);
+	      /* If we timed out, we effectively cancel waiting.  Note that
+		 we have decremented __g_refs before cancellation, so that a
+		 deadlock between waiting for quiescence of our group in
+		 __condvar_quiesce_and_switch_g1 and us trying to acquire
+		 the lock during cancellation is not possible.  */
+	      __condvar_cancel_waiting (cond, seq, g, private);
+	      result = ETIMEDOUT;
+	      goto done;
+	    }
+	  else
+	    __condvar_dec_grefs (cond, g, private);
+
+	  /* Reload signals.  See above for MO.  */
+	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
+	}
+
+    }
+  /* Try to grab a signal.  Use acquire MO so that we see an up-to-date value
+     of __g1_start below (see spinning above for a similar case).  In
+     particular, if we steal from a more recent group, we will also see a
+     more recent __g1_start below.  */
+  while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
+						&signals, signals - 2));
+
+  /* We consumed a signal but we could have consumed from a more recent group
+     that aliased with ours due to being in the same group slot.  If this
+     might be the case our group must be closed as visible through
+     __g1_start.  */
+  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
+  if (seq < (g1_start >> 1))
+    {
+      /* We potentially stole a signal from a more recent group but we do not
+	 know which group we really consumed from.
+	 We do not care about groups older than current G1 because they are
+	 closed; we could have stolen from these, but then we just add a
+	 spurious wake-up for the current groups.
+	 We will never steal a signal from current G2 that was really intended
+	 for G2 because G2 never receives signals (until it becomes G1).  We
+	 could have stolen a signal from G2 that was conservatively added by a
+	 previous waiter that also thought it stole a signal -- but given that
+	 that signal was added unnecessarily, it's not a problem if we steal
+	 it.
+	 Thus, the remaining case is that we could have stolen from the current
+	 G1, where "current" means the __g1_start value we observed.  However,
+	 if the current G1 does not have the same slot index as we do, we did
+	 not steal from it and do not need to undo that.  This is the reason
+	 for putting a bit with G2's index into__g1_start as well.  */
+      if (((g1_start & 1) ^ 1) == g)
+	{
+	  /* We have to conservatively undo our potential mistake of stealing
+	     a signal.  We can stop trying to do that when the current G1
+	     changes because other spinning waiters will notice this too and
+	     __condvar_quiesce_and_switch_g1 has checked that there are no
+	     futex waiters anymore before switching G1.
+	     Relaxed MO is fine for the __g1_start load because we need to
+	     merely be able to observe this fact and not have to observe
+	     something else as well.
+	     ??? Would it help to spin for a little while to see whether the
+	     current G1 gets closed?  This might be worthwhile if the group is
+	     small or close to being closed.  */
+	  unsigned int s = atomic_load_relaxed (cond->__data.__g_signals + g);
+	  while (__condvar_load_g1_start_relaxed (cond) == g1_start)
+	    {
+	      /* Try to add a signal.  We don't need to acquire the lock
+		 because at worst we can cause a spurious wake-up.  If the
+		 group is in the process of being closed (LSB is true), this
+		 has an effect similar to us adding a signal.  */
+	      if (((s & 1) != 0)
+		  || atomic_compare_exchange_weak_relaxed
+		       (cond->__data.__g_signals + g, &s, s + 2))
+		{
+		  /* If we added a signal, we also need to add a wake-up on
+		     the futex.  We also need to do that if we skipped adding
+		     a signal because the group is being closed because
+		     while __condvar_quiesce_and_switch_g1 could have closed
+		     the group, it might stil be waiting for futex waiters to
+		     leave (and one of those waiters might be the one we stole
+		     the signal from, which cause it to block using the
+		     futex).  */
+		  futex_wake (cond->__data.__g_signals + g, 1, private);
+		  break;
+		}
+	      /* TODO Back off.  */
+	    }
+	}
+    }
+
+ done:
+
+  /* Confirm that we have been woken.  We do that before acquiring the mutex
+     to allow for execution of pthread_cond_destroy while having acquired the
+     mutex.  */
+  __condvar_confirm_wakeup (cond, private);
+
+  /* Woken up; now re-acquire the mutex.  If this doesn't fail, return RESULT,
+     which is set to ETIMEDOUT if a timeout occured, or zero otherwise.  */
+  err = __pthread_mutex_cond_lock (mutex);
+  /* XXX Abort on errors that are disallowed by POSIX?  */
+  return (err != 0) ? err : result;
+}
+
 
 /* See __pthread_cond_wait_common.  */
 int
@@ -667,6 +941,17 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
   return __pthread_cond_wait_common (cond, mutex, abstime);
 }
 
+int
+__pthread_cond_timedwait64 (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    const struct __timespec64 *abstime)
+{
+  /* Check parameter validity.  This should also tell the compiler that
+     it can assume that abstime is not NULL.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+  return __pthread_cond_wait_common64 (cond, mutex, abstime);
+}
+
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 		  GLIBC_2_3_2);
 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index 28237b0..9d9dfdf 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -25,6 +25,7 @@
 #include <atomic.h>
 #include <lowlevellock.h>
 #include <not-cancel.h>
+#include <y2038-support.h>
 
 #include <stap-probe.h>
 
@@ -32,6 +33,10 @@
 #define lll_timedlock_elision(a,dummy,b,c) lll_timedlock(a, b, c)
 #endif
 
+#ifndef lll_timedlock_elision64
+#define lll_timedlock_elision64(a,dummy,b,c) lll_timedlock64(a, b, c)
+#endif
+
 #ifndef lll_trylock_elision
 #define lll_trylock_elision(a,t) lll_trylock(a)
 #endif
@@ -638,3 +643,635 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
   return result;
 }
 weak_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
+
+/* 64-bit time version */
+
+int
+__pthread_mutex_timedlock64 (pthread_mutex_t *mutex,
+			 const struct __timespec64 *abstime)
+{
+/* Only compile this function if kernel provides clock_gettime64 */
+#ifdef __NR_clock_gettime64
+  int oldval;
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+  int result = 0;
+#endif
+  struct timespec abstime32;
+
+  LIBC_PROBE (mutex_timedlock_entry, 2, mutex, abstime);
+
+/* Only compile this function if kernel provides clock_gettime64 */
+#ifdef __NR_clock_gettime64
+  if (__y2038_get_kernel_support())
+    {
+
+      /* We must not check ABSTIME here.  If the thread does not block
+         abstime must not be checked for a valid value.  */
+
+      switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
+                    PTHREAD_MUTEX_TIMED_NP))
+        {
+          /* Recursive mutex.  */
+        case PTHREAD_MUTEX_RECURSIVE_NP|PTHREAD_MUTEX_ELISION_NP:
+        case PTHREAD_MUTEX_RECURSIVE_NP:
+          /* Check whether we already hold the mutex.  */
+          if (mutex->__data.__owner == id)
+        {
+          /* Just bump the counter.  */
+          if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+            /* Overflow of the counter.  */
+            return EAGAIN;
+
+          ++mutex->__data.__count;
+
+          goto out;
+        }
+
+          /* We have to get the mutex.  */
+          result = lll_timedlock64 (mutex->__data.__lock, abstime,
+                          PTHREAD_MUTEX_PSHARED (mutex));
+
+          if (result != 0)
+        goto out;
+
+          /* Only locked once so far.  */
+          mutex->__data.__count = 1;
+          break;
+
+          /* Error checking mutex.  */
+        case PTHREAD_MUTEX_ERRORCHECK_NP:
+          /* Check whether we already hold the mutex.  */
+          if (__glibc_unlikely (mutex->__data.__owner == id))
+        return EDEADLK;
+
+          /* Don't do lock elision on an error checking mutex.  */
+          goto simple;
+
+        case PTHREAD_MUTEX_TIMED_NP:
+          FORCE_ELISION (mutex, goto elision);
+        simple:
+          /* Normal mutex.  */
+          result = lll_timedlock64 (mutex->__data.__lock, abstime,
+                          PTHREAD_MUTEX_PSHARED (mutex));
+          break;
+
+        case PTHREAD_MUTEX_TIMED_ELISION_NP:
+        elision: __attribute__((unused))
+          /* Don't record ownership */
+          return lll_timedlock_elision64 (mutex->__data.__lock,
+                        mutex->__data.__spins,
+                        abstime,
+                        PTHREAD_MUTEX_PSHARED (mutex));
+
+
+        case PTHREAD_MUTEX_ADAPTIVE_NP:
+          if (! __is_smp)
+        goto simple;
+
+          if (lll_trylock (mutex->__data.__lock) != 0)
+        {
+          int cnt = 0;
+          int max_cnt = MIN (MAX_ADAPTIVE_COUNT,
+                     mutex->__data.__spins * 2 + 10);
+          do
+            {
+              if (cnt++ >= max_cnt)
+            {
+              result = lll_timedlock64 (mutex->__data.__lock, abstime,
+                              PTHREAD_MUTEX_PSHARED (mutex));
+              break;
+            }
+              atomic_spin_nop ();
+            }
+          while (lll_trylock (mutex->__data.__lock) != 0);
+
+          mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
+        }
+          break;
+
+        case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
+        case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
+        case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
+        case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
+          THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+                 &mutex->__data.__list.__next);
+          /* We need to set op_pending before starting the operation.  Also
+         see comments at ENQUEUE_MUTEX.  */
+          __asm ("" ::: "memory");
+
+          oldval = mutex->__data.__lock;
+          /* This is set to FUTEX_WAITERS iff we might have shared the
+         FUTEX_WAITERS flag with other threads, and therefore need to keep it
+         set to avoid lost wake-ups.  We have the same requirement in the
+         simple mutex algorithm.  */
+          unsigned int assume_other_futex_waiters = 0;
+          while (1)
+        {
+          /* Try to acquire the lock through a CAS from 0 (not acquired) to
+             our TID | assume_other_futex_waiters.  */
+          if (__glibc_likely (oldval == 0))
+            {
+              oldval
+                = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                    id | assume_other_futex_waiters, 0);
+              if (__glibc_likely (oldval == 0))
+            break;
+            }
+
+          if ((oldval & FUTEX_OWNER_DIED) != 0)
+            {
+              /* The previous owner died.  Try locking the mutex.  */
+              int newval = id | (oldval & FUTEX_WAITERS)
+              | assume_other_futex_waiters;
+
+              newval
+            = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                   newval, oldval);
+              if (newval != oldval)
+            {
+              oldval = newval;
+              continue;
+            }
+
+              /* We got the mutex.  */
+              mutex->__data.__count = 1;
+              /* But it is inconsistent unless marked otherwise.  */
+              mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+              /* We must not enqueue the mutex before we have acquired it.
+             Also see comments at ENQUEUE_MUTEX.  */
+              __asm ("" ::: "memory");
+              ENQUEUE_MUTEX (mutex);
+              /* We need to clear op_pending after we enqueue the mutex.  */
+              __asm ("" ::: "memory");
+              THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+              /* Note that we deliberately exit here.  If we fall
+             through to the end of the function __nusers would be
+             incremented which is not correct because the old
+             owner has to be discounted.  */
+              return EOWNERDEAD;
+            }
+
+          /* Check whether we already hold the mutex.  */
+          if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+            {
+              int kind = PTHREAD_MUTEX_TYPE (mutex);
+              if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
+            {
+              /* We do not need to ensure ordering wrt another memory
+                 access.  Also see comments at ENQUEUE_MUTEX. */
+              THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+                     NULL);
+              return EDEADLK;
+            }
+
+              if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
+            {
+              /* We do not need to ensure ordering wrt another memory
+                 access.  */
+              THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+                     NULL);
+
+              /* Just bump the counter.  */
+              if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+                /* Overflow of the counter.  */
+                return EAGAIN;
+
+              ++mutex->__data.__count;
+
+              LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+              return 0;
+            }
+            }
+
+          /* We are about to block; check whether the timeout is invalid.  */
+          if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+            return EINVAL;
+          /* Work around the fact that the kernel rejects negative timeout
+             values despite them being valid.  */
+          if (__glibc_unlikely (abstime->tv_sec < 0))
+            return ETIMEDOUT;
+    #if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+         || !defined lll_futex_timed_wait_bitset)
+          struct timeval tv;
+          struct timespec rt;
+
+          /* Get the current time.  */
+          (void) __gettimeofday (&tv, NULL);
+
+          /* Compute relative timeout.  */
+          rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+          rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+          if (rt.tv_nsec < 0)
+            {
+              rt.tv_nsec += 1000000000;
+              --rt.tv_sec;
+            }
+
+          /* Already timed out?  */
+          if (rt.tv_sec < 0)
+            return ETIMEDOUT;
+    #endif
+
+          /* We cannot acquire the mutex nor has its owner died.  Thus, try
+             to block using futexes.  Set FUTEX_WAITERS if necessary so that
+             other threads are aware that there are potentially threads
+             blocked on the futex.  Restart if oldval changed in the
+             meantime.  */
+          if ((oldval & FUTEX_WAITERS) == 0)
+            {
+              if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
+                                oldval | FUTEX_WAITERS,
+                                oldval)
+              != 0)
+            {
+              oldval = mutex->__data.__lock;
+              continue;
+            }
+              oldval |= FUTEX_WAITERS;
+            }
+
+          /* It is now possible that we share the FUTEX_WAITERS flag with
+             another thread; therefore, update assume_other_futex_waiters so
+             that we do not forget about this when handling other cases
+             above and thus do not cause lost wake-ups.  */
+          assume_other_futex_waiters |= FUTEX_WAITERS;
+
+          /* Block using the futex.  */
+    #if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+         || !defined lll_futex_timed_wait_bitset)
+          lll_futex_timed wait_64 (&mutex->__data.__lock, oldval,
+                    &rt, PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
+    #else
+          int err = lll_futex_timed_wait_bitset64 (&mutex->__data.__lock,
+              oldval, abstime, FUTEX_CLOCK_REALTIME,
+              PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
+          /* The futex call timed out.  */
+          if (err == -ETIMEDOUT)
+            return -err;
+    #endif
+          /* Reload current lock value.  */
+          oldval = mutex->__data.__lock;
+        }
+
+          /* We have acquired the mutex; check if it is still consistent.  */
+          if (__builtin_expect (mutex->__data.__owner
+                    == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+        {
+          /* This mutex is now not recoverable.  */
+          mutex->__data.__count = 0;
+          int private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
+          lll_unlock (mutex->__data.__lock, private);
+          /* FIXME This violates the mutex destruction requirements.  See
+             __pthread_mutex_unlock_full.  */
+          THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+          return ENOTRECOVERABLE;
+        }
+
+          mutex->__data.__count = 1;
+          /* We must not enqueue the mutex before we have acquired it.
+         Also see comments at ENQUEUE_MUTEX.  */
+          __asm ("" ::: "memory");
+          ENQUEUE_MUTEX (mutex);
+          /* We need to clear op_pending after we enqueue the mutex.  */
+          __asm ("" ::: "memory");
+          THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+          break;
+
+        /* The PI support requires the Linux futex system call.  If that's not
+           available, pthread_mutex_init should never have allowed the type to
+           be set.  So it will get the default case for an invalid type.  */
+    #ifdef __NR_futex
+        case PTHREAD_MUTEX_PI_RECURSIVE_NP:
+        case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
+        case PTHREAD_MUTEX_PI_NORMAL_NP:
+        case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
+        case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
+        case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
+        case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
+        case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
+          {
+        int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+        int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
+
+        if (robust)
+          {
+            /* Note: robust PI futexes are signaled by setting bit 0.  */
+            THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+                   (void *) (((uintptr_t) &mutex->__data.__list.__next)
+                         | 1));
+            /* We need to set op_pending before starting the operation.  Also
+               see comments at ENQUEUE_MUTEX.  */
+            __asm ("" ::: "memory");
+          }
+
+        oldval = mutex->__data.__lock;
+
+        /* Check whether we already hold the mutex.  */
+        if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+          {
+            if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+              {
+            /* We do not need to ensure ordering wrt another memory
+               access.  */
+            THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+            return EDEADLK;
+              }
+
+            if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+              {
+            /* We do not need to ensure ordering wrt another memory
+               access.  */
+            THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+            /* Just bump the counter.  */
+            if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+              /* Overflow of the counter.  */
+              return EAGAIN;
+
+            ++mutex->__data.__count;
+
+            LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+            return 0;
+              }
+          }
+
+        oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                  id, 0);
+
+        if (oldval != 0)
+          {
+            /* The mutex is locked.  The kernel will now take care of
+               everything.  The timeout value must be a relative value.
+               Convert it.  */
+            int private = (robust
+                   ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
+                   : PTHREAD_MUTEX_PSHARED (mutex));
+            INTERNAL_SYSCALL_DECL (__err);
+
+            int e;
+            
+            if (abstime->tv_sec > INT_MAX)
+            {
+              e = EOVERFLOW;
+            }
+            else
+            {
+              struct timespec ts;
+              ts.tv_sec = abstime->tv_sec;
+              ts.tv_nsec = abstime->tv_nsec;
+              e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
+                          __lll_private_flag (FUTEX_LOCK_PI,
+                                  private), 1,
+                          &ts);
+            }
+            if (INTERNAL_SYSCALL_ERROR_P (e, __err))
+              {
+            if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT)
+              return ETIMEDOUT;
+
+            if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH
+                || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)
+              {
+                assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK
+                    || (kind != PTHREAD_MUTEX_ERRORCHECK_NP
+                    && kind != PTHREAD_MUTEX_RECURSIVE_NP));
+                /* ESRCH can happen only for non-robust PI mutexes where
+                   the owner of the lock died.  */
+                assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH
+                    || !robust);
+
+                /* Delay the thread until the timeout is reached.
+                   Then return ETIMEDOUT.  */
+                struct timespec reltime;
+                struct __timespec64 now;
+
+                INTERNAL_SYSCALL (clock_gettime64, __err, 2, CLOCK_REALTIME,
+                          &now);
+                reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+                reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec;
+                if (reltime.tv_nsec < 0)
+                  {
+                reltime.tv_nsec += 1000000000;
+                --reltime.tv_sec;
+                  }
+                if (reltime.tv_sec >= 0)
+                  while (__nanosleep_nocancel (&reltime, &reltime) != 0)
+                continue;
+
+                return ETIMEDOUT;
+              }
+
+            return INTERNAL_SYSCALL_ERRNO (e, __err);
+              }
+
+            oldval = mutex->__data.__lock;
+
+            assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
+          }
+
+        if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
+          {
+            atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
+
+            /* We got the mutex.  */
+            mutex->__data.__count = 1;
+            /* But it is inconsistent unless marked otherwise.  */
+            mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+            /* We must not enqueue the mutex before we have acquired it.
+               Also see comments at ENQUEUE_MUTEX.  */
+            __asm ("" ::: "memory");
+            ENQUEUE_MUTEX_PI (mutex);
+            /* We need to clear op_pending after we enqueue the mutex.  */
+            __asm ("" ::: "memory");
+            THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+            /* Note that we deliberately exit here.  If we fall
+               through to the end of the function __nusers would be
+               incremented which is not correct because the old owner
+               has to be discounted.  */
+            return EOWNERDEAD;
+          }
+
+        if (robust
+            && __builtin_expect (mutex->__data.__owner
+                     == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+          {
+            /* This mutex is now not recoverable.  */
+            mutex->__data.__count = 0;
+
+            INTERNAL_SYSCALL_DECL (__err);
+            INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
+                      __lll_private_flag (FUTEX_UNLOCK_PI,
+                              PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
+                      0, 0);
+
+            /* To the kernel, this will be visible after the kernel has
+               acquired the mutex in the syscall.  */
+            THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+            return ENOTRECOVERABLE;
+          }
+
+        mutex->__data.__count = 1;
+        if (robust)
+          {
+            /* We must not enqueue the mutex before we have acquired it.
+               Also see comments at ENQUEUE_MUTEX.  */
+            __asm ("" ::: "memory");
+            ENQUEUE_MUTEX_PI (mutex);
+            /* We need to clear op_pending after we enqueue the mutex.  */
+            __asm ("" ::: "memory");
+            THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+          }
+        }
+          break;
+    #endif  /* __NR_futex.  */
+
+        case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+        case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+        case PTHREAD_MUTEX_PP_NORMAL_NP:
+        case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+          {
+        int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+
+        oldval = mutex->__data.__lock;
+
+        /* Check whether we already hold the mutex.  */
+        if (mutex->__data.__owner == id)
+          {
+            if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+              return EDEADLK;
+
+            if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+              {
+            /* Just bump the counter.  */
+            if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+              /* Overflow of the counter.  */
+              return EAGAIN;
+
+            ++mutex->__data.__count;
+
+            LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+            return 0;
+              }
+          }
+
+        int oldprio = -1, ceilval;
+        do
+          {
+            int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+                  >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+            if (__pthread_current_priority () > ceiling)
+              {
+            result = EINVAL;
+              failpp:
+            if (oldprio != -1)
+              __pthread_tpp_change_priority (oldprio, -1);
+            return result;
+              }
+
+            result = __pthread_tpp_change_priority (oldprio, ceiling);
+            if (result)
+              return result;
+
+            ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+            oldprio = ceiling;
+
+            oldval
+              = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                 ceilval | 1, ceilval);
+
+            if (oldval == ceilval)
+              break;
+
+            do
+              {
+            oldval
+              = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                 ceilval | 2,
+                                 ceilval | 1);
+
+            if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+              break;
+
+            if (oldval != ceilval)
+              {
+                /* Reject invalid timeouts.  */
+                if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+                  {
+                result = EINVAL;
+                goto failpp;
+                  }
+
+                struct timeval tv;
+                struct timespec rt;
+
+                /* Get the current time.  */
+                (void) __gettimeofday (&tv, NULL);
+
+                /* Compute relative timeout.  */
+                rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+                rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+                if (rt.tv_nsec < 0)
+                  {
+                rt.tv_nsec += 1000000000;
+                --rt.tv_sec;
+                  }
+
+                /* Already timed out?  */
+                if (rt.tv_sec < 0)
+                  {
+                result = ETIMEDOUT;
+                goto failpp;
+                  }
+
+                lll_futex_timed_wait (&mutex->__data.__lock,
+                          ceilval | 2, &rt,
+                          PTHREAD_MUTEX_PSHARED (mutex));
+              }
+              }
+            while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                ceilval | 2, ceilval)
+               != ceilval);
+          }
+        while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
+
+        assert (mutex->__data.__owner == 0);
+        mutex->__data.__count = 1;
+          }
+          break;
+
+        default:
+          /* Correct code cannot set any other type.  */
+          return EINVAL;
+        }
+
+      if (result == 0)
+        {
+          /* Record the ownership.  */
+          mutex->__data.__owner = id;
+          ++mutex->__data.__nusers;
+
+          LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+        }
+     out:
+      return result;
+    }
+#endif
+
+  if (abstime->tv_sec > INT_MAX || abstime->tv_sec < INT_MIN)
+    {
+      return EOVERFLOW;
+    }
+
+  abstime32.tv_sec = (time_t) (abstime->tv_sec);
+  abstime32.tv_nsec = abstime->tv_nsec;
+
+  return __pthread_mutex_timedlock (mutex, &abstime32);
+}
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index a290d08..f34750e 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -507,6 +507,240 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   return 0;
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+__pthread_rwlock_rdlock_full64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  unsigned int r;
+
+  /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
+     situation we recognize and report.  */
+  if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
+      == THREAD_GETMEM (THREAD_SELF, tid)))
+    return EDEADLK;
+
+  /* If we prefer writers, recursive rdlock is disallowed, we are in a read
+     phase, and there are other readers present, we try to wait without
+     extending the read phase.  We will be unblocked by either one of the
+     other active readers, or if the writer gives up WRLOCKED (e.g., on
+     timeout).
+     If there are no other readers, we simply race with any existing primary
+     writer; it would have been a race anyway, and changing the odds slightly
+     will likely not make a big difference.  */
+  if (rwlock->__data.__flags == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
+    {
+      r = atomic_load_relaxed (&rwlock->__data.__readers);
+      while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+	      && ((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
+	      && ((r >> PTHREAD_RWLOCK_READER_SHIFT) > 0))
+	{
+	  /* TODO Spin first.  */
+	  /* Try setting the flag signaling that we are waiting without having
+	     incremented the number of readers.  Relaxed MO is fine because
+	     this is just about waiting for a state change in __readers.  */
+	  if (atomic_compare_exchange_weak_relaxed
+	      (&rwlock->__data.__readers, &r, r | PTHREAD_RWLOCK_RWAITING))
+	    {
+	      /* Wait for as long as the flag is set.  An ABA situation is
+		 harmless because the flag is just about the state of
+		 __readers, and all threads set the flag under the same
+		 conditions.  */
+	      while ((atomic_load_relaxed (&rwlock->__data.__readers)
+		  & PTHREAD_RWLOCK_RWAITING) != 0)
+		{
+		  int private = __pthread_rwlock_get_private (rwlock);
+		  int err = futex_abstimed_wait64 (&rwlock->__data.__readers,
+		      r, abstime, private);
+		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
+		     return because we don't need to clean up anything.  */
+		  if (err == ETIMEDOUT)
+		    return err;
+		}
+	      /* It makes sense to not break out of the outer loop here
+		 because we might be in the same situation again.  */
+	    }
+	  else
+	    {
+	      /* TODO Back-off.  */
+	    }
+	}
+    }
+  /* Register as a reader, using an add-and-fetch so that R can be used as
+     expected value for future operations.  Acquire MO so we synchronize with
+     prior writers as well as the last reader of the previous read phase (see
+     below).  */
+  r = atomic_fetch_add_acquire (&rwlock->__data.__readers,
+      (1 << PTHREAD_RWLOCK_READER_SHIFT)) + (1 << PTHREAD_RWLOCK_READER_SHIFT);
+
+  /* Check whether there is an overflow in the number of readers.  We assume
+     that the total number of threads is less than half the maximum number
+     of readers that we have bits for in __readers (i.e., with 32-bit int and
+     PTHREAD_RWLOCK_READER_SHIFT of 3, we assume there are less than
+     1 << (32-3-1) concurrent threads).
+     If there is an overflow, we use a CAS to try to decrement the number of
+     readers if there still is an overflow situation.  If so, we return
+     EAGAIN; if not, we are not a thread causing an overflow situation, and so
+     we just continue.  Using a fetch-add instead of the CAS isn't possible
+     because other readers might release the lock concurrently, which could
+     make us the last reader and thus responsible for handing ownership over
+     to writers (which requires a CAS too to make the decrement and ownership
+     transfer indivisible).  */
+  while (__glibc_unlikely (r >= PTHREAD_RWLOCK_READER_OVERFLOW))
+    {
+      /* Relaxed MO is okay because we just want to undo our registration and
+	 cannot have changed the rwlock state substantially if the CAS
+	 succeeds.  */
+      if (atomic_compare_exchange_weak_relaxed (&rwlock->__data.__readers, &r,
+	  r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
+	return EAGAIN;
+    }
+
+  /* We have registered as a reader, so if we are in a read phase, we have
+     acquired a read lock.  This is also the reader--reader fast-path.
+     Even if there is a primary writer, we just return.  If writers are to
+     be preferred and we are the only active reader, we could try to enter a
+     write phase to let the writer proceed.  This would be okay because we
+     cannot have acquired the lock previously as a reader (which could result
+     in deadlock if we would wait for the primary writer to run).  However,
+     this seems to be a corner case and handling it specially not be worth the
+     complexity.  */
+  if (__glibc_likely ((r & PTHREAD_RWLOCK_WRPHASE) == 0))
+    return 0;
+
+  /* If there is no primary writer but we are in a write phase, we can try
+     to install a read phase ourself.  */
+  while (((r & PTHREAD_RWLOCK_WRPHASE) != 0)
+      && ((r & PTHREAD_RWLOCK_WRLOCKED) == 0))
+    {
+       /* Try to enter a read phase: If the CAS below succeeds, we have
+	 ownership; if it fails, we will simply retry and reassess the
+	 situation.
+	 Acquire MO so we synchronize with prior writers.  */
+      if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
+	  r ^ PTHREAD_RWLOCK_WRPHASE))
+	{
+	  /* We started the read phase, so we are also responsible for
+	     updating the write-phase futex.  Relaxed MO is sufficient.
+	     Note that there can be no other reader that we have to wake
+	     because all other readers will see the read phase started by us
+	     (or they will try to start it themselves); if a writer started
+	     the read phase, we cannot have started it.  Furthermore, we
+	     cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
+	     overwrite the value set by the most recent writer (or the readers
+	     before it in case of explicit hand-over) and we know that there
+	     are no waiting readers.  */
+	  atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
+	  return 0;
+	}
+      else
+	{
+	  /* TODO Back off before retrying.  Also see above.  */
+	}
+    }
+
+  if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
+    {
+      /* We are in a write phase, and there must be a primary writer because
+	 of the previous loop.  Block until the primary writer gives up the
+	 write phase.  This case requires explicit hand-over using
+	 __wrphase_futex.
+	 However, __wrphase_futex might not have been set to 1 yet (either
+	 because explicit hand-over to the writer is still ongoing, or because
+	 the writer has started the write phase but does not yet have updated
+	 __wrphase_futex).  The least recent value of __wrphase_futex we can
+	 read from here is the modification of the last read phase (because
+	 we synchronize with the last reader in this read phase through
+	 __readers; see the use of acquire MO on the fetch_add above).
+	 Therefore, if we observe a value of 0 for __wrphase_futex, we need
+	 to subsequently check that __readers now indicates a read phase; we
+	 need to use acquire MO for this so that if we observe a read phase,
+	 we will also see the modification of __wrphase_futex by the previous
+	 writer.  We then need to load __wrphase_futex again and continue to
+	 wait if it is not 0, so that we do not skip explicit hand-over.
+	 Relaxed MO is sufficient for the load from __wrphase_futex because
+	 we just use it as an indicator for when we can proceed; we use
+	 __readers and the acquire MO accesses to it to eventually read from
+	 the proper stores to __wrphase_futex.  */
+      unsigned int wpf;
+      bool ready = false;
+      for (;;)
+	{
+	  while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
+	      | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
+	    {
+	      int private = __pthread_rwlock_get_private (rwlock);
+	      if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
+		  && !atomic_compare_exchange_weak_relaxed
+		      (&rwlock->__data.__wrphase_futex,
+		       &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))
+		continue;
+	      int err = futex_abstimed_wait64 (&rwlock->__data.__wrphase_futex,
+		  1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+	      if (err == ETIMEDOUT)
+		{
+		  /* If we timed out, we need to unregister.  If no read phase
+		     has been installed while we waited, we can just decrement
+		     the number of readers.  Otherwise, we just acquire the
+		     lock, which is allowed because we give no precise timing
+		     guarantees, and because the timeout is only required to
+		     be in effect if we would have had to wait for other
+		     threads (e.g., if futex_wait would time-out immediately
+		     because the given absolute time is in the past).  */
+		  r = atomic_load_relaxed (&rwlock->__data.__readers);
+		  while ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
+		    {
+		      /* We don't need to make anything else visible to
+			 others besides unregistering, so relaxed MO is
+			 sufficient.  */
+		      if (atomic_compare_exchange_weak_relaxed
+			  (&rwlock->__data.__readers, &r,
+			   r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
+			return ETIMEDOUT;
+		      /* TODO Back-off.  */
+		    }
+		  /* Use the acquire MO fence to mirror the steps taken in the
+		     non-timeout case.  Note that the read can happen both
+		     in the atomic_load above as well as in the failure case
+		     of the CAS operation.  */
+		  atomic_thread_fence_acquire ();
+		  /* We still need to wait for explicit hand-over, but we must
+		     not use futex_wait anymore because we would just time out
+		     in this case and thus make the spin-waiting we need
+		     unnecessarily expensive.  */
+		  while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex)
+		      | PTHREAD_RWLOCK_FUTEX_USED)
+		      == (1 | PTHREAD_RWLOCK_FUTEX_USED))
+		    {
+		      /* TODO Back-off?  */
+		    }
+		  ready = true;
+		  break;
+		}
+	      /* If we got interrupted (EINTR) or the futex word does not have the
+		 expected value (EAGAIN), retry.  */
+	    }
+	  if (ready)
+	    /* See below.  */
+	    break;
+	  /* We need acquire MO here so that we synchronize with the lock
+	     release of the writer, and so that we observe a recent value of
+	     __wrphase_futex (see below).  */
+	  if ((atomic_load_acquire (&rwlock->__data.__readers)
+	      & PTHREAD_RWLOCK_WRPHASE) == 0)
+	    /* We are in a read phase now, so the least recent modification of
+	       __wrphase_futex we can read from is the store by the writer
+	       with value 1.  Thus, only now we can assume that if we observe
+	       a value of 0, explicit hand-over is finished. Retry the loop
+	       above one more time.  */
+	    ready = true;
+	}
+    }
+
+  return 0;
+}
+
 
 static __always_inline void
 __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
@@ -924,3 +1158,360 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
       THREAD_GETMEM (THREAD_SELF, tid));
   return 0;
 }
+
+/* 64-bit time version */
+
+static __always_inline int
+__pthread_rwlock_wrlock_full64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
+     situation we recognize and report.  */
+  if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
+      == THREAD_GETMEM (THREAD_SELF, tid)))
+    return EDEADLK;
+
+  /* First we try to acquire the role of primary writer by setting WRLOCKED;
+     if it was set before, there already is a primary writer.  Acquire MO so
+     that we synchronize with previous primary writers.
+
+     We do not try to change to a write phase right away using a fetch_or
+     because we would have to reset it again and wake readers if there are
+     readers present (some readers could try to acquire the lock more than
+     once, so setting a write phase in the middle of this could cause
+     deadlock).  Changing to a write phase eagerly would only speed up the
+     transition from a read phase to a write phase in the uncontended case,
+     but it would slow down the contended case if readers are preferred (which
+     is the default).
+     We could try to CAS from a state with no readers to a write phase, but
+     this could be less scalable if readers arrive and leave frequently.  */
+  bool may_share_futex_used_flag = false;
+  unsigned int r = atomic_fetch_or_acquire (&rwlock->__data.__readers,
+      PTHREAD_RWLOCK_WRLOCKED);
+  if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRLOCKED) != 0))
+    {
+      /* There is another primary writer.  */
+      bool prefer_writer =
+	  (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP);
+      if (prefer_writer)
+	{
+	  /* We register as a waiting writer, so that we can make use of
+	     writer--writer hand-over.  Relaxed MO is fine because we just
+	     want to register.  We assume that the maximum number of threads
+	     is less than the capacity in __writers.  */
+	  atomic_fetch_add_relaxed (&rwlock->__data.__writers, 1);
+	}
+      for (;;)
+	{
+	  /* TODO Spin until WRLOCKED is 0 before trying the CAS below.
+	     But pay attention to not delay trying writer--writer hand-over
+	     for too long (which we must try eventually anyway).  */
+	  if ((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
+	    {
+	      /* Try to become the primary writer or retry.  Acquire MO as in
+		 the fetch_or above.  */
+	      if (atomic_compare_exchange_weak_acquire
+		  (&rwlock->__data.__readers, &r,
+		      r | PTHREAD_RWLOCK_WRLOCKED))
+		{
+		  if (prefer_writer)
+		    {
+		      /* Unregister as a waiting writer.  Note that because we
+			 acquired WRLOCKED, WRHANDOVER will not be set.
+			 Acquire MO on the CAS above ensures that
+			 unregistering happens after the previous writer;
+			 this sorts the accesses to __writers by all
+			 primary writers in a useful way (e.g., any other
+			 primary writer acquiring after us or getting it from
+			 us through WRHANDOVER will see both our changes to
+			 __writers).
+			 ??? Perhaps this is not strictly necessary for
+			 reasons we do not yet know of.  */
+		      atomic_fetch_add_relaxed (&rwlock->__data.__writers,
+			  -1);
+		    }
+		  break;
+		}
+	      /* Retry if the CAS fails (r will have been updated).  */
+	      continue;
+	    }
+	  /* If writer--writer hand-over is available, try to become the
+	     primary writer this way by grabbing the WRHANDOVER token.  If we
+	     succeed, we own WRLOCKED.  */
+	  if (prefer_writer)
+	    {
+	      unsigned int w = atomic_load_relaxed
+		  (&rwlock->__data.__writers);
+	      if ((w & PTHREAD_RWLOCK_WRHANDOVER) != 0)
+		{
+		  /* Acquire MO is required here so that we synchronize with
+		     the writer that handed over WRLOCKED.  We also need this
+		     for the reload of __readers below because our view of
+		     __readers must be at least as recent as the view of the
+		     writer that handed over WRLOCKED; we must avoid an ABA
+		     through WRHANDOVER, which could, for example, lead to us
+		     assuming we are still in a write phase when in fact we
+		     are not.  */
+		  if (atomic_compare_exchange_weak_acquire
+		      (&rwlock->__data.__writers,
+		       &w, (w - PTHREAD_RWLOCK_WRHANDOVER - 1)))
+		    {
+		      /* Reload so our view is consistent with the view of
+			 the previous owner of WRLOCKED.  See above.  */
+		      r = atomic_load_relaxed (&rwlock->__data.__readers);
+		      break;
+		    }
+		  /* We do not need to reload __readers here.  We should try
+		     to perform writer--writer hand-over if possible; if it
+		     is not possible anymore, we will reload __readers
+		     elsewhere in this loop.  */
+		  continue;
+		}
+	    }
+	  /* We did not acquire WRLOCKED nor were able to use writer--writer
+	     hand-over, so we block on __writers_futex.  */
+	  int private = __pthread_rwlock_get_private (rwlock);
+	  unsigned int wf = atomic_load_relaxed
+	      (&rwlock->__data.__writers_futex);
+	  if (((wf & ~(unsigned int) PTHREAD_RWLOCK_FUTEX_USED) != 1)
+	      || ((wf != (1 | PTHREAD_RWLOCK_FUTEX_USED))
+		  && !atomic_compare_exchange_weak_relaxed
+		      (&rwlock->__data.__writers_futex, &wf,
+		       1 | PTHREAD_RWLOCK_FUTEX_USED)))
+	    {
+	      /* If we cannot block on __writers_futex because there is no
+		 primary writer, or we cannot set PTHREAD_RWLOCK_FUTEX_USED,
+		 we retry.  We must reload __readers here in case we cannot
+		 block on __writers_futex so that we can become the primary
+		 writer and are not stuck in a loop that just continuously
+		 fails to block on __writers_futex.  */
+	      r = atomic_load_relaxed (&rwlock->__data.__readers);
+	      continue;
+	    }
+	  /* We set the flag that signals that the futex is used, or we could
+	     have set it if we had been faster than other waiters.  As a
+	     result, we may share the flag with an unknown number of other
+	     writers.  Therefore, we must keep this flag set when we acquire
+	     the lock.  We do not need to do this when we do not reach this
+	     point here because then we are not part of the group that may
+	     share the flag, and another writer will wake one of the writers
+	     in this group.  */
+	  may_share_futex_used_flag = true;
+	  int err = futex_abstimed_wait64 (&rwlock->__data.__writers_futex,
+	      1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+	  if (err == ETIMEDOUT)
+	    {
+	      if (prefer_writer)
+		{
+		  /* We need to unregister as a waiting writer.  If we are the
+		     last writer and writer--writer hand-over is available,
+		     we must make use of it because nobody else will reset
+		     WRLOCKED otherwise.  (If we use it, we simply pretend
+		     that this happened before the timeout; see
+		     pthread_rwlock_rdlock_full for the full reasoning.)
+		     Also see the similar code above.  */
+		  unsigned int w = atomic_load_relaxed
+		      (&rwlock->__data.__writers);
+		  while (!atomic_compare_exchange_weak_acquire
+		      (&rwlock->__data.__writers, &w,
+			  (w == PTHREAD_RWLOCK_WRHANDOVER + 1 ? 0 : w - 1)))
+		    {
+		      /* TODO Back-off.  */
+		    }
+		  if (w == PTHREAD_RWLOCK_WRHANDOVER + 1)
+		    {
+		      /* We must continue as primary writer.  See above.  */
+		      r = atomic_load_relaxed (&rwlock->__data.__readers);
+		      break;
+		    }
+		}
+	      /* We cleaned up and cannot have stolen another waiting writer's
+		 futex wake-up, so just return.  */
+	      return ETIMEDOUT;
+	    }
+	  /* If we got interrupted (EINTR) or the futex word does not have the
+	     expected value (EAGAIN), retry after reloading __readers.  */
+	  r = atomic_load_relaxed (&rwlock->__data.__readers);
+	}
+      /* Our snapshot of __readers is up-to-date at this point because we
+	 either set WRLOCKED using a CAS or were handed over WRLOCKED from
+	 another writer whose snapshot of __readers we inherit.  */
+    }
+
+  /* If we are in a read phase and there are no readers, try to start a write
+     phase.  */
+  while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+      && ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0))
+    {
+      /* Acquire MO so that we synchronize with prior writers and do
+	 not interfere with their updates to __writers_futex, as well
+	 as regarding prior readers and their updates to __wrphase_futex,
+	 respectively.  */
+      if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
+	  &r, r | PTHREAD_RWLOCK_WRPHASE))
+	{
+	  /* We have started a write phase, so need to enable readers to wait.
+	     See the similar case in__pthread_rwlock_rdlock_full.  */
+	  atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
+	  /* Make sure we fall through to the end of the function.  */
+	  r |= PTHREAD_RWLOCK_WRPHASE;
+	  break;
+	}
+      /* TODO Back-off.  */
+    }
+
+  /* We are the primary writer; enable blocking on __writers_futex.  Relaxed
+     MO is sufficient for futex words; acquire MO on the previous
+     modifications of __readers ensures that this store happens after the
+     store of value 0 by the previous primary writer.  */
+  atomic_store_relaxed (&rwlock->__data.__writers_futex,
+      1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0));
+
+  if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRPHASE) == 0))
+    {
+      /* We are not in a read phase and there are readers (because of the
+	 previous loop).  Thus, we have to wait for explicit hand-over from
+	 one of these readers.
+	 We basically do the same steps as for the similar case in
+	 __pthread_rwlock_rdlock_full, except that we additionally might try
+	 to directly hand over to another writer and need to wake up
+	 other writers or waiting readers (i.e., PTHREAD_RWLOCK_RWAITING).  */
+      unsigned int wpf;
+      bool ready = false;
+      for (;;)
+	{
+	  while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
+	      | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED)
+	    {
+	      int private = __pthread_rwlock_get_private (rwlock);
+	      if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
+		  && !atomic_compare_exchange_weak_relaxed
+		      (&rwlock->__data.__wrphase_futex, &wpf,
+		       PTHREAD_RWLOCK_FUTEX_USED))
+		continue;
+	      int err = futex_abstimed_wait64 (&rwlock->__data.__wrphase_futex,
+		  PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+	      if (err == ETIMEDOUT)
+		{
+		  if (rwlock->__data.__flags
+		      != PTHREAD_RWLOCK_PREFER_READER_NP)
+		    {
+		      /* We try writer--writer hand-over.  */
+		      unsigned int w = atomic_load_relaxed
+			  (&rwlock->__data.__writers);
+		      if (w != 0)
+			{
+			  /* We are about to hand over WRLOCKED, so we must
+			     release __writers_futex too; otherwise, we'd have
+			     a pending store, which could at least prevent
+			     other threads from waiting using the futex
+			     because it could interleave with the stores
+			     by subsequent writers.  In turn, this means that
+			     we have to clean up when we do not hand over
+			     WRLOCKED.
+			     Release MO so that another writer that gets
+			     WRLOCKED from us can take over our view of
+			     __readers.  */
+			  unsigned int wf = atomic_exchange_relaxed
+			      (&rwlock->__data.__writers_futex, 0);
+			  while (w != 0)
+			    {
+			      if (atomic_compare_exchange_weak_release
+				  (&rwlock->__data.__writers, &w,
+				      w | PTHREAD_RWLOCK_WRHANDOVER))
+				{
+				  /* Wake other writers.  */
+				  if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
+				    futex_wake
+					(&rwlock->__data.__writers_futex, 1,
+					 private);
+				  return ETIMEDOUT;
+				}
+			      /* TODO Back-off.  */
+			    }
+			  /* We still own WRLOCKED and someone else might set
+			     a write phase concurrently, so enable waiting
+			     again.  Make sure we don't loose the flag that
+			     signals whether there are threads waiting on
+			     this futex.  */
+			  atomic_store_relaxed
+			      (&rwlock->__data.__writers_futex, wf);
+			}
+		    }
+		  /* If we timed out and we are not in a write phase, we can
+		     just stop being a primary writer.  Otherwise, we just
+		     acquire the lock.  */
+		  r = atomic_load_relaxed (&rwlock->__data.__readers);
+		  if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+		    {
+		      /* We are about to release WRLOCKED, so we must release
+			 __writers_futex too; see the handling of
+			 writer--writer hand-over above.  */
+		      unsigned int wf = atomic_exchange_relaxed
+			  (&rwlock->__data.__writers_futex, 0);
+		      while ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+			{
+			  /* While we don't need to make anything from a
+			     caller's critical section visible to other
+			     threads, we need to ensure that our changes to
+			     __writers_futex are properly ordered.
+			     Therefore, use release MO to synchronize with
+			     subsequent primary writers.  Also wake up any
+			     waiting readers as they are waiting because of
+			     us.  */
+			  if (atomic_compare_exchange_weak_release
+			      (&rwlock->__data.__readers, &r,
+			       (r ^ PTHREAD_RWLOCK_WRLOCKED)
+			       & ~(unsigned int) PTHREAD_RWLOCK_RWAITING))
+			    {
+			      /* Wake other writers.  */
+			      if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
+				futex_wake (&rwlock->__data.__writers_futex,
+				    1, private);
+			      /* Wake waiting readers.  */
+			      if ((r & PTHREAD_RWLOCK_RWAITING) != 0)
+				futex_wake (&rwlock->__data.__readers,
+				    INT_MAX, private);
+			      return ETIMEDOUT;
+			    }
+			}
+		      /* We still own WRLOCKED and someone else might set a
+			 write phase concurrently, so enable waiting again.
+			 Make sure we don't loose the flag that signals
+			 whether there are threads waiting on this futex.  */
+		      atomic_store_relaxed (&rwlock->__data.__writers_futex,
+			  wf);
+		    }
+		  /* Use the acquire MO fence to mirror the steps taken in the
+		     non-timeout case.  Note that the read can happen both
+		     in the atomic_load above as well as in the failure case
+		     of the CAS operation.  */
+		  atomic_thread_fence_acquire ();
+		  /* We still need to wait for explicit hand-over, but we must
+		     not use futex_wait anymore.  */
+		  while ((atomic_load_relaxed
+		      (&rwlock->__data.__wrphase_futex)
+		       | PTHREAD_RWLOCK_FUTEX_USED)
+		      == PTHREAD_RWLOCK_FUTEX_USED)
+		    {
+		      /* TODO Back-off.  */
+		    }
+		  ready = true;
+		  break;
+		}
+	      /* If we got interrupted (EINTR) or the futex word does not have
+		 the expected value (EAGAIN), retry.  */
+	    }
+	  /* See pthread_rwlock_rdlock_full.  */
+	  if (ready)
+	    break;
+	  if ((atomic_load_acquire (&rwlock->__data.__readers)
+	      & PTHREAD_RWLOCK_WRPHASE) != 0)
+	    ready = true;
+	}
+    }
+
+  atomic_store_relaxed (&rwlock->__data.__cur_writer,
+      THREAD_GETMEM (THREAD_SELF, tid));
+  return 0;
+}
diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c
index 383e41e..90e8eaa 100644
--- a/nptl/pthread_rwlock_timedrdlock.c
+++ b/nptl/pthread_rwlock_timedrdlock.c
@@ -35,3 +35,22 @@ pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
 
   return __pthread_rwlock_rdlock_full (rwlock, abstime);
 }
+
+/* 64-bit time version */
+
+int
+__pthread_rwlock_timedrdlock64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  /* Make sure the passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  /* ??? Just move this to __pthread_rwlock_rdlock_full?  */
+  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
+  return __pthread_rwlock_rdlock_full64 (rwlock, abstime);
+}
diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
index 7a3d2ec..d4b32aa 100644
--- a/nptl/pthread_rwlock_timedwrlock.c
+++ b/nptl/pthread_rwlock_timedwrlock.c
@@ -35,3 +35,22 @@ pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
 
   return __pthread_rwlock_wrlock_full (rwlock, abstime);
 }
+
+/* 64-bit time version */
+
+int
+__pthread_rwlock_timedwrlock64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  /* Make sure the passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  /* ??? Just move this to __pthread_rwlock_wrlock_full?  */
+  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
+  return __pthread_rwlock_wrlock_full64 (rwlock, abstime);
+}
diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
index 8886ea2..8a6bfba 100644
--- a/nptl/sem_timedwait.c
+++ b/nptl/sem_timedwait.c
@@ -38,3 +38,21 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
   else
     return __new_sem_wait_slow((struct new_sem *) sem, abstime);
 }
+
+int
+__sem_timedwait64 (sem_t *sem, const struct __timespec64 *abstime)
+{
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  /* Check sem_wait.c for a more detailed explanation why it is required.  */
+  __pthread_testcancel ();
+
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow64 ((struct new_sem *) sem, abstime);
+}
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index e7d9106..f59f7f4 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -43,6 +43,30 @@ __new_sem_wait (sem_t *sem)
 }
 versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
 
+/* 64-bit time version */
+
+int
+__new_sem_wait64 (sem_t *sem)
+{
+  /* We need to check whether we need to act upon a cancellation request here
+     because POSIX specifies that cancellation points "shall occur" in
+     sem_wait and sem_timedwait, which also means that they need to check
+     this regardless whether they block or not (unlike "may occur"
+     functions).  See the POSIX Rationale for this requirement: Section
+     "Thread Cancellation Overview" [1] and austin group issue #1076 [2]
+     for thoughs on why this may be a suboptimal design.
+
+     [1] http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html
+     [2] http://austingroupbugs.net/view.php?id=1076 for thoughts on why this
+   */
+  __pthread_testcancel ();
+
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow64 ((struct new_sem *) sem, NULL);
+}
+
 #if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
 int
 attribute_compat_text_section
diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
index 30984be..c75c74b 100644
--- a/nptl/sem_waitcommon.c
+++ b/nptl/sem_waitcommon.c
@@ -119,6 +119,24 @@ do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
   return err;
 }
 
+static int
+__attribute__ ((noinline))
+do_futex_wait64 (struct new_sem *sem, const struct __timespec64 *abstime)
+{
+  int err;
+
+#if __HAVE_64B_ATOMICS
+  err = futex_abstimed_wait_cancelable64 (
+      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
+      sem->private);
+#else
+  err = futex_abstimed_wait_cancelable64 (&sem->value, SEM_NWAITERS_MASK,
+					abstime, sem->private);
+#endif
+
+  return err;
+}
+
 /* Fast path: Try to grab a token without blocking.  */
 static int
 __new_sem_wait_fast (struct new_sem *sem, int definitive_result)
@@ -310,6 +328,160 @@ error:
   return err;
 }
 
+/* 64-bit time version */
+
+static int
+__attribute__ ((noinline))
+__new_sem_wait_slow64 (struct new_sem *sem, const struct __timespec64 *abstime)
+{
+  int err = 0;
+
+#if __HAVE_64B_ATOMICS
+  /* Add a waiter.  Relaxed MO is sufficient because we can rely on the
+     ordering provided by the RMW operations we use.  */
+  uint64_t d = atomic_fetch_add_relaxed (&sem->data,
+      (uint64_t) 1 << SEM_NWAITERS_SHIFT);
+
+  pthread_cleanup_push (__sem_wait_cleanup, sem);
+
+  /* Wait for a token to be available.  Retry until we can grab one.  */
+  for (;;)
+    {
+      /* If there is no token available, sleep until there is.  */
+      if ((d & SEM_VALUE_MASK) == 0)
+	{
+	  err = do_futex_wait64 (sem, abstime);
+	  /* A futex return value of 0 or EAGAIN is due to a real or spurious
+	     wake-up, or due to a change in the number of tokens.  We retry in
+	     these cases.
+	     If we timed out, forward this to the caller.
+	     EINTR is returned if we are interrupted by a signal; we
+	     forward this to the caller.  (See futex_wait and related
+	     documentation.  Before Linux 2.6.22, EINTR was also returned on
+	     spurious wake-ups; we only support more recent Linux versions,
+	     so do not need to consider this here.)  */
+	  if (err == ETIMEDOUT || err == EINTR)
+	    {
+	      __set_errno (err);
+	      err = -1;
+	      /* Stop being registered as a waiter.  */
+	      atomic_fetch_add_relaxed (&sem->data,
+		  -((uint64_t) 1 << SEM_NWAITERS_SHIFT));
+	      break;
+	    }
+	  /* Relaxed MO is sufficient; see below.  */
+	  d = atomic_load_relaxed (&sem->data);
+	}
+      else
+	{
+	  /* Try to grab both a token and stop being a waiter.  We need
+	     acquire MO so this synchronizes with all token providers (i.e.,
+	     the RMW operation we read from or all those before it in
+	     modification order; also see sem_post).  On the failure path,
+	     relaxed MO is sufficient because we only eventually need the
+	     up-to-date value; the futex_wait or the CAS perform the real
+	     work.  */
+	  if (atomic_compare_exchange_weak_acquire (&sem->data,
+	      &d, d - 1 - ((uint64_t) 1 << SEM_NWAITERS_SHIFT)))
+	    {
+	      err = 0;
+	      break;
+	    }
+	}
+    }
+
+  pthread_cleanup_pop (0);
+#else
+  /* The main difference to the 64b-atomics implementation is that we need to
+     access value and nwaiters in separate steps, and that the nwaiters bit
+     in the value can temporarily not be set even if nwaiters is nonzero.
+     We work around incorrectly unsetting the nwaiters bit by letting sem_wait
+     set the bit again and waking the number of waiters that could grab a
+     token.  There are two additional properties we need to ensure:
+     (1) We make sure that whenever unsetting the bit, we see the increment of
+     nwaiters by the other thread that set the bit.  IOW, we will notice if
+     we make a mistake.
+     (2) When setting the nwaiters bit, we make sure that we see the unsetting
+     of the bit by another waiter that happened before us.  This avoids having
+     to blindly set the bit whenever we need to block on it.  We set/unset
+     the bit while having incremented nwaiters (i.e., are a registered
+     waiter), and the problematic case only happens when one waiter indeed
+     followed another (i.e., nwaiters was never larger than 1); thus, this
+     works similarly as with a critical section using nwaiters (see the MOs
+     and related comments below).
+
+     An alternative approach would be to unset the bit after decrementing
+     nwaiters; however, that would result in needing Dekker-like
+     synchronization and thus full memory barriers.  We also would not be able
+     to prevent misspeculation, so this alternative scheme does not seem
+     beneficial.  */
+  unsigned int v;
+
+  /* Add a waiter.  We need acquire MO so this synchronizes with the release
+     MO we use when decrementing nwaiters below; it ensures that if another
+     waiter unset the bit before us, we see that and set it again.  Also see
+     property (2) above.  */
+  atomic_fetch_add_acquire (&sem->nwaiters, 1);
+
+  pthread_cleanup_push (__sem_wait_cleanup, sem);
+
+  /* Wait for a token to be available.  Retry until we can grab one.  */
+  /* We do not need any ordering wrt. to this load's reads-from, so relaxed
+     MO is sufficient.  The acquire MO above ensures that in the problematic
+     case, we do see the unsetting of the bit by another waiter.  */
+  v = atomic_load_relaxed (&sem->value);
+  do
+    {
+      do
+	{
+	  /* We are about to block, so make sure that the nwaiters bit is
+	     set.  We need release MO on the CAS to ensure that when another
+	     waiter unsets the nwaiters bit, it will also observe that we
+	     incremented nwaiters in the meantime (also see the unsetting of
+	     the bit below).  Relaxed MO on CAS failure is sufficient (see
+	     above).  */
+	  do
+	    {
+	      if ((v & SEM_NWAITERS_MASK) != 0)
+		break;
+	    }
+	  while (!atomic_compare_exchange_weak_release (&sem->value,
+	      &v, v | SEM_NWAITERS_MASK));
+	  /* If there is no token, wait.  */
+	  if ((v >> SEM_VALUE_SHIFT) == 0)
+	    {
+	      /* See __HAVE_64B_ATOMICS variant.  */
+	      err = do_futex_wait64 (sem, abstime);
+	      if (err == ETIMEDOUT || err == EINTR)
+		{
+		  __set_errno (err);
+		  err = -1;
+		  goto error;
+		}
+	      err = 0;
+	      /* We blocked, so there might be a token now.  Relaxed MO is
+		 sufficient (see above).  */
+	      v = atomic_load_relaxed (&sem->value);
+	    }
+	}
+      /* If there is no token, we must not try to grab one.  */
+      while ((v >> SEM_VALUE_SHIFT) == 0);
+    }
+  /* Try to grab a token.  We need acquire MO so this synchronizes with
+     all token providers (i.e., the RMW operation we read from or all those
+     before it in modification order; also see sem_post).  */
+  while (!atomic_compare_exchange_weak_acquire (&sem->value,
+      &v, v - (1 << SEM_VALUE_SHIFT)));
+
+error:
+  pthread_cleanup_pop (0);
+
+  __sem_wait_32_finish (sem);
+#endif
+
+  return err;
+}
+
 /* Stop being a registered waiter (non-64b-atomics code only).  */
 #if !__HAVE_64B_ATOMICS
 static void
diff --git a/rt/Versions b/rt/Versions
index 1170133..9c464dd 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -44,5 +44,6 @@ librt {
    __timerfd_settime64;
    __mq_timedreceive64;
    __mq_timedsend_time64;
+   __aio_suspend64;
   }
 }
diff --git a/sysdeps/nptl/aio_misc.h b/sysdeps/nptl/aio_misc.h
index 206d8e1..24c2852 100644
--- a/sysdeps/nptl/aio_misc.h
+++ b/sysdeps/nptl/aio_misc.h
@@ -71,4 +71,43 @@
       }									      \
   } while (0)
 
+#define AIO_MISC_WAIT_T64(result, futex, timeout, cancel)		      \
+  do {									      \
+    volatile unsigned int *futexaddr = &futex;				      \
+    unsigned int oldval = futex;					      \
+									      \
+    if (oldval != 0)							      \
+      {									      \
+	pthread_mutex_unlock (&__aio_requests_mutex);			      \
+									      \
+	int oldtype;							      \
+	if (cancel)							      \
+	  oldtype = LIBC_CANCEL_ASYNC ();				      \
+									      \
+	int status;							      \
+	do								      \
+	  {								      \
+	    status = futex_reltimed_wait64 ((unsigned int *) futexaddr,     \
+					      oldval, timeout, FUTEX_PRIVATE);\
+	    if (status != EAGAIN)					      \
+	      break;							      \
+									      \
+	    oldval = *futexaddr;					      \
+	  }								      \
+	while (oldval != 0);						      \
+									      \
+	if (cancel)							      \
+	  LIBC_CANCEL_RESET (oldtype);					      \
+									      \
+	if (status == EINTR)						      \
+	  result = EINTR;						      \
+	else if (status == ETIMEDOUT)					      \
+	  result = EAGAIN;						      \
+	else								      \
+	  assert (status == 0 || status == EAGAIN);			      \
+									      \
+	pthread_mutex_lock (&__aio_requests_mutex);			      \
+      }									      \
+  } while (0)
+
 #include_next <aio_misc.h>
diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h
index bfbda99..7784ce7 100644
--- a/sysdeps/nptl/lowlevellock.h
+++ b/sysdeps/nptl/lowlevellock.h
@@ -122,6 +122,10 @@ extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
 				 int private) attribute_hidden;
 
+extern int __lll_timedlock_wait64 (int *futex,
+                                     const struct __timespec64 *,
+				     int private) attribute_hidden;
+
 
 /* As __lll_lock, but with a timeout.  If the timeout occurs then return
    ETIMEDOUT.  If ABSTIME is invalid, return EINVAL.  */
@@ -138,6 +142,19 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *,
 #define lll_timedlock(futex, abstime, private)  \
   __lll_timedlock (&(futex), abstime, private)
 
+#define __lll_timedlock64(futex, abstime, private)                \
+  ({                                                                \
+    int *__futex = (futex);                                         \
+    int __val = 0;                                                  \
+                                                                    \
+    if (__glibc_unlikely                                            \
+        (atomic_compare_and_exchange_bool_acq (__futex, 1, 0)))     \
+      __val = __lll_timedlock_wait64 (__futex, abstime, private); \
+    __val;                                                          \
+  })
+#define lll_timedlock64(futex, abstime, private)  \
+  __lll_timedlock64 (&(futex), abstime, private)
+
 
 /* This is an expression rather than a statement even though its value is
    void, so that it can be used in a comma expression or as an expression
diff --git a/sysdeps/pthread/aio_suspend.c b/sysdeps/pthread/aio_suspend.c
index 010cbf8..a14263d 100644
--- a/sysdeps/pthread/aio_suspend.c
+++ b/sysdeps/pthread/aio_suspend.c
@@ -251,3 +251,167 @@ aio_suspend (const struct aiocb *const list[], int nent,
 }
 
 weak_alias (aio_suspend, aio_suspend64)
+
+#ifdef DONT_NEED_AIO_MISC_COND
+static int
+__attribute__ ((noinline))
+do_aio_misc_wait64 (unsigned int *cntr, 
+		      const struct __timespec64 *timeout)
+{
+  int result = 0;
+
+  AIO_MISC_WAIT_T64 (result, *cntr, timeout, 1);
+
+  return result;
+}
+#endif
+
+int
+__aio_suspend64 (const struct aiocb *const list[], int nent,
+	         const struct __timespec64 *timeout)
+{
+  if (__glibc_unlikely (nent < 0))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  struct waitlist waitlist[nent];
+  struct requestlist *requestlist[nent];
+#ifndef DONT_NEED_AIO_MISC_COND
+  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+#endif
+  int cnt;
+  bool any = false;
+  int result = 0;
+  unsigned int cntr = 1;
+
+  /* Request the mutex.  */
+  pthread_mutex_lock (&__aio_requests_mutex);
+
+  /* There is not yet a finished request.  Signal the request that
+     we are working for it.  */
+  for (cnt = 0; cnt < nent; ++cnt)
+    if (list[cnt] != NULL)
+      {
+	if (list[cnt]->__error_code == EINPROGRESS)
+	  {
+	    requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]);
+
+	    if (requestlist[cnt] != NULL)
+	      {
+#ifndef DONT_NEED_AIO_MISC_COND
+		waitlist[cnt].cond = &cond;
+#endif
+		waitlist[cnt].result = NULL;
+		waitlist[cnt].next = requestlist[cnt]->waiting;
+		waitlist[cnt].counterp = &cntr;
+		waitlist[cnt].sigevp = NULL;
+#ifdef BROKEN_THREAD_SIGNALS
+		waitlist[cnt].caller_pid = 0;	/* Not needed.  */
+#endif
+		requestlist[cnt]->waiting = &waitlist[cnt];
+		any = true;
+	      }
+	    else
+	      /* We will never suspend.  */
+	      break;
+	  }
+	else
+	  /* We will never suspend.  */
+	  break;
+      }
+
+
+  /* Only if none of the entries is NULL or finished to be wait.  */
+  if (cnt == nent && any)
+    {
+      struct clparam clparam =
+	{
+	  .list = list,
+	  .waitlist = waitlist,
+	  .requestlist = requestlist,
+#ifndef DONT_NEED_AIO_MISC_COND
+	  .cond = &cond,
+#endif
+	  .nent = nent
+	};
+
+      pthread_cleanup_push (cleanup, &clparam);
+
+#ifdef DONT_NEED_AIO_MISC_COND
+      result = do_aio_misc_wait64 (&cntr, timeout);
+#else
+      if (timeout == NULL)
+	result = pthread_cond_wait (&cond, &__aio_requests_mutex);
+      else
+	{
+	  /* We have to convert the relative timeout value into an
+	     absolute time value with pthread_cond_timedwait expects.  */
+	  struct timeval now;
+	  struct timespec abstime;
+
+	  __gettimeofday (&now, NULL);
+	  abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000;
+	  abstime.tv_sec = timeout->tv_sec + now.tv_sec;
+	  if (abstime.tv_nsec >= 1000000000)
+	    {
+	      abstime.tv_nsec -= 1000000000;
+	      abstime.tv_sec += 1;
+	    }
+
+	  result = __pthread_cond_timedwait64 (&cond,
+					       &__aio_requests_mutex,
+					       &abstime);
+	}
+#endif
+
+      pthread_cleanup_pop (0);
+    }
+
+  /* Now remove the entry in the waiting list for all requests
+     which didn't terminate.  */
+  while (cnt-- > 0)
+    if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS)
+      {
+	struct waitlist **listp;
+
+	assert (requestlist[cnt] != NULL);
+
+	/* There is the chance that we cannot find our entry anymore. This
+	   could happen if the request terminated and restarted again.  */
+	listp = &requestlist[cnt]->waiting;
+	while (*listp != NULL && *listp != &waitlist[cnt])
+	  listp = &(*listp)->next;
+
+	if (*listp != NULL)
+	  *listp = (*listp)->next;
+      }
+
+#ifndef DONT_NEED_AIO_MISC_COND
+  /* Release the conditional variable.  */
+  if (__glibc_unlikely (pthread_cond_destroy (&cond) != 0))
+    /* This must never happen.  */
+    abort ();
+#endif
+
+  if (result != 0)
+    {
+#ifndef DONT_NEED_AIO_MISC_COND
+      /* An error occurred.  Possibly it's ETIMEDOUT.  We have to translate
+	 the timeout error report of `pthread_cond_timedwait' to the
+	 form expected from `aio_suspend'.  */
+      if (result == ETIMEDOUT)
+	__set_errno (EAGAIN);
+      else
+#endif
+	__set_errno (result);
+
+      result = -1;
+    }
+
+  /* Release the mutex.  */
+  pthread_mutex_unlock (&__aio_requests_mutex);
+
+  return result;
+}
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index 85bb1de..673f11d 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -6,6 +6,11 @@ GLIBC_2.12 pthread_mutexattr_setrobust F
 GLIBC_2.12 pthread_setname_np F
 GLIBC_2.18 pthread_getattr_default_np F
 GLIBC_2.18 pthread_setattr_default_np F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __pthread_cond_timedwait64 F
+GLIBC_2.28 __pthread_mutex_timedlock64 F
+GLIBC_2.28 __sem_timedwait64 F
+GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
 GLIBC_2.4 _IO_funlockfile F
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index d99df62..9e7647b 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,4 +1,5 @@
 GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __aio_suspend64 F
 GLIBC_2.28 __mq_timedreceive64 F
 GLIBC_2.28 __mq_timedsend_time64 F
 GLIBC_2.28 __timer_gettime64 F
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
index 96a07b0..484c8be 100644
--- a/sysdeps/unix/sysv/linux/futex-internal.h
+++ b/sysdeps/unix/sysv/linux/futex-internal.h
@@ -131,6 +131,32 @@ futex_reltimed_wait (unsigned int *futex_word, unsigned int expected,
     }
 }
 
+/* 64-bit time version */
+static __always_inline int
+futex_reltimed_wait64 (unsigned int *futex_word, unsigned int expected,
+		         const struct __timespec64 *reltime, int private)
+{
+  int err = lll_futex_timed_wait64 (futex_word, expected, reltime,
+                                      private);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
 futex_reltimed_wait_cancelable (unsigned int *futex_word,
@@ -160,6 +186,37 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
     }
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+futex_reltimed_wait_cancelable64 (unsigned int *futex_word,
+				    unsigned int expected,
+			            const struct __timespec64 *reltime,
+                                    int private)
+{
+  int oldtype;
+  oldtype = __pthread_enable_asynccancel ();
+  int err = lll_futex_timed_wait64 (futex_word, expected, reltime, private);
+  __pthread_disable_asynccancel (oldtype);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
 futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
@@ -190,6 +247,36 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
     }
 }
 
+/* 64-bit time version */
+static __always_inline int
+futex_abstimed_wait64 (unsigned int *futex_word, unsigned int expected,
+		         const struct __timespec64 *abstime, int private)
+{
+  /* Work around the fact that the kernel rejects negative timeout values
+     despite them being valid.  */
+  if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
+    return ETIMEDOUT;
+  int err = lll_futex_timed_wait_bitset64 (futex_word, expected, abstime,
+					     FUTEX_CLOCK_REALTIME, private);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
 futex_abstimed_wait_cancelable (unsigned int *futex_word,
@@ -224,6 +311,42 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
     }
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+futex_abstimed_wait_cancelable64 (unsigned int *futex_word,
+				    unsigned int expected,
+			            const struct __timespec64 *abstime,
+                                    int private)
+{
+  /* Work around the fact that the kernel rejects negative timeout values
+     despite them being valid.  */
+  if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
+    return ETIMEDOUT;
+  int oldtype;
+  oldtype = __pthread_enable_asynccancel ();
+  int err = lll_futex_timed_wait_bitset64 (futex_word, expected, abstime,
+					     FUTEX_CLOCK_REALTIME, private);
+  __pthread_disable_asynccancel (oldtype);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline void
 futex_wake (unsigned int *futex_word, int processes_to_wake, int private)
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index fc834ed..02fc2a5 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -82,6 +82,16 @@
 		     __lll_private_flag (FUTEX_WAIT, private),  \
 		     val, timeout)
 
+#define lll_futex_timed_wait64(futexp, val, timeout, private)     \
+  ({                                                                       \
+    struct timespec ts;                                                    \
+    ts.tv_sec = timeout->tv_sec;                                           \
+    ts.tv_nsec = timeout->tv_nsec;                                         \
+    lll_futex_syscall (4, futexp,                                 	   \
+		       __lll_private_flag (FUTEX_WAIT, private),  	   \
+		       val, &ts);					   \
+  })
+
 #define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
   lll_futex_syscall (6, futexp,                                         \
 		     __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
@@ -89,6 +99,18 @@
 		     val, timeout, NULL /* Unused.  */,                 \
 		     FUTEX_BITSET_MATCH_ANY)
 
+#define lll_futex_timed_wait_bitset64(futexp, val, timeout, clockbit, private) \
+  ({                                                                       \
+    struct timespec ts;                                                    \
+    ts.tv_sec = timeout->tv_sec;                                           \
+    ts.tv_nsec = timeout->tv_nsec;                                         \
+    lll_futex_syscall (6, futexp,                                          \
+		       __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
+		                           private),                       \
+		       val, &ts, NULL /* Unused.  */,                      \
+		       FUTEX_BITSET_MATCH_ANY);                            \
+  })
+
 #define lll_futex_wake(futexp, nr, private)                             \
   lll_futex_syscall (4, futexp,                                         \
 		     __lll_private_flag (FUTEX_WAKE, private), nr, 0)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index e51daee..099f51a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -206,6 +206,11 @@ GLIBC_2.2 pwrite64 F
 GLIBC_2.2 sem_timedwait F
 GLIBC_2.2.3 pthread_getattr_np F
 GLIBC_2.2.6 __nanosleep F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __pthread_cond_timedwait64 F
+GLIBC_2.28 __pthread_mutex_timedlock64 F
+GLIBC_2.28 __sem_timedwait64 F
+GLIBC_2.3.2 GLIBC_2.3.2 A
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
 GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index c85dc7c..06f478a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -28,6 +28,7 @@ GLIBC_2.2 timer_getoverrun F
 GLIBC_2.2 timer_gettime F
 GLIBC_2.2 timer_settime F
 GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __aio_suspend64 F
 GLIBC_2.28 __mq_timedreceive64 F
 GLIBC_2.28 __mq_timedsend_time64 F
 GLIBC_2.28 __timer_gettime64 F

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=05b8542d198fec7a1b3fdf6a8713c37c941df596

commit 05b8542d198fec7a1b3fdf6a8713c37c941df596
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:09 2017 +0200

    Y2038: add function __setitimer64

diff --git a/time/Makefile b/time/Makefile
index 01ee071..2bc2b80 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    gettimeofday settimeofday adjtime tzset	 \
 	    gettimeofday64 settimeofday64		 \
 	    tzfile getitimer setitimer			 \
-	    getitimer64					 \
+	    getitimer64 setitimer64			 \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
diff --git a/time/Versions b/time/Versions
index 709c5b1..c26ec45 100644
--- a/time/Versions
+++ b/time/Versions
@@ -88,5 +88,6 @@ libc {
     __adjtime64;
     __adjtimex64;
     __getitimer64;
+    __setitimer64;
   }
 }
diff --git a/time/setitimer64.c b/time/setitimer64.c
new file mode 100644
index 0000000..13133ad
--- /dev/null
+++ b/time/setitimer64.c
@@ -0,0 +1,64 @@
+/* Set an interval timer
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+/* Set the timer WHICH to *NEW.  If OLD is not NULL,
+   set *OLD to the old value of timer WHICH.
+   Returns 0 on success, -1 on errors.  */
+int
+__setitimer64 (enum __itimer_which which,
+                 const struct __itimerval64 *new,
+                 struct __itimerval64 *old)
+{
+  struct itimerval new32, *new32p = NULL;
+  struct itimerval old32, *old32p = NULL;
+
+  if (new != NULL)
+    {
+      if (new->it_interval.tv_sec > INT_MAX ||
+          new->it_value.tv_sec > INT_MAX)
+        {
+          __set_errno (EOVERFLOW);
+          return -1;
+        }
+      new32.it_interval.tv_sec = new->it_interval.tv_sec;
+      new32.it_interval.tv_usec = new->it_interval.tv_usec;
+      new32.it_value.tv_sec = new->it_value.tv_sec;
+      new32.it_value.tv_usec = new->it_value.tv_usec;
+      new32p = &new32;
+    }
+
+  if (old != NULL)
+    old32p = &old32;
+
+  int result = __setitimer(which, new32p, old32p);
+
+  if (old)
+    {
+      old->it_interval.tv_sec = old32.it_interval.tv_sec;
+      old->it_interval.tv_usec = old32.it_interval.tv_usec;
+      old->it_value.tv_sec = old32.it_value.tv_sec;
+      old->it_value.tv_usec = old32.it_value.tv_usec;
+    }
+
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1e018f28f04e5e8c768c8090df0caf8bd34a2403

commit 1e018f28f04e5e8c768c8090df0caf8bd34a2403
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:08 2017 +0200

    Y2038: add function __getitimer64

diff --git a/time/Makefile b/time/Makefile
index a38f640..01ee071 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,6 +37,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    gettimeofday settimeofday adjtime tzset	 \
 	    gettimeofday64 settimeofday64		 \
 	    tzfile getitimer setitimer			 \
+	    getitimer64					 \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
diff --git a/time/Versions b/time/Versions
index 5d79e15..709c5b1 100644
--- a/time/Versions
+++ b/time/Versions
@@ -87,5 +87,6 @@ libc {
     __utimes64;
     __adjtime64;
     __adjtimex64;
+    __getitimer64;
   }
 }
diff --git a/time/getitimer64.c b/time/getitimer64.c
new file mode 100644
index 0000000..68bcaef
--- /dev/null
+++ b/time/getitimer64.c
@@ -0,0 +1,46 @@
+/* Get the current value of an interval timer
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+/* Set *VALUE to the current setting of timer WHICH.
+   Return 0 on success, -1 on errors.  */
+int
+__getitimer64 (enum __itimer_which which,
+                 struct __itimerval64 *value)
+{
+  struct itimerval value32, *value32p= NULL;
+
+  if (value != NULL)
+    value32p = &value32;
+
+  int result = __getitimer(which, value32p);
+
+  if (result == 0 && value != NULL)
+    {
+      value->it_interval.tv_sec = value32.it_interval.tv_sec;
+      value->it_interval.tv_usec = value32.it_interval.tv_usec;
+      value->it_value.tv_sec = value32.it_value.tv_sec;
+      value->it_value.tv_usec = value32.it_value.tv_usec;
+    }
+
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=555f32792b82b0d49e0e62e08a0e3096f25680ce

commit 555f32792b82b0d49e0e62e08a0e3096f25680ce
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:07 2017 +0200

    Y2038: add struct __itimerval64

diff --git a/time/sys/time.h b/time/sys/time.h
index 4e6255e..b7fe339 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -110,6 +110,16 @@ struct itimerval
     struct timeval it_value;
   };
 
+/* 64-BIT-TIME Type of the second argument to `getitimer' and
+   the second and third arguments `setitimer'.  */
+struct __itimerval64
+  {
+    /* Value to put into `it_value' when the timer expires.  */
+    struct __timeval64 it_interval;
+    /* Time to the next timer expiration.  */
+    struct __timeval64 it_value;
+  };
+
 #if defined __USE_GNU && !defined __cplusplus
 /* Use the nicer parameter type only in GNU mode and not for C++ since the
    strict C++ rules prevent the automatic promotion.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5ae21adb847a4ec59ff4d63e0de6a3e142cd466e

commit 5ae21adb847a4ec59ff4d63e0de6a3e142cd466e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:06 2017 +0200

    Y2038: add function __utime64

diff --git a/include/utime.h b/include/utime.h
index 5049251..eb907f7 100644
--- a/include/utime.h
+++ b/include/utime.h
@@ -6,4 +6,11 @@
 libc_hidden_proto (utime)
 #endif
 
+/* Structure describing file times, 64-bit time version.  */
+struct __utimbuf64
+  {
+    __time64_t actime;		/* Access time.  */
+    __time64_t modtime;		/* Modification time.  */
+  };
+
 #endif /* utime.h */
diff --git a/io/Makefile b/io/Makefile
index 4a0d8fe..67cca96 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -28,7 +28,7 @@ headers := sys/stat.h bits/stat.h sys/statfs.h bits/statfs.h sys/vfs.h \
 	   utime.h ftw.h fts.h sys/sendfile.h
 
 routines :=								\
-	utime								\
+	utime utime64							\
 	mkfifo mkfifoat							\
 	stat fstat lstat stat64 fstat64 lstat64 fstatat fstatat64	\
 	xstat fxstat lxstat xstat64 fxstat64 lxstat64			\
diff --git a/io/Versions b/io/Versions
index eaeeca8..71583e6 100644
--- a/io/Versions
+++ b/io/Versions
@@ -142,5 +142,6 @@ libc {
     __xstat64_time64;
     __lxstat64_time64;
     __fxstatat64_time64;
+    __utime64;
   }
 }
diff --git a/io/utime.c b/io/utime.c
index 3f3c03c..b33296b 100644
--- a/io/utime.c
+++ b/io/utime.c
@@ -38,3 +38,19 @@ utime (const char *file, const struct utimbuf *times)
 libc_hidden_def (utime)
 
 stub_warning (utime)
+
+/* 64-bit time version */
+
+int
+__utime64 (const char *file, const struct __utimbuf64 *times)
+{
+  if (file == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utime64)
diff --git a/io/utime.c b/sysdeps/posix/utime64.c
similarity index 63%
copy from io/utime.c
copy to sysdeps/posix/utime64.c
index 3f3c03c..1f043da 100644
--- a/io/utime.c
+++ b/sysdeps/posix/utime64.c
@@ -1,5 +1,4 @@
-/* utime -- change access and modification times of file.  Stub version.
-   Copyright (C) 1991-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,25 +15,32 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <sysdep.h>
 #include <errno.h>
-#include <stddef.h>
 #include <utime.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/time.h>
 
 
 /* Set the access and modification times of FILE to those given in TIMES.
    If TIMES is NULL, set them to the current time.  */
 int
-utime (const char *file, const struct utimbuf *times)
+__utime64 (const char *file, const struct __utimbuf64 *times)
 {
-  if (file == NULL)
+  struct __timeval64 timevals[2];
+  struct __timeval64 *tvp;
+
+  if (times != NULL)
     {
-      __set_errno (EINVAL);
-      return -1;
+      timevals[0].tv_sec = (time_t) times->actime;
+      timevals[0].tv_usec = 0L;
+      timevals[1].tv_sec = (time_t) times->modtime;
+      timevals[1].tv_usec = 0L;
+      tvp = timevals;
     }
+  else
+    tvp = NULL;
 
-  __set_errno (ENOSYS);
-  return -1;
+  return __utimes64 (file, tvp);
 }
-libc_hidden_def (utime)
-
-stub_warning (utime)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8e6951b2d52a4284382173e364399f8afdb24d4f

commit 8e6951b2d52a4284382173e364399f8afdb24d4f
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:05 2017 +0200

    Y2038: add function __adjtime64, __adjtimex64 and __ntp_adjtime64

diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index 6edecb7..4238abd 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -19,6 +19,7 @@
 #include <limits.h>
 #include <sys/time.h>
 #include <sys/timex.h>
+#include <include/time.h>
 
 #define MAX_SEC	(INT_MAX / 1000000L - 2)
 #define MIN_SEC	(INT_MIN / 1000000L + 2)
diff --git a/sysdeps/unix/sysv/linux/adjtime64.c b/sysdeps/unix/sysv/linux/adjtime64.c
new file mode 100644
index 0000000..c305717
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/adjtime64.c
@@ -0,0 +1,164 @@
+/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <include/time.h>
+
+#define MAX_SEC	(INT_MAX / 1000000L - 2)
+#define MIN_SEC	(INT_MIN / 1000000L + 2)
+
+#ifndef MOD_OFFSET
+#define modes mode
+#endif
+
+#ifndef TIMEVAL
+#define TIMEVAL timeval
+#endif
+
+#ifndef TIMEX
+#define TIMEX timex
+#endif
+
+#ifndef ADJTIME
+#define ADJTIME __adjtime
+#endif
+
+#ifndef ADJTIMEX
+#define NO_LOCAL_ADJTIME
+#define ADJTIMEX(x) __adjtimex (x)
+#endif
+
+#ifndef LINKAGE
+#define LINKAGE
+#endif
+
+int __adjtime64 (const struct __timeval64 *itv,
+                 struct __timeval64 *otv)
+{
+  struct TIMEX tntx;
+
+  if (itv)
+    {
+      struct TIMEVAL tmp;
+
+      /* We will do some check here. */
+      tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
+      tmp.tv_usec = itv->tv_usec % 1000000L;
+      if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
+	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+      tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
+      tntx.modes = ADJ_OFFSET_SINGLESHOT;
+    }
+  else
+    tntx.modes = ADJ_OFFSET_SS_READ;
+
+  if (__glibc_unlikely (ADJTIMEX (&tntx) < 0))
+    return -1;
+
+  if (otv)
+    {
+      if (tntx.offset < 0)
+	{
+	  otv->tv_usec = -(-tntx.offset % 1000000);
+	  otv->tv_sec  = -(-tntx.offset / 1000000);
+	}
+      else
+	{
+	  otv->tv_usec = tntx.offset % 1000000;
+	  otv->tv_sec  = tntx.offset / 1000000;
+	}
+    }
+  return 0;
+}
+
+int
+__adjtimex64(struct __timex64 *tx)
+{
+  struct timex tx32;
+
+  if (tx == NULL)
+    {
+      __set_errno (EFAULT);
+      return -1;
+    }
+
+  if ((tx->modes & ADJ_SETOFFSET) != 0 && tx->time.tv_sec > INT_MAX)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  /* Implement with existing 32-bit time syscall */
+
+  /* Just copy everything */
+  tx32.modes = tx->modes;
+  tx32.offset = tx->offset;
+  tx32.freq = tx->freq;
+  tx32.maxerror = tx->maxerror;
+  tx32.esterror = tx->esterror;
+  tx32.status = tx->status;
+  tx32.constant = tx->constant;
+  tx32.precision = tx->precision;
+  tx32.tolerance = tx->tolerance;
+  tx32.time.tv_sec = tx->time.tv_sec;
+  tx32.time.tv_usec = tx->time.tv_usec;
+  tx32.tick = tx->tick;
+  tx32.ppsfreq = tx->ppsfreq;
+  tx32.jitter = tx->jitter;
+  tx32.shift = tx->shift;
+  tx32.stabil = tx->stabil;
+  tx32.jitcnt = tx->jitcnt;
+  tx32.calcnt = tx->calcnt;
+  tx32.errcnt = tx->errcnt;
+  tx32.stbcnt = tx->stbcnt;
+
+  tx32.tai = tx->tai;
+  /* WARNING -- anonymous fields after TAI are not copied. */
+
+  int result = ADJTIMEX(&tx32);
+
+  if (result == 0)
+    {
+      /* Just copy back everything */
+      tx->modes = tx32.modes;
+      tx->offset = tx32.offset;
+      tx->freq = tx32.freq;
+      tx->maxerror = tx32.maxerror;
+      tx->esterror = tx32.esterror;
+      tx->status = tx32.status;
+      tx->constant = tx32.constant;
+      tx->precision = tx32.precision;
+      tx->tolerance = tx32.tolerance;
+      tx->time.tv_sec = tx32.time.tv_sec;
+      tx->time.tv_usec = tx32.time.tv_usec;
+      tx->tick = tx32.tick;
+      tx->ppsfreq = tx32.ppsfreq;
+      tx->jitter = tx32.jitter;
+      tx->shift = tx32.shift;
+      tx->stabil = tx32.stabil;
+      tx->jitcnt = tx32.jitcnt;
+      tx->calcnt = tx32.calcnt;
+      tx->errcnt = tx32.errcnt;
+      tx->stbcnt = tx32.stbcnt;
+    }
+
+  return result;
+}
+weak_alias (__adjtimex64, __ntp_adjtime64);
diff --git a/time/Versions b/time/Versions
index f59ae08..5d79e15 100644
--- a/time/Versions
+++ b/time/Versions
@@ -85,5 +85,7 @@ libc {
     __time64;
     __stime64;
     __utimes64;
+    __adjtime64;
+    __adjtimex64;
   }
 }
diff --git a/time/adjtime.c b/time/adjtime.c
index 4a972d6..800715c 100644
--- a/time/adjtime.c
+++ b/time/adjtime.c
@@ -31,3 +31,13 @@ __adjtime (const struct timeval *delta, struct timeval *olddelta)
 stub_warning (adjtime)
 
 weak_alias (__adjtime, adjtime)
+
+/* 64-bit time version */
+
+int
+__adjtime64 (const struct __timeval64 *delta, struct __timeval64 *olddelta)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__adjtime64)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b9b05dbecd4586e73dfb0db35d7b8d4b08b9ec98

commit b9b05dbecd4586e73dfb0db35d7b8d4b08b9ec98
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:04 2017 +0200

    Y2038: add function __nanosleep64

diff --git a/posix/Makefile b/posix/Makefile
index 6281522..a881989 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -63,7 +63,7 @@ routines :=								      \
 	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
 	posix_madvise							      \
 	get_child_max sched_cpucount sched_cpualloc sched_cpufree	      \
-	sched_rr_gi64
+	sched_rr_gi64 nanosleep64
 
 aux		:= init-posix environ
 tests		:= test-errno tstgetopt testfnm runtests runptests \
diff --git a/posix/Versions b/posix/Versions
index 56c723a..621decb 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -139,6 +139,7 @@ libc {
   }
   GLIBC_2.28 {
     __sched_rr_get_interval_time64;
+    __nanosleep64;
   }
   GLIBC_PRIVATE {
     __libc_fork; __libc_pread; __libc_pwrite;
diff --git a/posix/nanosleep64.c b/posix/nanosleep64.c
new file mode 100644
index 0000000..ae4805d
--- /dev/null
+++ b/posix/nanosleep64.c
@@ -0,0 +1,56 @@
+/* Pause execution for a number of nanoseconds
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+/* Pause execution for a number of nanoseconds.  */
+int
+__nanosleep64 (const struct __timespec64 *requested_time,
+	         struct __timespec64 *remaining)
+{
+  struct timespec treq32, *treqp32 = NULL;
+  struct timespec trem32, *tremp32 = NULL;
+
+  if (requested_time)
+    {
+      if (requested_time->tv_sec > INT_MAX)
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+      treq32.tv_sec = requested_time->tv_sec;
+      treq32.tv_nsec = requested_time->tv_nsec;
+      treqp32 = & treq32;
+    }
+
+  if (remaining)
+    tremp32 = &trem32;
+
+  int result = __nanosleep(treqp32, tremp32);
+
+  if (result == 1 && errno == EINTR && remaining)
+    {
+      remaining->tv_sec = trem32.tv_sec;
+      remaining->tv_nsec = trem32.tv_nsec;
+      remaining->tv_pad = 0;
+    }
+
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e2e7283b7f342e3cfc62396f8c7ed9efa95ff87a

commit e2e7283b7f342e3cfc62396f8c7ed9efa95ff87a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:03 2017 +0200

    Y2038: add function __sched_rr_get_interval64

diff --git a/posix/Makefile b/posix/Makefile
index 00c6284..6281522 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -62,7 +62,8 @@ routines :=								      \
 	spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
 	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
 	posix_madvise							      \
-	get_child_max sched_cpucount sched_cpualloc sched_cpufree
+	get_child_max sched_cpucount sched_cpualloc sched_cpufree	      \
+	sched_rr_gi64
 
 aux		:= init-posix environ
 tests		:= test-errno tstgetopt testfnm runtests runptests \
diff --git a/posix/Versions b/posix/Versions
index cad4c23..56c723a 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -137,6 +137,9 @@ libc {
   GLIBC_2.27 {
     glob; glob64;
   }
+  GLIBC_2.28 {
+    __sched_rr_get_interval_time64;
+  }
   GLIBC_PRIVATE {
     __libc_fork; __libc_pread; __libc_pwrite;
     __nanosleep_nocancel; __pause_nocancel;
diff --git a/posix/sched_rr_gi64.c b/posix/sched_rr_gi64.c
new file mode 100644
index 0000000..35dc938
--- /dev/null
+++ b/posix/sched_rr_gi64.c
@@ -0,0 +1,55 @@
+/* Get the SCHED_RR interval for the named process.
+  
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <y2038-support.h>
+
+int
+__sched_rr_get_interval_time64 (pid_t pid, struct __timespec64 *t)
+{
+  struct timespec ts32;
+  int result;
+
+  if (t == NULL)
+    {
+      __set_errno(EINVAL);
+      return -1;
+    }
+
+#ifdef __NR_sched_rr_get_interval_time64
+  if (__y2038_linux_support > 0)
+    {
+      result = INLINE_SYSCALL(sched_rr_get_interval_time64, 2, pid, t);
+      if (result == 0 || errno != ENOSYS)
+        return result;
+      __y2038_linux_support = -1;
+    }
+#endif
+
+  result = __sched_rr_get_interval(pid, &ts32);
+  if (result == 0)
+    {
+      t->tv_sec = ts32.tv_sec;
+      t->tv_nsec = ts32.tv_nsec;
+      t->tv_pad = 0;
+    }
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b249f54338c4d75bbf614aa6a73418702490ac1f

commit b249f54338c4d75bbf614aa6a73418702490ac1f
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:02 2017 +0200

    Y2038: add function __msgctl64

diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index 7280cba..f785804 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -69,3 +69,60 @@ __old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf)
 }
 compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0);
 #endif
+
+/* 64-bit time version */
+
+struct __msqid_ds64
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  __time64_t msg_rtime;		/* time of last msgrcv command */
+  __time64_t msg_ctime;		/* time of last change */
+  unsigned long int __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  unsigned long int __glibc_reserved4;
+  unsigned long int __glibc_reserved5;
+};
+
+int
+__msgctl64 (int msqid, int cmd, struct __msqid_ds64 *buf)
+{
+  int result;
+  struct msqid_ds buf32, *pbuf32 = NULL;
+
+  if (cmd == IPC_SET && buf != NULL)
+    {
+      buf32.msg_qbytes = buf->msg_qbytes;
+      buf32.msg_perm.uid = buf->msg_perm.uid;
+      buf32.msg_perm.gid = buf->msg_perm.gid;
+      buf32.msg_perm.mode = buf->msg_perm.mode;
+    }
+
+  if (cmd == IPC_SET || cmd == IPC_STAT)
+    pbuf32 = &buf32;
+
+#ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
+  result = INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, pbuf32);
+#else
+  result = INLINE_SYSCALL_CALL (ipc, IPCOP_msgctl, msqid, cmd | __IPC_64,
+                                0, pbuf32);
+#endif
+
+  if (cmd == IPC_STAT && result == 0 && buf != NULL)
+    {
+      buf->msg_perm = buf32.msg_perm;
+      buf->msg_stime = buf32.msg_stime;
+      buf->msg_rtime = buf32.msg_rtime;
+      buf->msg_ctime = buf32.msg_ctime;
+      buf->__msg_cbytes = buf32.__msg_cbytes;
+      buf->msg_qnum = buf32.msg_qnum;
+      buf->msg_qbytes = buf32.msg_qbytes;
+      buf->msg_lspid = buf32.msg_lspid;
+      buf->msg_lrpid = buf32.msg_lrpid;
+    }
+
+  return result;
+}
diff --git a/sysvipc/Versions b/sysvipc/Versions
index 4c797e2..0e7f297 100644
--- a/sysvipc/Versions
+++ b/sysvipc/Versions
@@ -13,6 +13,9 @@ libc {
     # Non-standard function.
     semtimedop;
   }
+  GLIBC_2.28 {
+    __msgctl64;
+  }
   GLIBC_PRIVATE {
     # Cancellation point entries.
     __libc_msgrcv; __libc_msgsnd;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4c8cb1f1fd39830d4a7194e7b1eaf73ed405cdf8

commit 4c8cb1f1fd39830d4a7194e7b1eaf73ed405cdf8
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:01 2017 +0200

    Y2038: add function __mq_timedsend_time64

diff --git a/rt/Makefile b/rt/Makefile
index 928f90e..f6011f4 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -38,7 +38,7 @@ shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
 		  mq_timedreceive					\
-		  mq_timedreceiv_time64
+		  mq_timedreceiv_time64 mq_timedsend_time64
 
 routines = $(clock-routines)
 
diff --git a/rt/Versions b/rt/Versions
index 8ca4459..1170133 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -43,5 +43,6 @@ librt {
    __timerfd_gettime64;
    __timerfd_settime64;
    __mq_timedreceive64;
+   __mq_timedsend_time64;
   }
 }
diff --git a/rt/mq_timedsend_time64.c b/rt/mq_timedsend_time64.c
new file mode 100644
index 0000000..7459d94
--- /dev/null
+++ b/rt/mq_timedsend_time64.c
@@ -0,0 +1,52 @@
+/* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
+   on full message queue if ABS_TIMEOUT expires.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <mqueue.h>
+#include <y2038-support.h>
+
+/* 64-bit time version */
+
+int
+__mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
+		  unsigned int msg_prio, const struct __timespec64 *abs_timeout)
+{
+  struct timespec ts32, *tsp32 = NULL;
+#ifdef __NR_mq_timedsend_time64
+  int result;
+  
+  if (__y2038_get_kernel_support () > 0)
+    {
+      result = INLINE_SYSCALL (mq_timedsend_time64, 5, mqdes, msg_ptr,
+			       msg_len, msg_prio, abs_timeout);
+      if (result == 0 || errno != ENOSYS)
+        return result;
+      __y2038_set_kernel_support (-1);
+    }
+#endif
+
+  if (abs_timeout)
+    {
+      ts32.tv_sec = abs_timeout->tv_sec;
+      ts32.tv_nsec = abs_timeout->tv_nsec;
+      tsp32 = &ts32;
+    }
+  return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, tsp32);
+}
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index 2f34cea..d99df62 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,5 +1,6 @@
 GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __mq_timedreceive64 F
+GLIBC_2.28 __mq_timedsend_time64 F
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
 GLIBC_2.28 __timerfd_gettime64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index 6c2e1d5..c85dc7c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -29,6 +29,7 @@ GLIBC_2.2 timer_gettime F
 GLIBC_2.2 timer_settime F
 GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __mq_timedreceive64 F
+GLIBC_2.28 __mq_timedsend_time64 F
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
 GLIBC_2.28 __timerfd_gettime64 F

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b0c4a13148cc7380ce3269ce22eeb48ed7b1eb54

commit b0c4a13148cc7380ce3269ce22eeb48ed7b1eb54
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:42:00 2017 +0200

    Y2038: add function __mq_timedreceiv_time64

diff --git a/rt/Makefile b/rt/Makefile
index 994891e..928f90e 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -37,7 +37,8 @@ timer-routines := timer_create timer_delete timer_getoverr		\
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
-		  mq_timedreceive
+		  mq_timedreceive					\
+		  mq_timedreceiv_time64
 
 routines = $(clock-routines)
 
diff --git a/rt/Versions b/rt/Versions
index 25f115d..8ca4459 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -42,5 +42,6 @@ librt {
    __timer_settime64;
    __timerfd_gettime64;
    __timerfd_settime64;
+   __mq_timedreceive64;
   }
 }
diff --git a/rt/mq_timedreceiv_time64.c b/rt/mq_timedreceiv_time64.c
new file mode 100644
index 0000000..6d94efe
--- /dev/null
+++ b/rt/mq_timedreceiv_time64.c
@@ -0,0 +1,54 @@
+/* Receive the oldest from highest priority messages in message queue
+   MQDES, stop waiting if ABS_TIMEOUT expires.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <mqueue.h>
+#include <y2038-support.h>
+
+/* 64-bit time version */
+
+ssize_t
+__mq_timedreceiv_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len,
+			 unsigned int *__restrict msg_prio,
+			 const struct __timespec64 *__restrict abs_timeout)
+{
+  struct timespec ts32, *tsp32 = NULL;
+
+#ifdef __NR_timedreceiv_time64
+  int result;
+
+  if (__y2038_get_kernel_support () > 0)
+    {
+      result = INLINE_SYSCALL (mq_timedreceiv_time64, 5, mqdes, msg_ptr, msg_len,
+			       msg_prio, abs_timeout);
+      if (result == 0 || errno != ENOSYS)
+	return result;
+      __y2038_set_kernel_support (-1);
+    }
+#endif
+
+  if (abs_timeout)
+    {
+      ts32.tv_sec = abs_timeout->tv_sec;
+      ts32.tv_nsec = abs_timeout->tv_nsec;
+      tsp32 = &ts32;
+    }
+  return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, tsp32);
+}
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index 751396c..2f34cea 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,4 +1,5 @@
 GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __mq_timedreceive64 F
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
 GLIBC_2.28 __timerfd_gettime64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index 0870b4f..6c2e1d5 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -28,6 +28,7 @@ GLIBC_2.2 timer_getoverrun F
 GLIBC_2.2 timer_gettime F
 GLIBC_2.2 timer_settime F
 GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __mq_timedreceive64 F
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
 GLIBC_2.28 __timerfd_gettime64 F

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=045fa9393a208d254b3a36ae5a32e9a51204792e

commit 045fa9393a208d254b3a36ae5a32e9a51204792e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:57 2017 +0200

    Y2038: add function __utimes64

diff --git a/include/time.h b/include/time.h
index 70fbe89..564bfee 100644
--- a/include/time.h
+++ b/include/time.h
@@ -34,6 +34,9 @@ extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
 				const struct __timespec64 *__req,
 				struct __timespec64 *__rem);
 
+extern int __utimes64 (const char *file,
+                       const struct __timeval64 tvp[2]);
+
 /* Now define the internal interfaces.  */
 struct tm;
 
diff --git a/misc/Makefile b/misc/Makefile
index 027a395..d5cbc63 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -71,7 +71,7 @@ routines := brk sbrk sstk ioctl \
 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
 	    removexattr setxattr getauxval ifunc-impl-list makedev \
-	    allocate_once y2038-support
+	    allocate_once y2038-support utimes64
 
 generated += tst-error1.mtrace tst-error1-mem.out \
   tst-allocate_once.mtrace tst-allocate_once-mem.out
diff --git a/misc/utimes.c b/misc/utimes.c
index 0ae6946..cdb43f6 100644
--- a/misc/utimes.c
+++ b/misc/utimes.c
@@ -38,3 +38,18 @@ __utimes (const char *file, const struct timeval tvp[2])
 weak_alias (__utimes, utimes)
 
 stub_warning (utimes)
+
+int
+__utimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  if (file == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__utimes64)
diff --git a/misc/utimes.c b/sysdeps/unix/sysv/linux/utimes64.c
similarity index 52%
copy from misc/utimes.c
copy to sysdeps/unix/sysv/linux/utimes64.c
index 0ae6946..b17f997 100644
--- a/misc/utimes.c
+++ b/sysdeps/unix/sysv/linux/utimes64.c
@@ -1,5 +1,4 @@
-/* utimes -- Change access and modification times of file.  Stub version.
-   Copyright (C) 1991-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,25 +15,34 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sys/time.h>
 #include <errno.h>
 #include <stddef.h>
+#include <utime.h>
+#include <sys/time.h>
+#include <sysdep.h>
+#include <fcntl.h>
+
+/* 64-bit-time variant */
 
-/* Change the access time of FILE to TVP[0] and
-   the modification time of FILE to TVP[1].  */
 int
-__utimes (const char *file, const struct timeval tvp[2])
+__utimes64 (const char *file, const struct __timeval64 tvp[2])
 {
-  if (file == NULL)
+  struct timespec ts32[2], *tsp32 = NULL;
+
+  if (tvp != NULL)
     {
-      __set_errno (EINVAL);
-      return -1;
+      if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+      ts32[0].tv_sec = tvp[0].tv_sec;
+      ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+      ts32[1].tv_sec = tvp[1].tv_sec;
+      ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+      tsp32 = ts32;
     }
 
-  __set_errno (ENOSYS);
-  return -1;
+  /* use utimensat rather than utimes which not all arches can use */
+  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tsp32, 0);
 }
-
-weak_alias (__utimes, utimes)
-
-stub_warning (utimes)
diff --git a/time/Versions b/time/Versions
index 9a84360..f59ae08 100644
--- a/time/Versions
+++ b/time/Versions
@@ -84,5 +84,6 @@ libc {
     __settimeofday64;
     __time64;
     __stime64;
+    __utimes64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bff0f236a846a1e17db971f36ea4befe6f6091d4

commit bff0f236a846a1e17db971f36ea4befe6f6091d4
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:56 2017 +0200

    Y2038: add function __stime64
    
    This implementation uses __settimeofday64.
    Therefore, on a system where current time-of-day is 32 bits, this
    implementation will fail for dates beyond Y2038.

diff --git a/time/stime.c b/sysdeps/unix/stime64.c
similarity index 69%
copy from time/stime.c
copy to sysdeps/unix/stime64.c
index 0378e23..2506227 100644
--- a/time/stime.c
+++ b/sysdeps/unix/stime64.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
+/* Set the system clock on a unix system 
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,22 +18,30 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
+#include <stddef.h>		/* For NULL.  */
+#include <sys/time.h>
 #include <time.h>
-#include <stddef.h>
 
 /* Set the system clock to *WHEN.  */
 
 int
-stime (const time_t *when)
+__stime64 (const __time64_t *when)
 {
+  struct __timeval64 tv;
+
   if (when == NULL)
     {
       __set_errno (EINVAL);
       return -1;
     }
 
-  __set_errno (ENOSYS);
-  return -1;
-}
+  if (*when > INT_MAX)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
 
-stub_warning (stime)
+  tv.tv_sec = *when;
+  tv.tv_usec = 0;
+  return __settimeofday64 (&tv, (struct timezone *) 0);
+}
diff --git a/time/Makefile b/time/Makefile
index 497123e..a38f640 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -33,7 +33,7 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
-	    time64					 \
+	    time64 stime64				 \
 	    gettimeofday settimeofday adjtime tzset	 \
 	    gettimeofday64 settimeofday64		 \
 	    tzfile getitimer setitimer			 \
diff --git a/time/Versions b/time/Versions
index 835119e..9a84360 100644
--- a/time/Versions
+++ b/time/Versions
@@ -83,5 +83,6 @@ libc {
     __gettimeofday64;
     __settimeofday64;
     __time64;
+    __stime64;
   }
 }
diff --git a/time/stime.c b/time/stime.c
index 0378e23..5d22aaa 100644
--- a/time/stime.c
+++ b/time/stime.c
@@ -35,3 +35,20 @@ stime (const time_t *when)
 }
 
 stub_warning (stime)
+
+/* 64-bit time version */
+
+int
+__stime64 (const __time64_t *when)
+{
+  if (when == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__stime64)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c55ecd959b7f57a81e37e0513adc331a325c3038

commit c55ecd959b7f57a81e37e0513adc331a325c3038
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:55 2017 +0200

    Y2038: add function __time64
    
    This provides a generic Posix implementation based on calling
    __gettimeofday64().

diff --git a/time/time.c b/sysdeps/posix/time64.c
similarity index 57%
copy from time/time.c
copy to sysdeps/posix/time64.c
index 4996d26..4a58228 100644
--- a/time/time.c
+++ b/sysdeps/posix/time64.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+/* Get the 64-bit current time
+ * 
+   Copyright (C) 1991-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,19 +17,27 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
+#include <stddef.h>		/* For NULL.  */
 #include <time.h>
+#include <sys/time.h>
 
-/* Return the time now, and store it in *TIMER if not NULL.  */
-time_t
-time (time_t *timer)
+
+/* Return the current time as a `time_t' and also put it in *T if T is
+   not NULL.  Time is represented as seconds from Jan 1 00:00:00 1970.  */
+
+__time64_t
+__time64 (__time64_t *t)
 {
-  __set_errno (ENOSYS);
+  struct __timeval64 tv;
+  __time64_t result;
 
-  if (timer != NULL)
-    *timer = (time_t) -1;
-  return (time_t) -1;
-}
-libc_hidden_def (time)
+  if (__gettimeofday64 (&tv, (struct timezone *) NULL))
+    result = (__time64_t) -1;
+  else
+    result = tv.tv_sec;
 
-stub_warning (time)
+  if (t != NULL)
+    *t = result;
+
+  return result;
+}
diff --git a/time/Makefile b/time/Makefile
index 1efe9ac..497123e 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -33,6 +33,7 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
+	    time64					 \
 	    gettimeofday settimeofday adjtime tzset	 \
 	    gettimeofday64 settimeofday64		 \
 	    tzfile getitimer setitimer			 \
diff --git a/time/Versions b/time/Versions
index 9095c10..835119e 100644
--- a/time/Versions
+++ b/time/Versions
@@ -82,5 +82,6 @@ libc {
     __lutimes64;
     __gettimeofday64;
     __settimeofday64;
+    __time64;
   }
 }
diff --git a/time/time.c b/time/time.c
index 4996d26..9703c72 100644
--- a/time/time.c
+++ b/time/time.c
@@ -31,3 +31,16 @@ time (time_t *timer)
 libc_hidden_def (time)
 
 stub_warning (time)
+
+/* 64-bit time version */
+
+__time64_t
+__time64 (__time64_ *timer)
+{
+  __set_errno (ENOSYS);
+
+  if (timer != NULL)
+    *timer = (__time64_t) -1;
+  return (__time64_t) -1;
+}
+libc_hidden_def (__time64)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=85bd1384a2b4264bbc43d315fc0b21faffe01751

commit 85bd1384a2b4264bbc43d315fc0b21faffe01751
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:59 2017 +0200

    Y2038: add function __settimeofday64
    
    Implementing a 64-bit settimeofday requires adding a new
    file to build under time/ and we cannot name that new file
    'settimeofday.c' or it will break the 32-bit settimeofday
    file symbol, so we call it 'settimeofday64.c'.

diff --git a/include/sys/time.h b/include/sys/time.h
index ed73a44..792fe84 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -29,6 +29,8 @@ extern int __gettimeofday64 (struct __timeval64 *__tv,
 extern int __settimeofday (const struct timeval *__tv,
 			   const struct timezone *__tz)
 	attribute_hidden;
+extern int __settimeofday64 (const struct __timeval64 *__tv,
+			     const struct timezone *__tz);
 extern int __adjtime (const struct timeval *__delta,
 		      struct timeval *__olddelta);
 extern int __getitimer (enum __itimer_which __which,
diff --git a/time/settimeofday.c b/sysdeps/unix/sysv/linux/settimeofday64.c
similarity index 68%
copy from time/settimeofday.c
copy to sysdeps/unix/sysv/linux/settimeofday64.c
index 01bf4b0..1a9fa23 100644
--- a/time/settimeofday.c
+++ b/sysdeps/unix/sysv/linux/settimeofday64.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+/* Set the current time of day and timezone information.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,17 +17,23 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <sysdep.h>
 #include <errno.h>
 #include <sys/time.h>
 
-/* Set the current time of day and timezone information.
-   This call is restricted to the super-user.  */
-int
-__settimeofday (const struct timeval *tv, const struct timezone *tz)
+int __settimeofday64(const struct __timeval64 *tv,
+                       const struct timezone *tz)
 {
-  __set_errno (ENOSYS);
-  return -1;
-}
-stub_warning (settimeofday)
+  struct timeval tv32;
 
-weak_alias (__settimeofday, settimeofday)
+  if (tv && tv->tv_sec > INT_MAX)
+    {
+      __set_errno(EOVERFLOW);
+      return -1;
+    }
+
+  tv32.tv_sec = tv->tv_sec;
+  tv32.tv_usec = tv->tv_usec;
+
+  return __settimeofday(&tv32, tz);
+}
diff --git a/time/Makefile b/time/Makefile
index dd09d09..1efe9ac 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -34,7 +34,7 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
 	    gettimeofday settimeofday adjtime tzset	 \
-	    gettimeofday64				 \
+	    gettimeofday64 settimeofday64		 \
 	    tzfile getitimer setitimer			 \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
diff --git a/time/Versions b/time/Versions
index 098e748..9095c10 100644
--- a/time/Versions
+++ b/time/Versions
@@ -81,5 +81,6 @@ libc {
     __futimes64;
     __lutimes64;
     __gettimeofday64;
+    __settimeofday64;
   }
 }
diff --git a/time/settimeofday.c b/time/settimeofday.c
index 01bf4b0..000ed21 100644
--- a/time/settimeofday.c
+++ b/time/settimeofday.c
@@ -29,3 +29,11 @@ __settimeofday (const struct timeval *tv, const struct timezone *tz)
 stub_warning (settimeofday)
 
 weak_alias (__settimeofday, settimeofday)
+
+int
+__settimeofday64 (const struct timeval *tv, const struct timezone *tz)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__settimeofday64)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5c2ac7e7b30858449c998f164bb6fb1d74f0a8d8

commit 5c2ac7e7b30858449c998f164bb6fb1d74f0a8d8
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:58 2017 +0200

    Y2038: add function __gettimeofday64
    
    Implementing a 64-bit settimeofday requires adding a new
    file to build under time/ and we cannot name that new file
    'settimeofday.c' or it will break the 32-bit settimeofday
    symbol, so we call it 'settimeofday64.c'.

diff --git a/include/sys/time.h b/include/sys/time.h
index 98f6b6b..ed73a44 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -24,6 +24,8 @@ extern int __gettimeofday (struct timeval *__tv,
 			   struct timezone *__tz);
 libc_hidden_proto (__gettimeofday)
 libc_hidden_proto (gettimeofday)
+extern int __gettimeofday64 (struct __timeval64 *__tv,
+			     struct timezone *__tz);
 extern int __settimeofday (const struct timeval *__tv,
 			   const struct timezone *__tz)
 	attribute_hidden;
diff --git a/sysdeps/unix/sysv/linux/gettimeofday64.c b/sysdeps/unix/sysv/linux/gettimeofday64.c
new file mode 100644
index 0000000..e1538a9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/gettimeofday64.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2015-2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sys/time.h>
+
+#undef __gettimeofday
+
+#ifdef HAVE_GETTIMEOFDAY_VSYSCALL
+# define HAVE_VSYSCALL
+#include <sysdep-vdso.h>
+#endif
+
+/* Get the current time of day and timezone information,
+   putting it into *tv and *tz.  If tz is null, *tz is not filled.
+   Returns 0 on success, -1 on errors.  */
+
+int
+__gettimeofday64 (struct __timeval64 *tv, struct timezone *tz)
+{
+  struct timeval tv32;
+  int result;
+
+#ifdef __vdso_gettimeofday
+  result = INLINE_VSYSCALL (gettimeofday, 2, &tv32, tz);
+#else
+  result = INLINE_SYSCALL (gettimeofday, 2, &tv32, tz);
+#endif
+
+  if (result == 0)
+    {
+      tv->tv_sec = tv32.tv_sec;
+      tv->tv_usec = tv32.tv_usec;
+    }
+
+  return result;
+}
diff --git a/time/Makefile b/time/Makefile
index 2d60110..dd09d09 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -34,6 +34,7 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
 	    gettimeofday settimeofday adjtime tzset	 \
+	    gettimeofday64				 \
 	    tzfile getitimer setitimer			 \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
diff --git a/time/Versions b/time/Versions
index 9f0df57..098e748 100644
--- a/time/Versions
+++ b/time/Versions
@@ -80,5 +80,6 @@ libc {
     __sigtimedwait_time64;
     __futimes64;
     __lutimes64;
+    __gettimeofday64;
   }
 }
diff --git a/time/gettimeofday.c b/time/gettimeofday.c
index d1ab9ac..e4a67c6 100644
--- a/time/gettimeofday.c
+++ b/time/gettimeofday.c
@@ -16,7 +16,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
-#include <sys/time.h>
 
 /* Get the current time of day and timezone information,
    putting it into *TV and *TZ.  If TZ is NULL, *TZ is not filled.
@@ -32,3 +31,13 @@ weak_alias (__gettimeofday, gettimeofday)
 libc_hidden_weak (gettimeofday)
 
 stub_warning (gettimeofday)
+
+/* 64-bit time version */
+
+int
+__gettimeofday64 (struct timeval *tv, struct timezone *tz)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__gettimeofday64)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d405cfcf0e96d0a7e9de714ca3ed2a96fabf9fb0

commit d405cfcf0e96d0a7e9de714ca3ed2a96fabf9fb0
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:54 2017 +0200

    Y2038: add function __fstatat64_time64 (and __fxstatat_time64)
    
    These implementations just use the existing syscalls and convert from
    kernel 32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 72aca27..d267dd0 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -42,6 +42,10 @@ extern int __xstat64_time64 (int __ver, const char *__filename,
 			     struct __stat64_t64 *__stat_buf);
 extern int __lxstat64_time64 (int __ver, const char *__filename,
 			      struct __stat64_t64 *__stat_buf);
+extern int __fxstatat64_time64 (int __ver, int __fildes,
+				const char *__filename,
+				struct __stat64_t64 *__stat_buf,
+				int __flag);
 
 #if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN)
 hidden_proto (__fxstat)
diff --git a/io/Versions b/io/Versions
index d067016..eaeeca8 100644
--- a/io/Versions
+++ b/io/Versions
@@ -141,5 +141,6 @@ libc {
     __fxstat64_time64;
     __xstat64_time64;
     __lxstat64_time64;
+    __fxstatat64_time64;
   }
 }
diff --git a/io/fstatat64.c b/io/fstatat64.c
index f4f46a9..b7efd89 100644
--- a/io/fstatat64.c
+++ b/io/fstatat64.c
@@ -50,3 +50,10 @@ fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
 {
   return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
 }
+
+int
+attribute_hidden
+__fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  return __fxstatat64_time64 (_STAT_VER, fd, file, buf, flag);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index baa9a60..2c04e66 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -45,3 +45,48 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
 								      err));
 }
 libc_hidden_def (__fxstatat64)
+
+/* 64-bit time version */
+
+int
+__fxstatat64_time64 (int vers, int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  if (__glibc_unlikely (vers != _STAT_VER_LINUX))
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+  int result;
+  struct stat64 st64;
+  INTERNAL_SYSCALL_DECL (err);
+
+  result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
+  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
+    {
+      buf->st_dev          = st64.st_dev;
+    
+#if defined _HAVE_STAT64___ST_INO
+      buf->__st_ino        = st64.__st_ino;
+#endif
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    
+      return 0;
+    }
+  else
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
+								      err));
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=db3c966ae365ef0dce78c9adeaa36df495a1f421

commit db3c966ae365ef0dce78c9adeaa36df495a1f421
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:53 2017 +0200

    Y2038: add function __lstat64_time64 (and __lxstat64_time64)
    
    These implementations just use the existing syscalls and convert from
    kernel 32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 186df0c..72aca27 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -40,6 +40,8 @@ extern int __fxstat64_time64 (int __ver, int __fildes,
 			      struct __stat64_t64 *__stat_buf);
 extern int __xstat64_time64 (int __ver, const char *__filename,
 			     struct __stat64_t64 *__stat_buf);
+extern int __lxstat64_time64 (int __ver, const char *__filename,
+			      struct __stat64_t64 *__stat_buf);
 
 #if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN)
 hidden_proto (__fxstat)
diff --git a/io/Versions b/io/Versions
index 58ceb22..d067016 100644
--- a/io/Versions
+++ b/io/Versions
@@ -140,5 +140,6 @@ libc {
   GLIBC_2.28 {
     __fxstat64_time64;
     __xstat64_time64;
+    __lxstat64_time64;
   }
 }
diff --git a/io/lstat64.c b/io/lstat64.c
index c3eb7a7..96ce999 100644
--- a/io/lstat64.c
+++ b/io/lstat64.c
@@ -50,3 +50,10 @@ lstat64 (const char *file, struct stat64 *buf)
 {
   return __lxstat64 (_STAT_VER, file, buf);
 }
+
+int
+attribute_hidden
+__lstat64_time64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __lxstat64_time64 (_STAT_VER, file, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index d05fa14..0c55407 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -50,3 +50,44 @@ hidden_ver (___lxstat64, __lxstat64)
 strong_alias (___lxstat64, __lxstat64);
 hidden_def (__lxstat64)
 #endif
+
+/* 64-bit time version */
+
+int
+__lxstat64_time64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  result = INLINE_SYSCALL (lstat64, 2, name, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+    
+#if defined _HAVE_STAT64___ST_INO
+      buf->__st_ino        = st64.__st_ino;
+#endif
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=eed0cedb9d42d83e7efffaa6088cd0127836dc54

commit eed0cedb9d42d83e7efffaa6088cd0127836dc54
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:52 2017 +0200

    Y2038: add function __stat64_time64 (and __xstat64_time64)
    
    These implementations just use the existing syscalls and convert from
    kernel 32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

diff --git a/include/sys/stat.h b/include/sys/stat.h
index c00f7b4..186df0c 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -38,6 +38,8 @@ extern int __mknod (const char *__path,
 		    __mode_t __mode, __dev_t __dev);
 extern int __fxstat64_time64 (int __ver, int __fildes,
 			      struct __stat64_t64 *__stat_buf);
+extern int __xstat64_time64 (int __ver, const char *__filename,
+			     struct __stat64_t64 *__stat_buf);
 
 #if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN)
 hidden_proto (__fxstat)
diff --git a/io/Versions b/io/Versions
index fe85a5a..58ceb22 100644
--- a/io/Versions
+++ b/io/Versions
@@ -139,5 +139,6 @@ libc {
   }
   GLIBC_2.28 {
     __fxstat64_time64;
+    __xstat64_time64;
   }
 }
diff --git a/io/stat64.c b/io/stat64.c
index 5020551..4ed632f 100644
--- a/io/stat64.c
+++ b/io/stat64.c
@@ -50,3 +50,10 @@ stat64 (const char *file, struct stat64 *buf)
 {
   return __xstat64 (_STAT_VER, file, buf);
 }
+
+int
+attribute_hidden
+__stat64_time64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __xstat64_time64 (_STAT_VER, file, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index afc9ba2..e0341c1 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -52,3 +52,44 @@ hidden_ver (___xstat64, __xstat64)
 strong_alias (___xstat64, __xstat64)
 hidden_def (__xstat64)
 #endif
+
+/* 64-bit time version */
+
+int
+__xstat64_time64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  result = INLINE_SYSCALL (stat64, 2, name, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+#if defined _HAVE_STAT64___ST_INO
+      buf->__st_ino        = st64.__st_ino;
+#endif
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;
+
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
+
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=10a5a7dd30e848d35f1d8d853cf2b4dacd3ec443

commit 10a5a7dd30e848d35f1d8d853cf2b4dacd3ec443
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:51 2017 +0200

    Y2038: add function __fstat64_time64 (and __fxstat64_time64)
    
    These implementations just use the existing syscalls and convert from
    kernel 32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 0f2a662..c00f7b4 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -36,6 +36,9 @@ extern int __mkdir (const char *__path, __mode_t __mode);
 libc_hidden_proto (__mkdir)
 extern int __mknod (const char *__path,
 		    __mode_t __mode, __dev_t __dev);
+extern int __fxstat64_time64 (int __ver, int __fildes,
+			      struct __stat64_t64 *__stat_buf);
+
 #if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN)
 hidden_proto (__fxstat)
 hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index 98037fb..fe85a5a 100644
--- a/io/Versions
+++ b/io/Versions
@@ -137,4 +137,7 @@ libc {
     __open64_nocancel;
     __write_nocancel;
   }
+  GLIBC_2.28 {
+    __fxstat64_time64;
+  }
 }
diff --git a/io/fstat64.c b/io/fstat64.c
index 0f4de02..56b1b3f 100644
--- a/io/fstat64.c
+++ b/io/fstat64.c
@@ -50,3 +50,10 @@ fstat64 (int fd, struct stat64 *buf)
 {
   return __fxstat64 (_STAT_VER, fd, buf);
 }
+
+int
+attribute_hidden
+__fstat64_time64 (int fd, struct __stat64_t64 *buf)
+{
+  return __fxstat64_time64 (_STAT_VER, fd, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 0d05389..8c376cc 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -51,3 +51,43 @@ hidden_ver (___fxstat64, __fxstat64)
 strong_alias (___fxstat64, __fxstat64)
 hidden_def (__fxstat64)
 #endif
+
+/* 64-bit time version */
+
+int
+__fxstat64_time64 (int vers, int fd, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  result = INLINE_SYSCALL (fstat64, 2, fd, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+#if defined _HAVE_STAT64___ST_INO
+      buf->__st_ino        = st64.__st_ino;
+#endif
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=aa1eefe8d4568c9cd5e07c998a07d93579310e26

commit aa1eefe8d4568c9cd5e07c998a07d93579310e26
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:50 2017 +0200

    Y2038: add struct __stat64_t64

diff --git a/include/sys/stat.h b/include/sys/stat.h
index b82d452..0f2a662 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -2,6 +2,28 @@
 #include <io/sys/stat.h>
 
 #ifndef _ISOMAC
+
+/* Used for 64-bit time implementations */
+struct __stat64_t64
+  {
+    __dev_t st_dev;			/* Device.  */
+
+    __ino_t __st_ino;			/* 32bit file serial number.	*/
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+    __off64_t st_size;			/* Size of file, in bytes.  */
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+
+    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
+    struct __timespec64 st_atim;		/* Time of last access.  */
+    struct __timespec64 st_mtim;		/* Time of last modification.  */
+    struct __timespec64 st_ctim;		/* Time of last status change.  */
+    __ino64_t st_ino;			/* File serial number.		*/
+  };
+
 /* Now define the internal interfaces. */
 extern int __stat (const char *__file, struct stat *__buf);
 extern int __fstat (int __fd, struct stat *__buf);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3897bcf86b60c2acf6f85a4da40ea458c741f66c

commit 3897bcf86b60c2acf6f85a4da40ea458c741f66c
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:49 2017 +0200

    Y2038: add function __timerfd_settime64
    
    For Linux this uses the 32-bit time syscal, so it converts
    syscall input from 64-bit time into 32-bit time and syscall
    output from 32-bit time to 64-bit time.

diff --git a/rt/Makefile b/rt/Makefile
index c0aad5d..994891e 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -33,7 +33,7 @@ clock-routines := get_clockfreq clock_getcpuclockid			\
 		  clock_nanosleep
 timer-routines := timer_create timer_delete timer_getoverr		\
 		  timer_gettime timer_settime                           \
-		  timerfd_gettime64
+		  timerfd_gettime64 timerfd_settime64
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
diff --git a/rt/Versions b/rt/Versions
index b31ae4c..25f115d 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -41,5 +41,6 @@ librt {
    __timer_gettime64;
    __timer_settime64;
    __timerfd_gettime64;
+   __timerfd_settime64;
   }
 }
diff --git a/rt/timerfd_settime64.c b/rt/timerfd_settime64.c
new file mode 100644
index 0000000..39ce88b
--- /dev/null
+++ b/rt/timerfd_settime64.c
@@ -0,0 +1,30 @@
+/* Set timer TIMERID to VALUE, returning old value in OVALUE.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+int
+__timerfd_settime64 (int fd, int flags, const struct itimerspec *value,
+	       struct itimerspec *ovalue)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_settime64)
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index ce9da27..751396c 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -2,6 +2,7 @@ GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
 GLIBC_2.28 __timerfd_gettime64 F
+GLIBC_2.28 __timerfd_settime64 F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 aio_cancel F
 GLIBC_2.4 aio_cancel64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index d3d887b..0870b4f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -31,6 +31,7 @@ GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
 GLIBC_2.28 __timerfd_gettime64 F
+GLIBC_2.28 __timerfd_settime64 F
 GLIBC_2.3.4 GLIBC_2.3.4 A
 GLIBC_2.3.4 mq_close F
 GLIBC_2.3.4 mq_getattr F
diff --git a/sysdeps/unix/sysv/linux/timerfd_settime64.c b/sysdeps/unix/sysv/linux/timerfd_settime64.c
new file mode 100644
index 0000000..fc31f5a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_settime64.c
@@ -0,0 +1,72 @@
+/* Set timer TIMERID to VALUE, returning old value in OVALUE.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include <y2038-support.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
+	             struct __itimerspec64 *ovalue)
+{
+  int res;
+  struct itimerspec value32;
+  struct itimerspec ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+#ifdef __NR_timerfd_settime64
+  if (__y2038_get_kernel_support () > 0)
+    {
+      res = INLINE_SYSCALL (timerfd_settime64, 3, fd, value, ovalue);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+      __y2038_set_kernel_support (-1);
+    }
+#endif
+
+  if (value->it_value.tv_sec > INT_MAX
+      || value->it_interval.tv_sec > INT_MAX)
+    {
+      __set_errno(EOVERFLOW);
+      return -1;
+    }
+
+  value32.it_value.tv_sec = value->it_value.tv_sec;
+  value32.it_value.tv_nsec = value->it_value.tv_nsec;
+  value32.it_interval.tv_sec = value->it_interval.tv_sec;
+  value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+  res = INLINE_SYSCALL (timerfd_settime, 4, fd, flags,
+                        &value32, &ovalue32);
+
+  if (res == 0 && ovalue != NULL)
+    {
+      ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+      ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+      ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+      ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+    }
+
+  return res;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=51eadb3be102be21a32aded51a060787132f6fe0

commit 51eadb3be102be21a32aded51a060787132f6fe0
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:48 2017 +0200

    Y2038: add function __timerfd_gettime64
    
    For Linux this uses the 32-bit time syscall so it converts the
    syscall output from 32-bit time to 64-bit time.

diff --git a/rt/Makefile b/rt/Makefile
index 6d6b896..c0aad5d 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -32,7 +32,8 @@ clock-routines := get_clockfreq clock_getcpuclockid			\
 		  clock_getres clock_gettime clock_settime		\
 		  clock_nanosleep
 timer-routines := timer_create timer_delete timer_getoverr		\
-		  timer_gettime timer_settime
+		  timer_gettime timer_settime                           \
+		  timerfd_gettime64
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
diff --git a/rt/Versions b/rt/Versions
index 00bf559..b31ae4c 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -40,5 +40,6 @@ librt {
   GLIBC_2.28 {
    __timer_gettime64;
    __timer_settime64;
+   __timerfd_gettime64;
   }
 }
diff --git a/rt/timerfd_gettime64.c b/rt/timerfd_gettime64.c
new file mode 100644
index 0000000..72d0b68
--- /dev/null
+++ b/rt/timerfd_gettime64.c
@@ -0,0 +1,29 @@
+/* Get current value of timer TIMERID and store it in VALUE.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+int
+__timerfd_gettime64 (int fd, struct itimerspec *value)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_gettime64)
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index 287f470..ce9da27 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,6 +1,7 @@
 GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
+GLIBC_2.28 __timerfd_gettime64 F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 aio_cancel F
 GLIBC_2.4 aio_cancel64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index 8b8c09b..d3d887b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -30,6 +30,7 @@ GLIBC_2.2 timer_settime F
 GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __timer_gettime64 F
 GLIBC_2.28 __timer_settime64 F
+GLIBC_2.28 __timerfd_gettime64 F
 GLIBC_2.3.4 GLIBC_2.3.4 A
 GLIBC_2.3.4 mq_close F
 GLIBC_2.3.4 mq_getattr F
diff --git a/sysdeps/unix/sysv/linux/timerfd_gettime64.c b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
new file mode 100644
index 0000000..51be6c7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
@@ -0,0 +1,54 @@
+/* Get current value of timer TIMERID and store it in VALUE.
+
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include <y2038-support.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_gettime64 (int fd, struct __itimerspec64 *value)
+{
+  int res;
+  struct itimerspec value32;
+
+#ifdef __NR_timerfd_gettime64
+  if (__y2038_get_kernel_support () > 0)
+    {
+      res = INLINE_SYSCALL (timerfd_gettime64, 2, fd, value);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+      __y2038_set_kernel_support (-1);
+    }
+#endif
+
+  res = INLINE_SYSCALL (timerfd_gettime, 2, fd, &value32);
+
+  if (res == 0)
+    {
+      value->it_value.tv_sec = value32.it_value.tv_sec;
+      value->it_value.tv_nsec = value32.it_value.tv_nsec;
+      value->it_interval.tv_sec = value32.it_interval.tv_sec;
+      value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+    }
+
+  return res;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e78c1afdd4fb9d3eb9cfab9b56837f71aa55177a

commit e78c1afdd4fb9d3eb9cfab9b56837f71aa55177a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:47 2017 +0200

    Y2038: add function __timer_settime64
    
    For Linux this uses a 32-bit syscall, so it converts the syscall
    input from 64-bit time into 32-bit time, and the syscall output
    from 32-bit time into 64-bit time.

diff --git a/rt/Versions b/rt/Versions
index e0bfc57..00bf559 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -39,5 +39,6 @@ librt {
   }
   GLIBC_2.28 {
    __timer_gettime64;
+   __timer_settime64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index fb42115..287f470 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,5 +1,6 @@
 GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __timer_gettime64 F
+GLIBC_2.28 __timer_settime64 F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 aio_cancel F
 GLIBC_2.4 aio_cancel64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index 0160bef..8b8c09b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -29,6 +29,7 @@ GLIBC_2.2 timer_gettime F
 GLIBC_2.2 timer_settime F
 GLIBC_2.28 GLIBC_2.28 A
 GLIBC_2.28 __timer_gettime64 F
+GLIBC_2.28 __timer_settime64 F
 GLIBC_2.3.4 GLIBC_2.3.4 A
 GLIBC_2.3.4 mq_close F
 GLIBC_2.3.4 mq_getattr F
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index 7c938bd..bc876a9 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <sysdep.h>
+#include <y2038-support.h>
 #include "kernel-posix-timers.h"
 
 
@@ -41,3 +42,52 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
 
   return res;
 }
+
+/* 64-bit time version */
+
+int
+__timer_settime64 (timer_t timerid, int flags, const struct itimerspec *value,
+                   struct itimerspec *ovalue)
+{
+  int res;
+  struct timer *kt = (struct timer *) timerid;
+  struct itimerspec value32, ovalue32;
+
+  if (value == NULL)
+  {
+    __set_errno(EFAULT);
+    return -1;
+  }
+
+#ifdef __NR_timer_settime64
+  if (__y2038_get_kernel_support () > 0)
+    {
+      res = INLINE_SYSCALL (timer_settime, 3, kt->ktimerid, value, ovalue);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+      __y2038_set_kernel_support (-1);
+    }
+#endif
+
+  if (value->it_value.tv_sec > INT_MAX
+      || value->it_interval.tv_sec > INT_MAX)
+    return EOVERFLOW;
+
+  value32.it_value.tv_sec = value->it_value.tv_sec;
+  value32.it_value.tv_nsec = value->it_value.tv_nsec;
+  value32.it_interval.tv_sec = value->it_interval.tv_sec;
+  value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+  res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
+        &value32, &ovalue32);
+
+  if (res == 0 && ovalue != NULL)
+    {
+      ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+      ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+      ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+      ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+    }
+
+  return res;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f9f1ea00d5b60753f4dbdd93fd1597f1db16a44d

commit f9f1ea00d5b60753f4dbdd93fd1597f1db16a44d
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:46 2017 +0200

    Y2038: add function __timer_gettime64
    
    For Linux this uses the 32-bit time syscall, so it
    converts the syscall output into 64-bit time.

diff --git a/rt/Versions b/rt/Versions
index 91e3fd2..e0bfc57 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -37,4 +37,7 @@ librt {
   GLIBC_2.7 {
    __mq_open_2;
   }
+  GLIBC_2.28 {
+   __timer_gettime64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index cfbbd27..fb42115 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,3 +1,6 @@
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __timer_gettime64 F
+GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 aio_cancel F
 GLIBC_2.4 aio_cancel64 F
 GLIBC_2.4 aio_error F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index 595f1b7..0160bef 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -27,6 +27,9 @@ GLIBC_2.2 timer_delete F
 GLIBC_2.2 timer_getoverrun F
 GLIBC_2.2 timer_gettime F
 GLIBC_2.2 timer_settime F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 __timer_gettime64 F
+GLIBC_2.3.4 GLIBC_2.3.4 A
 GLIBC_2.3.4 mq_close F
 GLIBC_2.3.4 mq_getattr F
 GLIBC_2.3.4 mq_notify F
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 10a19d9..85806f4 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <sysdep.h>
+#include <y2038-support.h>
 #include "kernel-posix-timers.h"
 
 
@@ -39,3 +40,35 @@ timer_gettime (timer_t timerid, struct itimerspec *value)
 
   return res;
 }
+
+/* 64-bit time version */
+
+int
+__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
+{
+  struct itimerspec value32;
+  struct timer *kt = (struct timer *) timerid;
+  int res;
+
+#ifdef __NR_timer_gettime64
+  if (__y2038_get_kernel_support () > 0)
+    {
+      res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+      __y2038_set_kernel_support (-1);
+    }
+#endif
+
+  res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, &value32);
+
+  if (res == 0)
+    {
+      value->it_value.tv_sec = value32.it_value.tv_sec;
+      value->it_value.tv_nsec = value32.it_value.tv_nsec;
+      value->it_interval.tv_sec = value32.it_interval.tv_sec;
+      value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+    }
+
+  return res;
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e8bcf105b52bceaf08dcc90cd419ab18a849aa89

commit e8bcf105b52bceaf08dcc90cd419ab18a849aa89
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:45 2017 +0200

    Y2038: add struct __itimerspec64

diff --git a/include/bits/types/struct_itimerspec64.h b/include/bits/types/struct_itimerspec64.h
new file mode 100644
index 0000000..cc503f7
--- /dev/null
+++ b/include/bits/types/struct_itimerspec64.h
@@ -0,0 +1 @@
+#include <time/bits/types/struct_itimerspec64.h>
diff --git a/sysdeps/unix/sysv/linux/sys/timerfd.h b/sysdeps/unix/sysv/linux/sys/timerfd.h
index 4d75e15..37490cf 100644
--- a/sysdeps/unix/sysv/linux/sys/timerfd.h
+++ b/sysdeps/unix/sysv/linux/sys/timerfd.h
@@ -20,6 +20,7 @@
 
 #include <time.h>
 #include <bits/types/struct_itimerspec.h>
+#include <bits/types/struct_itimerspec64.h>
 
 /* Get the platform-dependent flags.  */
 #include <bits/timerfd.h>
diff --git a/time/Makefile b/time/Makefile
index 5e76bc0..2d60110 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -28,7 +28,8 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 	   bits/types/struct_timespec.h bits/types/struct_timeval.h	\
 	   bits/types/struct_tm.h bits/types/timer_t.h			\
 	   bits/types/time_t.h bits/types/struct_timespec64.h		\
-	   bits/types/struct_timeval64.h
+	   bits/types/struct_timeval64.h				\
+	   bits/types/struct_itimerspec64.h
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
diff --git a/time/bits/types/struct_itimerspec64.h b/time/bits/types/struct_itimerspec64.h
new file mode 100644
index 0000000..039af1c
--- /dev/null
+++ b/time/bits/types/struct_itimerspec64.h
@@ -0,0 +1,15 @@
+#ifndef __itimerspec64_defined
+#define __itimerspec64_defined 1
+
+#include <bits/types.h>
+#include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
+
+/* POSIX.1b structure for timer start values and intervals.  */
+struct __itimerspec64
+{
+  struct __timespec64 it_interval;
+  struct __timespec64 it_value;
+};
+
+#endif
diff --git a/time/time.h b/time/time.h
index c9282e2..dcc275a 100644
--- a/time/time.h
+++ b/time/time.h
@@ -47,6 +47,7 @@
 # include <bits/types/clockid_t.h>
 # include <bits/types/timer_t.h>
 # include <bits/types/struct_itimerspec.h>
+# include <bits/types/struct_itimerspec64.h>
 struct sigevent;
 #endif
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d6e445b11498745c7744fe38b083d55167a18c5a

commit d6e445b11498745c7744fe38b083d55167a18c5a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:44 2017 +0200

    Y2038: add function __lutimes64

diff --git a/misc/lutimes.c b/misc/lutimes.c
index b241c14..e436899 100644
--- a/misc/lutimes.c
+++ b/misc/lutimes.c
@@ -31,3 +31,11 @@ __lutimes (const char *file, const struct timeval tvp[2])
 weak_alias (__lutimes, lutimes)
 
 stub_warning (lutimes)
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__lutimes64)
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 4f2f9ec..e76b9dd 100644
--- a/sysdeps/unix/sysv/linux/lutimes.c
+++ b/sysdeps/unix/sysv/linux/lutimes.c
@@ -22,6 +22,7 @@
 #include <time.h>
 #include <sys/time.h>
 #include <sysdep.h>
+#include <y2038-support.h>
 
 
 int
@@ -42,3 +43,60 @@ lutimes (const char *file, const struct timeval tvp[2])
   return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL,
 			 AT_SYMLINK_NOFOLLOW);
 }
+
+/* 64-bit time version */
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  struct timespec ts32[2], *ts32p = NULL;;
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat_time64
+  /* The system call expects timespec, not timeval.  */
+  struct __timespec64 ts64[2], *ts64p = NULL;
+  int result;
+#endif
+
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat_time64
+  if (__y2038_linux_support > 0)
+    {
+      if (tvp != NULL)
+        {
+          if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+              || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+  	    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+        
+          ts64[0].tv_sec = tvp[0].tv_sec;
+          ts64[0].tv_nsec = tvp[0].tv_usec * 1000;
+          ts64[0].tv_pad = 0;
+          ts64[1].tv_sec = tvp[1].tv_sec;
+          ts64[1].tv_nsec = tvp[1].tv_usec * 1000;
+          ts64[1].tv_pad = 0;
+          ts64p = ts64;
+        }
+    
+      result = INLINE_SYSCALL (utimensat_time64, 4, AT_FDCWD, file, ts64p,
+  	  		     AT_SYMLINK_NOFOLLOW);
+      if (result == 0 || errno == ENOSYS)
+        return result;
+      __y2038_linux_support = -1;
+    }
+#endif
+
+  if (tvp != NULL)
+    {
+      if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+          || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+    
+      ts32[0].tv_sec = tvp[0].tv_sec;
+      ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+      ts32[1].tv_sec = tvp[1].tv_sec;
+      ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+      ts32p = ts32;
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, ts32p,
+                             AT_SYMLINK_NOFOLLOW);
+}
diff --git a/time/Versions b/time/Versions
index 7c4a1a2..9f0df57 100644
--- a/time/Versions
+++ b/time/Versions
@@ -79,5 +79,6 @@ libc {
     __futimens64;
     __sigtimedwait_time64;
     __futimes64;
+    __lutimes64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b941c423071b7d6a4fb03f6e708fc2ff0e1e4776

commit b941c423071b7d6a4fb03f6e708fc2ff0e1e4776
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:43 2017 +0200

    Y2038: add function __futimes64

diff --git a/misc/futimes.c b/misc/futimes.c
index 3ffa40b..c8756a0 100644
--- a/misc/futimes.c
+++ b/misc/futimes.c
@@ -30,3 +30,12 @@ __futimes (int fd, const struct timeval tvp[2])
 weak_alias (__futimes, futimes)
 
 stub_warning (futimes)
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__futimes64)
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index 9e6267c..c3d7678 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -24,6 +24,7 @@
 #include <sys/time.h>
 #include <_itoa.h>
 #include <fcntl.h>
+#include <y2038-support.h>
 
 
 /* Change the access time of the file associated with FD to TVP[0] and
@@ -49,3 +50,61 @@ __futimes (int fd, const struct timeval tvp[2])
   return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0);
 }
 weak_alias (__futimes, futimes)
+
+/* 64-bit time version */
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  struct timespec ts32[2], *ts32p = NULL;
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat_time64
+  /* The utimensat system call expects timespec not timeval.  */
+  struct __timespec64 ts64[2], *ts64p = NULL;
+  int result;
+#endif
+
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat_time64
+  if (__y2038_linux_support > 0)
+    {
+      if (tvp != NULL)
+        {
+          if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+              || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+  	    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+        
+          ts64[0].tv_sec = tvp[0].tv_sec;
+          ts64[0].tv_nsec = tvp[0].tv_usec * 1000;
+          ts64[0].tv_pad = 0;
+          ts64[1].tv_sec = tvp[1].tv_sec;
+          ts64[1].tv_nsec = tvp[1].tv_usec * 1000;
+          ts64[1].tv_pad = 0;
+          ts64p = ts64;
+        }
+    
+      result = INLINE_SYSCALL (utimensat_time64, 4, fd, NULL, ts64p, 0);
+      if (result == 0 || errno != ENOSYS)
+        return result;
+      __y2038_linux_support = -1;
+    }
+#endif
+
+  if (tvp != NULL)
+    {
+      if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+          || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+    
+      if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
+    
+      ts32[0].tv_sec = tvp[0].tv_sec;
+      ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+      ts32[1].tv_sec = tvp[1].tv_sec;
+      ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+      ts32p = ts32;
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, ts32p, 0);
+}
diff --git a/time/Versions b/time/Versions
index 5f8a1bc..7c4a1a2 100644
--- a/time/Versions
+++ b/time/Versions
@@ -78,5 +78,6 @@ libc {
     __utimensat_time64;
     __futimens64;
     __sigtimedwait_time64;
+    __futimes64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=df2de817cd3ddaaa14036784c820506c53a339aa

commit df2de817cd3ddaaa14036784c820506c53a339aa
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:42 2017 +0200

    Y2038: add struct __timeval64
    
    Also, provide static inline functions and macros for checking
    and converting between 32-bit and 64-bit timevals.

diff --git a/bits/resource.h b/bits/resource.h
index 7693d20..c0b00be 100644
--- a/bits/resource.h
+++ b/bits/resource.h
@@ -134,6 +134,7 @@ enum __rusage_who
   };
 
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 #include <bits/types/struct_rusage.h>
 
 /* Priority limits.  */
diff --git a/include/bits/types/struct_timeval64.h b/include/bits/types/struct_timeval64.h
new file mode 100644
index 0000000..fe2ffe6
--- /dev/null
+++ b/include/bits/types/struct_timeval64.h
@@ -0,0 +1 @@
+#include <time/bits/types/struct_timeval64.h>
diff --git a/misc/sys/select.h b/misc/sys/select.h
index 1285dc4..060e7f4 100644
--- a/misc/sys/select.h
+++ b/misc/sys/select.h
@@ -35,6 +35,7 @@
 /* Get definition of timer specification structures.  */
 #include <bits/types/time_t.h>
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 #ifdef __USE_XOPEN2K
 # include <bits/types/struct_timespec.h>
 # include <bits/types/struct_timespec64.h>
diff --git a/resource/bits/types/struct_rusage.h b/resource/bits/types/struct_rusage.h
index 5dc0916..bb2ecb2 100644
--- a/resource/bits/types/struct_rusage.h
+++ b/resource/bits/types/struct_rusage.h
@@ -21,6 +21,7 @@
 
 #include <bits/types.h>
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 
 /* Structure which says how much of each resource has been used.  */
 
diff --git a/sysdeps/unix/sysv/linux/alpha/bits/resource.h b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
index dddcb0f..b602f56 100644
--- a/sysdeps/unix/sysv/linux/alpha/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/alpha/bits/resource.h
@@ -176,6 +176,7 @@ enum __rusage_who
 };
 
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 #include <bits/types/struct_rusage.h>
 
 /* Priority limits.  */
diff --git a/sysdeps/unix/sysv/linux/bits/resource.h b/sysdeps/unix/sysv/linux/bits/resource.h
index fafbadf..1f42d0d 100644
--- a/sysdeps/unix/sysv/linux/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/bits/resource.h
@@ -176,6 +176,7 @@ enum __rusage_who
 };
 
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 #include <bits/types/struct_rusage.h>
 
 /* Priority limits.  */
diff --git a/sysdeps/unix/sysv/linux/bits/timex.h b/sysdeps/unix/sysv/linux/bits/timex.h
index 1dbcc0b..d3c16ec 100644
--- a/sysdeps/unix/sysv/linux/bits/timex.h
+++ b/sysdeps/unix/sysv/linux/bits/timex.h
@@ -20,6 +20,7 @@
 
 #include <bits/types.h>
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 
 /* These definitions from linux/timex.h as of 3.18.  */
 
diff --git a/sysdeps/unix/sysv/linux/mips/bits/resource.h b/sysdeps/unix/sysv/linux/mips/bits/resource.h
index 89d8788..ba46c0b 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/resource.h
@@ -184,6 +184,7 @@ enum __rusage_who
 };
 
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 #include <bits/types/struct_rusage.h>
 
 /* Priority limits.  */
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/resource.h b/sysdeps/unix/sysv/linux/sparc/bits/resource.h
index ee5c26e..1c88169 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/resource.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/resource.h
@@ -192,6 +192,7 @@ enum __rusage_who
 };
 
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 #include <bits/types/struct_rusage.h>
 
 /* Priority limits.  */
diff --git a/time/Makefile b/time/Makefile
index 61b8904..5e76bc0 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -27,7 +27,8 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 	   bits/types/struct_itimerspec.h				\
 	   bits/types/struct_timespec.h bits/types/struct_timeval.h	\
 	   bits/types/struct_tm.h bits/types/timer_t.h			\
-	   bits/types/time_t.h bits/types/struct_timespec64.h
+	   bits/types/time_t.h bits/types/struct_timespec64.h		\
+	   bits/types/struct_timeval64.h
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
diff --git a/time/bits/types/struct_timeval64.h b/time/bits/types/struct_timeval64.h
new file mode 100644
index 0000000..e4966ea
--- /dev/null
+++ b/time/bits/types/struct_timeval64.h
@@ -0,0 +1,13 @@
+#ifndef __timeval64_defined
+#define __timeval64_defined 1
+
+#include <bits/types.h>
+
+/* A time value that is accurate to the nearest
+   microsecond but also has a range of years.  */
+struct __timeval64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __int64_t tv_usec;		/* Microseconds */
+};
+#endif
diff --git a/time/sys/time.h b/time/sys/time.h
index 4166a5b..4e6255e 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -23,6 +23,7 @@
 #include <bits/types.h>
 #include <bits/types/time_t.h>
 #include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timeval64.h>
 
 #ifndef __suseconds_t_defined
 typedef __suseconds_t suseconds_t;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6491513be7c86b8422e7aef282087efc6d74e784

commit 6491513be7c86b8422e7aef282087efc6d74e784
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:41 2017 +0200

    Y2038: add function __sigtimedwait_time64

diff --git a/signal/sigtimedwait.c b/signal/sigtimedwait.c
index 308b9b9..e187883 100644
--- a/signal/sigtimedwait.c
+++ b/signal/sigtimedwait.c
@@ -30,3 +30,13 @@ libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
 
 stub_warning (sigtimedwait)
+
+int
+__sigtimedwait_time64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__sigtimedwait_time64)
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index b4de885..6cfe8f0 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -18,7 +18,11 @@
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+//#include <stdint.h>
+
+//#include <nptl/pthreadP.h>
 #include <sysdep-cancel.h>
+#include <y2038-support.h>
 
 int
 __sigtimedwait (const sigset_t *set, siginfo_t *info,
@@ -39,3 +43,80 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
 }
 libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
+
+/* 64-bit time version */
+
+int
+__sigtimedwait_time64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  int result;
+  struct timespec ts32;
+#ifdef __NR_rt_sigtimedwait_time64
+  struct __timespec64 ts64;
+#endif
+
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+	  ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+#ifdef __NR_rt_sigtimedwait_time64
+  if (__y2038_linux_support > 0)
+    {
+      if (timeout)
+        {
+          ts64.tv_sec = timeout->tv_sec;
+          ts64.tv_nsec = timeout->tv_nsec;
+          ts64.tv_pad = 0;
+          result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, &ts64, _NSIG / 8);
+          if (result == -1 && errno==ENOSYS)
+	    {
+	      __y2038_linux_support = -1;
+	    }
+        }
+      else
+        result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+    }
+  else
+#endif
+    {
+      if (timeout)
+        {
+          if (! timespec64_to_timespec(timeout, &ts32))
+            {
+              errno = EOVERFLOW;
+              return -1;
+            }
+          result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts32, _NSIG / 8);
+        }
+      else
+        result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+    }
+
+  /* The kernel generates a SI_TKILL code in si_code in case tkill is
+     used.  tkill is transparently used in raise().  Since having
+     SI_TKILL as a code is useful in general we fold the results
+     here.  */
+  if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+    info->si_code = SI_USER;
+
+  return result;
+}
diff --git a/time/Versions b/time/Versions
index 04492b1..5f8a1bc 100644
--- a/time/Versions
+++ b/time/Versions
@@ -77,5 +77,6 @@ libc {
     __timespec_get64;
     __utimensat_time64;
     __futimens64;
+    __sigtimedwait_time64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=08e7f17370b0fe5915ab2f86174ce90731f779ce

commit 08e7f17370b0fe5915ab2f86174ce90731f779ce
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:39 2017 +0200

    Y2038: add function __futimens64

diff --git a/io/futimens.c b/io/futimens.c
index fb170ff..2e9648a 100644
--- a/io/futimens.c
+++ b/io/futimens.c
@@ -32,3 +32,11 @@ futimens (int fd, const struct timespec tsp[2])
   return -1;
 }
 stub_warning (futimens)
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__futimens64)
diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c
index bc7fe54..5de651d 100644
--- a/sysdeps/unix/sysv/linux/futimens.c
+++ b/sysdeps/unix/sysv/linux/futimens.c
@@ -21,7 +21,7 @@
 #include <string.h>
 #include <time.h>
 #include <sysdep.h>
-
+#include <y2038-support.h>
 
 /* Change the access time of the file associated with FD to TSP[0] and
    the modification time of FILE to TSP[1].
@@ -36,3 +36,50 @@ futimens (int fd, const struct timespec tsp[2])
   /* Avoid implicit array coercion in syscall macros.  */
   return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0);
 }
+
+/* 64-bit time version */
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  struct timespec ts32[2];
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimesat_time64
+  struct __timespec64 ts64[2];
+  int res;
+#endif
+
+  if (fd < 0)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimesat_time64
+  if (__y2038_linux_support > 0)
+    {
+      ts64[0].tv_sec = tsp[0].tv_sec;
+      ts64[0].tv_nsec = tsp[0].tv_nsec;
+      ts64[0].tv_pad = 0;
+      ts64[1].tv_sec = tsp[1].tv_sec;
+      ts64[1].tv_nsec = tsp[1].tv_nsec;
+      ts64[1].tv_pad = 0;
+      res = INLINE_SYSCALL (utimensat_time64, 4, fd, NULL, &ts64[0], 0);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+      __y2038_linux_support = -1;
+    }
+#endif
+
+  if (! timespec64_to_timespec(&tsp[0], &ts32[0]))
+    {
+      __set_errno(EOVERFLOW);
+      return -1;
+    }
+
+  if (! timespec64_to_timespec(&tsp[1], &ts32[1]))
+    {
+      __set_errno(EOVERFLOW);
+      return -1;
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32[0], 0);
+}
diff --git a/time/Versions b/time/Versions
index b0f8961..04492b1 100644
--- a/time/Versions
+++ b/time/Versions
@@ -76,5 +76,6 @@ libc {
     __clock_nanosleep64;
     __timespec_get64;
     __utimensat_time64;
+    __futimens64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=ffb2ba407619f6732c536b85b0788aec25a392db

commit ffb2ba407619f6732c536b85b0788aec25a392db
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:40 2017 +0200

    Y2038: add function __utimensat_time64

diff --git a/io/utimensat.c b/io/utimensat.c
index 6b67a52..c535930 100644
--- a/io/utimensat.c
+++ b/io/utimensat.c
@@ -30,3 +30,12 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
   return -1;
 }
 stub_warning (utimensat)
+
+int
+__utimensat_time64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utimensat_time64)
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 108d3bc..a0d1f5d 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sysdep.h>
+#include <y2038-support.h>
 
 
 /* Change the access time of FILE to TSP[0] and
@@ -34,3 +35,60 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
   /* Avoid implicit array coercion in syscall macros.  */
   return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags);
 }
+
+/* 64-bit time version */
+
+int
+__utimensat_time64 (int fd, const char *file, const struct __timespec64 tsp[2],
+		    int flags)
+{
+  struct timespec ts32[2], *ts32p = NULL;
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat_time64
+  struct __timespec64 ts64[2], *ts64p = NULL;
+  int res;
+#endif
+
+  if (file == NULL)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+/* Only try and use this syscall if defined by kernel */
+#ifdef __NR_utimensat_time64
+  if (__y2038_linux_support > 0)
+    {
+      if (tsp)
+        {
+          ts64[0].tv_sec = tsp[0].tv_sec;
+          ts64[0].tv_nsec = tsp[0].tv_nsec;
+          ts64[0].tv_pad = 0;
+          ts64[1].tv_sec = tsp[1].tv_sec;
+          ts64[1].tv_nsec = tsp[1].tv_nsec;
+          ts64[1].tv_pad = 0;
+          ts64p = ts64;
+        }
+
+      res = INLINE_SYSCALL (utimensat_time64, 4, fd, file, ts64p, flags);
+      if (res == 0 || errno != ENOSYS)
+        return res;
+      __y2038_linux_support = -1;
+    }
+#endif
+
+  if (tsp)
+    {
+      if (! timespec64_to_timespec(&tsp[0], &ts32[0]))
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+
+      if (! timespec64_to_timespec(&tsp[1], &ts32[1]))
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+      ts32p = ts32;
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, file, ts32p, flags);
+}
diff --git a/time/Versions b/time/Versions
index a4a9c42..b0f8961 100644
--- a/time/Versions
+++ b/time/Versions
@@ -75,5 +75,6 @@ libc {
     __clock_getres_time64;
     __clock_nanosleep64;
     __timespec_get64;
+    __utimensat_time64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fe6090e6ca0809a4a4ad4fb426ff614e5038e111

commit fe6090e6ca0809a4a4ad4fb426ff614e5038e111
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:38 2017 +0200

    Y2038: add function __timespec_get64

diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index b14a302..4cc534a 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -44,3 +44,24 @@ timespec_get (struct timespec *ts, int base)
 
   return base;
 }
+
+/* 64-bit time version */
+
+/* We don't have a 64-bit-time syscall yet, so just convert arguments
+ * between 64-bit and 32-bit time, and use the 32-bit implementation.
+ * 
+ * We could do the reverse and make the 32-bit time implementation a
+ * wrapper around the 64-bit-time implementation, but then 32-bit-time
+ * uses would incur two conversions instead of zero right now.
+ */
+int
+__timespec_get64 (struct __timespec64 *ts, int base)
+{
+  struct timespec ts32;
+  int res = timespec_get (&ts32, base);
+  if (res != base)
+    {
+      timespec_to_timespec64(&ts32, ts);
+    }
+  return res;
+}
diff --git a/time/Versions b/time/Versions
index 07ba1e2..a4a9c42 100644
--- a/time/Versions
+++ b/time/Versions
@@ -74,5 +74,6 @@ libc {
     __clock_settime64;
     __clock_getres_time64;
     __clock_nanosleep64;
+    __timespec_get64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1e6c3968db019ac89294a1b9af9e97c82ef5302a

commit 1e6c3968db019ac89294a1b9af9e97c82ef5302a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:37 2017 +0200

    Y2038: add function __clock_nanosleep64
    
    Linux does not provide a 64-bit-time clock_nanosleep syscall,
    so __clock_nanosleep64 is a wrapper calling __clock_nanosleep,
    with one conversion before the call and possibly one after.
    
    Note:
    
    There is no point in implementing __clock_nanosleep64 directly
    around the 32-bit-time syscall and making __clock_nanosleep a
    wrapper around __clock_nanosleep64, because __clock_nanosleep64
    would still need one or two conversions, and __clock_nanosleep
    would now also need those, adding a cost of 2 to 4 conversions
    in the worst case.

diff --git a/include/time.h b/include/time.h
index 11a1209..70fbe89 100644
--- a/include/time.h
+++ b/include/time.h
@@ -30,6 +30,9 @@ extern int __clock_settime64 (clockid_t __clock_id,
 			       const struct __timespec64 *__tp) __THROW;
 extern int __clock_getres_time64 (clockid_t __clock_id,
 				  struct __timespec64 *__res) __THROW;
+extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
+				const struct __timespec64 *__req,
+				struct __timespec64 *__rem);
 
 /* Now define the internal interfaces.  */
 struct tm;
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 93d5d6e..6878da9 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -21,7 +21,6 @@
 #include <sysdep-cancel.h>
 #include "kernel-posix-cpu-timers.h"
 
-
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
 int
@@ -52,3 +51,51 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
+
+/* 64-bit time version */
+
+/* We don't have a 64-bit-time syscall yet, so just convert arguments
+ * between 64-bit and 32-bit time, and use the 32-bit implementation.
+ * 
+ * We could do the reverse and make the 32-bit time implementation a
+ * wrapper around the 64-bit-time implementation, but then 32-bit-time
+ * uses would incur four conversions instead of zero right now.
+ */
+int
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+		     const struct __timespec64 *req,
+		     struct __timespec64 *rem)
+{
+  int res;
+  struct timespec req32, rem32, *rem32p = NULL;
+
+  if (req == NULL)
+    {
+      __set_errno (EFAULT);
+      return -1;
+    }
+
+  if (req->tv_sec > INT32_MAX || req->tv_sec < INT32_MIN)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  /* For now, use the 32-bit-time implementation above */
+
+  req32.tv_sec = req->tv_sec;
+  req32.tv_nsec = req->tv_nsec;
+
+  if (rem != NULL)
+    rem32p = &rem32;
+
+  res = __clock_nanosleep (clock_id, flags, &req32, rem32p);
+
+  if (res == 0 && rem != NULL)
+    {
+      rem->tv_sec = rem32.tv_sec;
+      rem->tv_nsec = rem32.tv_nsec;
+    }
+
+  return res;
+}
diff --git a/time/Versions b/time/Versions
index 7cb78d2..07ba1e2 100644
--- a/time/Versions
+++ b/time/Versions
@@ -73,5 +73,6 @@ libc {
     __clock_gettime64;
     __clock_settime64;
     __clock_getres_time64;
+    __clock_nanosleep64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fb3d6f365ef25d91bd1accb460d1d6417d13b0d6

commit fb3d6f365ef25d91bd1accb460d1d6417d13b0d6
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:36 2017 +0200

    Y2038: add function __clock_getres_time64
    
    The Unix implementation uses 32-bit calls and converts to
    64-bit time.
    
    The Linux implementation uses the 64-bit time syscall if
    available, otherwise it falls back to 32-bit syscall and
    conversion.
    
    This implementation depends on the clock_getres_time64
    syscall being provided by the kernel at build as well
    as run time.

diff --git a/include/time.h b/include/time.h
index 3775374..11a1209 100644
--- a/include/time.h
+++ b/include/time.h
@@ -28,6 +28,8 @@ 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;
+extern int __clock_getres_time64 (clockid_t __clock_id,
+				  struct __timespec64 *__res) __THROW;
 
 /* Now define the internal interfaces.  */
 struct tm;
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index e7924e0..6b0d5da 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -23,12 +23,11 @@
 #include <sys/param.h>
 #include <libc-internal.h>
 
-
 #if HP_TIMING_AVAIL
 static long int nsec;		/* Clock frequency of the processor.  */
 
 static int
-hp_timing_getres (struct timespec *res)
+hp_timing_getres (struct __timespec64 *res)
 {
   if (__glibc_unlikely (nsec == 0))
     {
@@ -56,7 +55,7 @@ hp_timing_getres (struct timespec *res)
 #endif
 
 static inline int
-realtime_getres (struct timespec *res)
+realtime_getres (struct __timespec64 *res)
 {
   long int clk_tck = __sysconf (_SC_CLK_TCK);
 
@@ -73,17 +72,16 @@ realtime_getres (struct timespec *res)
   return -1;
 }
 
-
 /* Get resolution of clock.  */
 int
-__clock_getres (clockid_t clock_id, struct timespec *res)
+__clock_getres_time64 (clockid_t clock_id, struct __timespec64 *res)
 {
   int retval = -1;
 
   switch (clock_id)
     {
-#ifdef SYSDEP_GETRES
-      SYSDEP_GETRES;
+#ifdef SYSDEP_GETRES64
+      SYSDEP_GETRES64;
 #endif
 
 #ifndef HANDLED_REALTIME
@@ -93,8 +91,8 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
 #endif	/* handled REALTIME */
 
     default:
-#ifdef SYSDEP_GETRES_CPU
-      SYSDEP_GETRES_CPU;
+#ifdef SYSDEP_GETRES_CPU64
+      SYSDEP_GETRES_CPU64;
 #endif
 #if HP_TIMING_AVAIL
       if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
@@ -115,4 +113,19 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
 
   return retval;
 }
+
+int
+__clock_getres (clockid_t clock_id, struct timespec *res)
+{
+  struct __timespec64 ts64;
+  int retval = __clock_getres_time64 (clock_id, &ts64);
+  if (retval == 0)
+    {
+      // We assume we never run with a CPU clock period greater than
+      // 2**31 seconds and therefore we do not check the seconds field
+      res->tv_sec = ts64.tv_sec;
+      res->tv_nsec = ts64.tv_nsec;
+    }
+  return retval;
+}
 weak_alias (__clock_getres, clock_getres)
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 5d94f59..6b895f1 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -19,6 +19,7 @@
 #include <sysdep.h>
 #include <errno.h>
 #include <time.h>
+#include <y2038-support.h>
 #include "kernel-posix-cpu-timers.h"
 
 #ifdef HAVE_CLOCK_GETRES_VSYSCALL
@@ -48,4 +49,64 @@
 #define SYSDEP_GETRES_CPU SYSCALL_GETRES
 #define SYSDEP_GETRES_CPUTIME	/* Default catches them too.  */
 
+/* The 64-bit version */
+
+// Call the 32-bit syscall and convert to 64-bit time
+#define SYSCALL_GETRES32 \
+  retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);		\
+  if (retval==0)							\
+    {									\
+      timespec_to_timespec64(&ts32, res);				\
+      res->tv_pad = 0;							\
+    }
+
+#ifdef __NR_clock_getres_time64
+
+/* We are building with a 64-bit-time getres syscall */
+
+#define SYSCALL_GETRES64 \
+  if (__y2038_linux_support > 0)					\
+    {									\
+      retval = INLINE_SYSCALL (clock_getres_time64, 2, clock_id, res);	\
+      if (retval == -1 && errno == ENOSYS)				\
+	{								\
+	  __y2038_linux_support = -1;					\
+	  SYSCALL_GETRES32;						\
+	}								\
+    }									\
+  else									\
+    {									\
+      SYSCALL_GETRES32;							\
+    }									\
+  break
+
+#else
+
+/* We are building without a 64-bit-time getres syscall */
+
+#define SYSCALL_GETRES64 \
+  SYSCALL_GETRES32;							\
+  break
+
+#endif
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+   kernel.  */
+#define SYSDEP_GETRES64							\
+  SYSDEP_GETRES_CPUTIME64						\
+  case CLOCK_REALTIME:							\
+  case CLOCK_MONOTONIC:							\
+  case CLOCK_MONOTONIC_RAW:						\
+  case CLOCK_REALTIME_COARSE:						\
+  case CLOCK_MONOTONIC_COARSE:						\
+    SYSCALL_GETRES64
+
+/* We handled the REALTIME clock here.  */
+#define HANDLED_REALTIME64	1
+#define HANDLED_CPUTIME64	1
+
+#define SYSDEP_GETRES_CPU64 SYSCALL_GETRES64
+#define SYSDEP_GETRES_CPUTIME64 \
+  struct timespec ts32;
+
 #include <sysdeps/posix/clock_getres.c>
diff --git a/time/Versions b/time/Versions
index bc2a0f0..7cb78d2 100644
--- a/time/Versions
+++ b/time/Versions
@@ -72,5 +72,6 @@ libc {
     __mktime64; __timelocal64_r; __timegm64;
     __clock_gettime64;
     __clock_settime64;
+    __clock_getres_time64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4ccb1e1bbcf450944feeaf1616b95610c870c1e6

commit 4ccb1e1bbcf450944feeaf1616b95610c870c1e6
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:35 2017 +0200

    Y2038: add function __clock_settime64
    
    The Unix implementation converts to 32-bit time and uses
    32-bit calls if possible, or returns -1 / EOVERFLOW.
    
    The Linux implementation uses the 64-bit time syscall if
    available, otherwise it falls back to 32-bit syscall and
    conversion.
    
    This implementation depends on the clock_settime64 syscall
    being provided in the kernel at build as well as run time.

diff --git a/include/time.h b/include/time.h
index 028498d..3775374 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 38813ed..ec59ecf 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -68,8 +68,67 @@ 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)
+{
+#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;
+}
 
-/* 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 5f3f22f..5913dd6 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>
diff --git a/time/Versions b/time/Versions
index 1b1a541..bc2a0f0 100644
--- a/time/Versions
+++ b/time/Versions
@@ -71,5 +71,6 @@ libc {
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r; __timegm64;
     __clock_gettime64;
+    __clock_settime64;
   }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d8330afe40f74e5d1643ef8afe2a333921b8e9fa

commit d8330afe40f74e5d1643ef8afe2a333921b8e9fa
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Sun Apr 8 11:15:24 2018 +0200

    Y2038: add function __clock_gettime64
    
    The Unix implementation uses 32-bit calls and converts to
    64-bit time.
    
    The Linux implementation uses the 64-bit time syscall if
    available, otherwise it falls back to 32-bit syscall and
    conversion.
    
    This implementation depends on the clock_gettime64 syscall
    being provided by the kernel at build as well as run time.

diff --git a/include/time.h b/include/time.h
index c3ec611..028498d 100644
--- a/include/time.h
+++ b/include/time.h
@@ -24,6 +24,9 @@ extern __typeof (clock_settime) __clock_settime;
 extern __typeof (clock_nanosleep) __clock_nanosleep;
 extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
+extern int __clock_gettime64 (clockid_t __clock_id,
+			      struct __timespec64 *__tp) __THROW;
+
 /* Now define the internal interfaces.  */
 struct tm;
 
diff --git a/nptl/pthread_clock_gettime.c b/nptl/pthread_clock_gettime.c
index 6bc75cf..508821b 100644
--- a/nptl/pthread_clock_gettime.c
+++ b/nptl/pthread_clock_gettime.c
@@ -18,13 +18,14 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <time.h>
+#include <bits/types/struct_timespec64.h>
 #include "pthreadP.h"
 
 
 #if HP_TIMING_AVAIL
 int
-__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
-			 struct timespec *tp)
+__pthread_clock_gettime64 (clockid_t clock_id, hp_timing_t freq,
+			   struct __timespec64 *tp)
 {
   hp_timing_t tsc;
 
@@ -64,4 +65,36 @@ __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
 
   return 0;
 }
+
+int
+__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
+			   struct timespec *tp)
+{
+  struct __timespec64 ts64;
+  int res;
+
+  if (tp == NULL)
+    {
+      __set_errno(EINVAL);
+      res = -1;
+    }
+  else
+    {
+      int res = __pthread_clock_gettime64 (clock_id, freq, &ts64);
+      if (res == 0)
+	{
+	  if (fits_in_time_t (ts64.tv_time))
+	    {
+	      tp->tv_sec = ts64.tv_sec;
+	      tp->tv_nsec = ts64.tv_nsec;
+	    }
+	  else
+	    {
+	      set_errno(EOVERFLOW);
+	      res = -1;
+	    }
+	}
+    }
+  return res;
+}
 #endif
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 96df78a..429ec6e 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -32,12 +32,12 @@ static hp_timing_t freq;
 
 
 /* This function is defined in the thread library.  */
-extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
-				    struct timespec *tp)
+extern int __pthread_clock_gettime64 (clockid_t clock_id, hp_timing_t freq,
+				      struct __timespec64 *tp)
      __attribute__ ((__weak__));
 
 static int
-hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
+hp_timing_gettime (clockid_t clock_id, struct __timespec64 *tp)
 {
   hp_timing_t tsc;
 
@@ -55,7 +55,7 @@ hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
 
   if (clock_id != CLOCK_PROCESS_CPUTIME_ID
       && __pthread_clock_gettime != NULL)
-    return __pthread_clock_gettime (clock_id, freq, tp);
+    return __pthread_clock_gettime64 (clock_id, freq, tp);
 
   /* Get the current counter.  */
   HP_TIMING_NOW (tsc);
@@ -76,20 +76,20 @@ hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
 
 
 static inline int
-realtime_gettime (struct timespec *tp)
+realtime_gettime (struct __timespec64 *tp)
 {
   struct timeval tv;
   int retval = __gettimeofday (&tv, NULL);
   if (retval == 0)
     /* Convert into `timespec'.  */
-    TIMEVAL_TO_TIMESPEC (&tv, tp);
+    valid_timeval_to_timespec64 (&tv, tp);
   return retval;
 }
 
 
 /* Get current value of CLOCK and store it in TP.  */
 int
-__clock_gettime (clockid_t clock_id, struct timespec *tp)
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
 {
   int retval = -1;
 
@@ -103,9 +103,9 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
     case CLOCK_REALTIME:
       {
 	struct timeval tv;
-	retval = __gettimeofday (&tv, NULL);
+	retval = __gettimeofday (&tv32, NULL);
 	if (retval == 0)
-	  TIMEVAL_TO_TIMESPEC (&tv, tp);
+	  valid_timeval_to_timespec64 (&tv32, tp);
       }
       break;
 #endif
@@ -132,5 +132,36 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
 
   return retval;
 }
+
+int
+__clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+  struct __timespec64 ts64;
+  int res;
+
+  if (tp == NULL)
+    {
+      __set_errno(EINVAL);
+      res = -1;
+    }
+  else
+    {
+      res = __clock_gettime64 (clock_id, &ts64);
+      if (res == 0)
+	{
+	  if (fits_in_time_t (ts64.tv_time))
+	    {
+	      tp->tv_sec = ts64.tv_sec;
+	      tp->tv_nsec = ts64.tv_nsec;
+	    }
+	  else
+	    {
+	      set_errno(EOVERFLOW);
+	      res = -1;
+	    }
+	}
+    }
+  return res;
+}
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index d837fa3..ba1a55f 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -25,14 +25,49 @@
 # define HAVE_VSYSCALL
 #endif
 #include <sysdep-vdso.h>
+#include <y2038-support.h>
+
+# define DO_CLOCK_GETTIME_32 \
+  retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);		\
+  if (retval == 0)							\
+    {									\
+      valid_timespec_to_timespec64 (&ts32, tp);				\
+    }
+
+#ifdef __NR_clock_gettime64
+
+/* We are building with a 64-bit-time clock_gettime syscall */
+
+# define DO_CLOCK_GETTIME_64 \
+    if (__y2038_linux_support > 0)					\
+      {									\
+	retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp);	\
+	if (retval == -1 && errno == ENOSYS)				\
+	  {								\
+	    __y2038_linux_support = -1;					\
+	    DO_CLOCK_GETTIME_32;					\
+	  }								\
+      }									\
+    else								\
+      {									\
+        DO_CLOCK_GETTIME_32;						\
+      }
+
+#else
+
+/* We are building withoout a 64-bit-time clock_gettime syscall */
+
+# define DO_CLOCK_GETTIME_64 DO_CLOCK_GETTIME_32
+
+#endif
 
 /* The REALTIME and MONOTONIC clock are definitely supported in the
    kernel.  */
 #define SYSDEP_GETTIME \
-  SYSDEP_GETTIME_CPUTIME;						      \
-  case CLOCK_REALTIME:							      \
-  case CLOCK_MONOTONIC:							      \
-    retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp);		      \
+  SYSDEP_GETTIME64_CPUTIME;						\
+  case CLOCK_REALTIME:							\
+  case CLOCK_MONOTONIC:							\
+    DO_CLOCK_GETTIME_64;						\
     break
 
 /* We handled the REALTIME clock here.  */
@@ -44,4 +79,11 @@
   break
 #define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */
 
+#define SYSDEP_GETTIME_CPU(clock_id, tp) \
+  DO_CLOCK_GETTIME_32;							\
+  break
+
+#define SYSDEP_GETTIME_CPUTIME \
+  struct timespec ts32
+
 #include <sysdeps/unix/clock_gettime.c>
diff --git a/time/Versions b/time/Versions
index fd83818..1b1a541 100644
--- a/time/Versions
+++ b/time/Versions
@@ -65,4 +65,11 @@ libc {
   GLIBC_2.16 {
     timespec_get;
   }
+  GLIBC_2.28 {
+    __ctime64; __ctime64_r;
+    __gmtime64; __gmtime64_r;
+    __localtime64; __localtime64_r;
+    __mktime64; __timelocal64_r; __timegm64;
+    __clock_gettime64;
+  }
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=505bfee4f180d85cbb4ed8a6132b8ba33986d4d2

commit 505bfee4f180d85cbb4ed8a6132b8ba33986d4d2
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Fri Sep 8 00:41:33 2017 +0200

    Y2038: add struct __timespec64
    
    To be Y2038-proof, struct __timespec64 needs its tv_sec field to
    be a __time64_t rather than a __time_t. However, the question is
    which type should the tv_nsec field be.
    
    Keeping tv_nsec a long (32-bit) would be compatible with Posix
    requirements but would result in the GLIBC struct timespec being
    binary-incompatible with the Linux 64-bit struct timespec, which
    contains a 64-bit, not 32-bit, signed tv_nsec field.
    
    In order to maintain Posix compatibility yet simplify conversion
    between Posix and Linux struct timespec values, the Y2038-proof
    struct time stores its tv_nsec field as a 32-bit signed integer
    plus a padding which can serve as a 64-bit sign extension. This
    both meets Posix requirements and makes the GLIBC and Linux
    struct timespec binary compatible.
    
    Note that in the API (which is not modified here, and will be
    later alongside all Y2038-sensitive APIs), this padding is made
    'invisible' by defining it as an anonymous bitfield, whereas
    the struct __timespec64 introduced here has a named field for
    the padding, allowing implementations to read and write it.
    
    Also, provide static inline functions and macros for checking
    and converting between 32-bit itimevals and timespecs to 64-bit
    timespecs.

diff --git a/include/bits/types/struct_timespec64.h b/include/bits/types/struct_timespec64.h
new file mode 100644
index 0000000..4286968
--- /dev/null
+++ b/include/bits/types/struct_timespec64.h
@@ -0,0 +1 @@
+#include <time/bits/types/struct_timespec64.h>
diff --git a/include/time.h b/include/time.h
index 63cc855..c3ec611 100644
--- a/include/time.h
+++ b/include/time.h
@@ -144,5 +144,87 @@ fits_in_time_t (__time64_t t)
   return t == (time_t) t;
 } 
 
+/* convert a known valid struct timeval into a struct __timespec64 */
+static inline void
+valid_timeval_to_timespec64 (const struct timeval *tv32,
+			     struct __timespec64 *ts64)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+/* convert a known valid struct timespec into a struct __timespec64 */
+static inline void
+valid_timespec_to_timespec64 (const struct timespec *ts32,
+			      struct __timespec64 *ts64)
+{
+  ts64->tv_sec = ts32->tv_sec;
+  ts64->tv_nsec = ts32->tv_nsec;
+  /* we only need to zero ts64->tv_pad if we pass it to the kernel */
+}
+
+/* convert a known valid struct __timespec64 into a struct timespec */
+static inline void
+valid_timespec64_to_timespec (const struct __timespec64 *ts64,
+			      struct timespec *ts32)
+{
+  ts32->tv_sec = (time_t) ts64->tv_sec;
+  ts32->tv_nsec = ts64->tv_nsec;
+}
+
+/* convert a known valid struct __timespec64 into a struct timeval */
+static inline void
+valid_timespec64_to_timeval (const struct __timespec64 *ts64,
+			     struct timeval *tv32)
+{
+  tv32->tv_sec = (time_t) ts64->tv_sec;
+  tv32->tv_usec = ts64->tv_nsec / 1000;
+}
+
+/* check if a value lies with the valid nanoseconds range */
+#define IS_VALID_NANOSECONDS(ns) (ns >= 0 && ns <= 999999999)
+
+/* check and convert a struct timespec into a struct __timespec64 */
+static inline bool timespec_to_timespec64 (const struct timespec *ts32,
+					   struct __timespec64 *ts64)
+{
+  /* check that ts32 holds a valid count of nanoseconds */
+  if (! IS_VALID_NANOSECONDS (ts32->tv_nsec))
+    return false;
+  /* all ts32 fields can fit in ts64, so copy them */
+  valid_timespec_to_timespec64 (ts32, ts64);
+  /* we only need to zero ts64->tv_pad if we pass it to the kernel */
+  return true;
+}
+
+/* check and convert a struct __timespec64 into a struct timespec */
+static inline bool timespec64_to_timespec (const struct __timespec64 *ts64,
+					   struct timespec *ts32)
+{
+  /* check that tv_nsec holds a valid count of nanoseconds */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* check that tv_sec can fit in a __time_t */
+  if (! fits_in_time_t (ts64->tv_sec))
+    return false;
+  /* all ts64 fields can fit in ts32, so copy them */
+  valid_timespec64_to_timespec (ts64, ts32);
+  return true;
+}
+
+/* check and convert a struct __timespec64 into a struct timeval */
+static inline bool timespec64_to_timeval (const struct __timespec64 *ts64,
+					  struct timeval *tv32)
+{
+  /* check that tv_nsec holds a valid count of nanoseconds */
+  if (! IS_VALID_NANOSECONDS (ts64->tv_nsec))
+    return false;
+  /* check that tv_sec can fit in a __time_t */
+  if (! fits_in_time_t (ts64->tv_sec))
+    return false;
+  /* all ts64 fields can fit in tv32, so copy them */
+  valid_timespec64_to_timeval (ts64, tv32);
+  return true;
+}
 #endif
 #endif
diff --git a/io/fcntl.h b/io/fcntl.h
index 3afc620..e45a8e7 100644
--- a/io/fcntl.h
+++ b/io/fcntl.h
@@ -73,6 +73,7 @@ typedef __pid_t pid_t;
 /* For XPG all symbols from <sys/stat.h> should also be available.  */
 #ifdef __USE_XOPEN2K8
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 #if defined __USE_XOPEN || defined __USE_XOPEN2K8
 # include <bits/stat.h>
diff --git a/io/sys/poll.h b/io/sys/poll.h
index 68f68ca..a4c2547 100644
--- a/io/sys/poll.h
+++ b/io/sys/poll.h
@@ -26,6 +26,7 @@
 #ifdef __USE_GNU
 # include <bits/types/__sigset_t.h>
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 90c403c..cc05fe8 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -28,6 +28,7 @@
 
 #ifdef __USE_XOPEN2K8
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 #if defined __USE_XOPEN || defined __USE_XOPEN2K
diff --git a/misc/sys/select.h b/misc/sys/select.h
index 6dd0c83..1285dc4 100644
--- a/misc/sys/select.h
+++ b/misc/sys/select.h
@@ -37,6 +37,7 @@
 #include <bits/types/struct_timeval.h>
 #ifdef __USE_XOPEN2K
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 #ifndef __suseconds_t_defined
diff --git a/posix/sched.h b/posix/sched.h
index 619b3b3..732c12b 100644
--- a/posix/sched.h
+++ b/posix/sched.h
@@ -30,6 +30,7 @@
 
 #include <bits/types/time_t.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
 #ifndef __USE_XOPEN2K
 # include <time.h>
 #endif
diff --git a/resolv/netdb.h b/resolv/netdb.h
index 003800e..96f675d 100644
--- a/resolv/netdb.h
+++ b/resolv/netdb.h
@@ -35,6 +35,7 @@
 #ifdef __USE_GNU
 # include <bits/types/sigevent_t.h>
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 #include <bits/netdb.h>
diff --git a/rt/aio.h b/rt/aio.h
index c3a1f4b..ffda0de 100644
--- a/rt/aio.h
+++ b/rt/aio.h
@@ -27,6 +27,7 @@
 #include <bits/types/sigevent_t.h>
 #include <bits/sigevent-consts.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
 
 __BEGIN_DECLS
 
diff --git a/rt/mqueue.h b/rt/mqueue.h
index 5f354b4..39e2a24 100644
--- a/rt/mqueue.h
+++ b/rt/mqueue.h
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 #include <bits/types/sigevent_t.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
 /* Get the definition of mqd_t and struct mq_attr.  */
 #include <bits/mqueue.h>
 
diff --git a/signal/signal.h b/signal/signal.h
index 87dc82a..caa2915 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -51,6 +51,7 @@ typedef __uid_t uid_t;
 #ifdef __USE_POSIX199309
 /* We need `struct timespec' later on.  */
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 #if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index df049ab..41b915e 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -27,6 +27,7 @@
 #include <bits/setjmp.h>
 #include <bits/wordsize.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
 
 
 /* Detach state.  */
diff --git a/sysdeps/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
index ff672eb..312433f 100644
--- a/sysdeps/pthread/semaphore.h
+++ b/sysdeps/pthread/semaphore.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 #ifdef __USE_XOPEN2K
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 /* Get the definition for sem_t.  */
diff --git a/sysdeps/unix/sysv/linux/hppa/pthread.h b/sysdeps/unix/sysv/linux/hppa/pthread.h
index 11a024d..e4640b3 100644
--- a/sysdeps/unix/sysv/linux/hppa/pthread.h
+++ b/sysdeps/unix/sysv/linux/hppa/pthread.h
@@ -27,6 +27,7 @@
 #include <bits/setjmp.h>
 #include <bits/wordsize.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
 
 
 /* Detach state.  */
diff --git a/sysvipc/sys/sem.h b/sysvipc/sys/sem.h
index 200765b..b6a7eb2 100644
--- a/sysvipc/sys/sem.h
+++ b/sysvipc/sys/sem.h
@@ -31,6 +31,7 @@
 
 #ifdef __USE_GNU
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 /* The following System V style IPC functions implement a semaphore
diff --git a/time/Makefile b/time/Makefile
index ec3e39d..61b8904 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -27,7 +27,7 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 	   bits/types/struct_itimerspec.h				\
 	   bits/types/struct_timespec.h bits/types/struct_timeval.h	\
 	   bits/types/struct_tm.h bits/types/timer_t.h			\
-	   bits/types/time_t.h
+	   bits/types/time_t.h bits/types/struct_timespec64.h
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
diff --git a/time/bits/types/struct_itimerspec.h b/time/bits/types/struct_itimerspec.h
index 17cc1ac..d36295a 100644
--- a/time/bits/types/struct_itimerspec.h
+++ b/time/bits/types/struct_itimerspec.h
@@ -3,6 +3,7 @@
 
 #include <bits/types.h>
 #include <bits/types/struct_timespec.h>
+#include <bits/types/struct_timespec64.h>
 
 /* POSIX.1b structure for timer start values and intervals.  */
 struct itimerspec
diff --git a/time/bits/types/struct_timespec64.h b/time/bits/types/struct_timespec64.h
new file mode 100644
index 0000000..2221bed
--- /dev/null
+++ b/time/bits/types/struct_timespec64.h
@@ -0,0 +1,29 @@
+#ifndef __timespec64_defined
+#define __timespec64_defined 1
+
+#include <bits/types.h>
+#include <endian.h>
+
+/* Y2036proof structure for a time value.  This is like a `struct timeval' but
+   has nanoseconds instead of microseconds.  To keep tings Posix-ish, we keep
+   the nanoseconds field a signed long, but since Linux has a 64-bit signed int,
+   we pad it with a 32-bit int, which should always be 0.
+   Note that the public type has an anonymous bitfield as padding, so that
+   it cannot be written into (or read from). */ 
+#if BYTE_ORDER == BIG_ENDIAN
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+};
+#else
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+};
+#endif
+
+#endif
diff --git a/time/time.h b/time/time.h
index 4b55e34..c9282e2 100644
--- a/time/time.h
+++ b/time/time.h
@@ -40,6 +40,7 @@
 
 #if defined __USE_POSIX199309 || defined __USE_ISOC11
 # include <bits/types/struct_timespec.h>
+# include <bits/types/struct_timespec64.h>
 #endif
 
 #ifdef __USE_POSIX199309

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f65810268c4362e3cd0dd23e9214f25b1115e25b

commit f65810268c4362e3cd0dd23e9214f25b1115e25b
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Sun Jun 10 10:47:12 2018 +0200

    Y2038: provide kernel support indication
    
    New function __y2038_get_kernel_support() returns:
    - 0 if the underlying kernel does not support Y2038 at all
    - > 0 if the underlying kernel has some support for Y2038
    - < 0 if the underlying kernel support for Y2038 is broken
    
    New function __y2038_set_kernel_support() allows indicating
    a kernel's Y2038 support (or support failure)
    
    Implementations which want to use Y2038 specific kernel
    features (e.g., for Linux, 64-bit-time syscalls) should
    check that __y2038_get_kernel_support() returns positive.
    
    Implementations which detect a failure in a Y2038 specific
    kernel feature (e.g., for Linux, a 64-bit-time syscall has
    returned -1 and errno equals  ENOSYS) should indicate the
    failure by calling __y2038_set_kernel_support() with a
    negative argument.
    
    Default implementation (covering non-Linux kernels) always
    returns 0 (no support).
    
    Linux implementation keep support indication in a libc
    private global, __y2038_linux_support, which is set to
    0 (no support) by default.
    
    Linux implementations which have access to __y2038_linux_support
    (i.e., they are part of libc.so / libc.a) may check or change it
    directly rather than call __y2038_[gs]et_kernel_support().

diff --git a/misc/Makefile b/misc/Makefile
index b7be2bc..027a395 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -71,7 +71,7 @@ routines := brk sbrk sstk ioctl \
 	    fgetxattr flistxattr fremovexattr fsetxattr getxattr \
 	    listxattr lgetxattr llistxattr lremovexattr lsetxattr \
 	    removexattr setxattr getauxval ifunc-impl-list makedev \
-	    allocate_once
+	    allocate_once y2038-support
 
 generated += tst-error1.mtrace tst-error1-mem.out \
   tst-allocate_once.mtrace tst-allocate_once-mem.out
diff --git a/misc/Versions b/misc/Versions
index 900e4ff..9031af3 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -158,6 +158,10 @@ libc {
   GLIBC_2.26 {
     preadv2; preadv64v2; pwritev2; pwritev64v2;
   }
+  GLIBC_2.28 {
+    __y2038_get_kernel_support;
+    __y2038_set_kernel_support;
+  }
   GLIBC_PRIVATE {
     __madvise;
     __mktemp;
diff --git a/misc/y2038-support.c b/misc/y2038-support.c
new file mode 100644
index 0000000..e401cb1
--- /dev/null
+++ b/misc/y2038-support.c
@@ -0,0 +1,32 @@
+/* y2038 general kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* By default glibc assumes the underlying kernel does not support Y2038 */ 
+int __default_y2038_get_kernel_support (void)
+{
+  return 0;
+}
+weak_alias (__default_y2038_get_kernel_support, __y2038_get_kernel_support)
+
+/* By default glibc just ignores Y2038 support indication setting */ 
+int __default_y2038_set_kernel_support (int new with __attribute__ ((unused)))
+{
+  return 0;
+}
+weak_alias (__default_y2038_set_kernel_support, __y2038_set_kernel_support)
diff --git a/misc/y2038-support.h b/misc/y2038-support.h
new file mode 100644
index 0000000..ec7891b
--- /dev/null
+++ b/misc/y2038-support.h
@@ -0,0 +1,36 @@
+/* y2038 general kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Get Y2038 kernel support.
+ * 0 means no suppport
+ * > 0 means (some) support
+ * < 0 means support is broken
+ */
+extern int __y2038_get_kernel_support (void);
+
+/* Set Y2038 support.
+ * 0 means no suppport
+ * > 0 means (some) support
+ * < 0 means support is broken
+ * Architectures should call this with new > 0 as soon as they know that
+ * their underlying kernel has Y2038 support.
+ * Implementations should call this with new < 0 as soon as they detect
+ * that a Y2038 kernel support failure occurred.
+ * As a courtesy, the previous support indication is returned. */
+extern int __y2038_set_kernel_support (int new);
diff --git a/sysdeps/unix/sysv/linux/y2038-support.c b/sysdeps/unix/sysv/linux/y2038-support.c
new file mode 100644
index 0000000..f325efc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.c
@@ -0,0 +1,40 @@
+/* y2038 Linux kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* By default the underlying Linux kernel is assumed not to support Y2038.
+ * Any Linux architecture may claim Y2038 kernel support by setting
+ * __y2038_linux_support.
+ */
+int __y2038_linux_support = 0;
+
+/* For Linux, Y2038 kernel support is determined by __y2038_linux_support  */
+
+int __linux_y2038_get_kernel_support (void)
+{
+  return __y2038_linux_support;
+}
+strong_alias (__linux_y2038_get_kernel_support, __y2038_get_kernel_support)
+
+int __linux_y2038_set_kernel_support (int new)
+{
+  int previous = __y2038_linux_support;
+  __y2038_linux_support = new;
+  return previous;
+}
+strong_alias (__linux_y2038_set_kernel_support, __y2038_set_kernel_support)
diff --git a/sysdeps/unix/sysv/linux/y2038-support.h b/sysdeps/unix/sysv/linux/y2038-support.h
new file mode 100644
index 0000000..95ab2f1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.h
@@ -0,0 +1,27 @@
+/* y2038 Linux kernel support indication.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Indicates Y2038 support, 0 means no suppport, != 0 means support.
+ * Can be read from within libc.
+ * Can be written non-zero to indicate support.
+ */
+extern int __y2038_linux_support;
+
+/* As a fallback, provide generic Y2038 support indication */
+#include <misc/y2038-support.h>

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=dd56bc5d5e52236ede9e897fd749d5871c25a8a3

commit dd56bc5d5e52236ede9e897fd749d5871c25a8a3
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Mar 29 11:57:53 2017 +0200

    Y2038: add function __difftime64
    
    Note:
    
    1. The implementation expects __time64_t arguments, and could,
       in theory, require 64 bits to express the difference accurately;
       but it returns a double, which only provides about 55 significant
       bits.
    
       We could make it return a long double, which would be more than
       enough for 64 bits accuracy. But then, existing source code which
       uses difftime, and therefore stores difftime results in doubles,
       would need to change to long doubles. However, we want 64-bit time
       support to work without any application source code change.
    
       Besides, 55 bits allow for counting seconds accurately over 417
       billion years, which is arguably enough for most actual uses of
       difftime.
    
    2. The 64-bit time implementation was obtained by duplicating the
       original 32-bit code then simplifying the source code based on
       the knowledge that __time64_t is a 64-bit signed integer for
       all architectures. This led to the following removals:
       - in the subtract64 function, removal of code which handled
         unsigned time handling (as __time64_t is signed);
       - in the difftime64 function, removal of code which handled
         time bitsize smaller than or equal to that of a double matissa
         (as __time64_t has more bits than a double mantissa can hold)
    
    3. The 32-bit implementation is now a wrapper around the 64-bit
       one.

diff --git a/include/time.h b/include/time.h
index 5afb123..63cc855 100644
--- a/include/time.h
+++ b/include/time.h
@@ -125,6 +125,12 @@ extern char * __strptime_internal (const char *rp, const char *fmt,
 				   struct tm *tm, void *statep,
 				   locale_t locparam) attribute_hidden;
 
+#if __TIMESIZE == 64
+# define __difftime64 __difftime
+#else
+extern double __difftime64 (__time64_t time1, __time64_t time0);
+#endif
+
 extern double __difftime (time_t time1, time_t time0);
 
 /* Use in the clock_* functions.  Size of the field representing the
diff --git a/time/difftime.c b/time/difftime.c
index 7c5dd98..fbc7ad9 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -30,87 +30,75 @@
 /* Return the difference between TIME1 and TIME0, where TIME0 <= TIME1.
    time_t is known to be an integer type.  */
 
-static double
-subtract (time_t time1, time_t time0)
+static double subtract (__time64_t time1, __time64_t time0)
 {
-  if (! TYPE_SIGNED (time_t))
-    return time1 - time0;
-  else
-    {
-      /* Optimize the common special cases where time_t
-	 can be converted to uintmax_t without losing information.  */
-      uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;
-      double delta = dt;
-
-      if (UINTMAX_MAX / 2 < INTMAX_MAX)
-	{
-	  /* This is a rare host where uintmax_t has padding bits, and possibly
-	     information was lost when converting time_t to uintmax_t.
-	     Check for overflow by comparing dt/2 to (time1/2 - time0/2).
-	     Overflow occurred if they differ by more than a small slop.
-	     Thanks to Clive D.W. Feather for detailed technical advice about
-	     hosts with padding bits.
+  /* Optimize the common special cases where __time64_t
+ can be converted to uintmax_t without losing information.  */
+  uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;
+  double delta = dt;
 
-	     In the following code the "h" prefix means half.  By range
-	     analysis, we have:
+  if (UINTMAX_MAX / 2 < INTMAX_MAX)
+{
+  /* This is a rare host where uintmax_t has padding bits, and possibly
+	 information was lost when converting time_t to uintmax_t.
+	 Check for overflow by comparing dt/2 to (time1/2 - time0/2).
+	 Overflow occurred if they differ by more than a small slop.
+	 Thanks to Clive D.W. Feather for detailed technical advice about
+	 hosts with padding bits.
 
-                  -0.5 <= ht1 - 0.5*time1 <= 0.5
-                  -0.5 <= ht0 - 0.5*time0 <= 0.5
-                  -1.0 <= dht - 0.5*(time1 - time0) <= 1.0
+	 In the following code the "h" prefix means half.  By range
+	 analysis, we have:
 
-             If overflow has not occurred, we also have:
+			  -0.5 <= ht1 - 0.5*time1 <= 0.5
+			  -0.5 <= ht0 - 0.5*time0 <= 0.5
+			  -1.0 <= dht - 0.5*(time1 - time0) <= 1.0
 
-                  -0.5 <= hdt - 0.5*(time1 - time0) <= 0
-                  -1.0 <= dht - hdt <= 1.5
+		 If overflow has not occurred, we also have:
 
-             and since dht - hdt is an integer, we also have:
+			  -0.5 <= hdt - 0.5*(time1 - time0) <= 0
+			  -1.0 <= dht - hdt <= 1.5
 
-                  -1 <= dht - hdt <= 1
+		 and since dht - hdt is an integer, we also have:
 
-             or equivalently:
+			  -1 <= dht - hdt <= 1
 
-                  0 <= dht - hdt + 1 <= 2
+		 or equivalently:
 
-             In the above analysis, all the operators have their exact
-             mathematical semantics, not C semantics.  However, dht - hdt +
-             1 is unsigned in C, so it need not be compared to zero.  */
+			  0 <= dht - hdt + 1 <= 2
 
-	  uintmax_t hdt = dt / 2;
-	  time_t ht1 = time1 / 2;
-	  time_t ht0 = time0 / 2;
-	  time_t dht = ht1 - ht0;
+		 In the above analysis, all the operators have their exact
+		 mathematical semantics, not C semantics.  However, dht - hdt +
+		 1 is unsigned in C, so it need not be compared to zero.  */
 
-	  if (2 < dht - hdt + 1)
-	    {
-	      /* Repair delta overflow.
+  uintmax_t hdt = dt / 2;
+  __time64_t ht1 = time1 / 2;
+  __time64_t ht0 = time0 / 2;
+  __time64_t dht = ht1 - ht0;
 
-		 The following expression contains a second rounding,
-		 so the result may not be the closest to the true answer.
-		 This problem occurs only with very large differences.
-		 It's too painful to fix this portably.  */
+  if (2 < dht - hdt + 1)
+	{
+	  /* Repair delta overflow.
 
-	      delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);
-	    }
+	 The following expression contains a second rounding,
+	 so the result may not be the closest to the true answer.
+	 This problem occurs only with very large differences.
+	 It's too painful to fix this portably.  */
+
+	  delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);
 	}
+}
 
-      return delta;
-    }
+  return delta;
 }
 
 /* Return the difference between TIME1 and TIME0.  */
 double
-__difftime (time_t time1, time_t time0)
+__difftime64 (__time64_t time1, __time64_t time0)
 {
-  /* Convert to double and then subtract if no double-rounding error could
+  /* Convert to long double and then subtract if no double-rounding error could
      result.  */
 
-  if (TYPE_BITS (time_t) <= DBL_MANT_DIG
-      || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double)))
-    return (double) time1 - (double) time0;
-
-  /* Likewise for long double.  */
-
-  if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t))
+  if (TYPE_BITS (__time64_t) <= LDBL_MANT_DIG)
     return (long double) time1 - (long double) time0;
 
   /* Subtract the smaller integer from the larger, convert the difference to
@@ -118,4 +106,16 @@ __difftime (time_t time1, time_t time0)
 
   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
 }
+
+#if __TIMESIZE != 64
+
+/* Return the difference between TIME1 and TIME0.  */
+double
+__difftime (time_t time1, time_t time0)
+{
+  return __difftime64 (time1, time0);
+}
+
+#endif
+
 strong_alias (__difftime, difftime)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9066c714445d793626f25a619c1a403507d726cc

commit 9066c714445d793626f25a619c1a403507d726cc
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 2 13:15:50 2018 +0200

    Y2038: make __mktime_internal compatible with 64-bit-time
    
    This implies that its callers be 64-bit-time compatible too.
    It is done by creating 64-bit-time versions of these and
    turning their original 32-bit-time versions into wrappers
    (at a slight execution time cost).
    
    The callers affected are:
    
          * mktime
          * timelocal (as an alias of mktime)
          * timegm

diff --git a/include/time.h b/include/time.h
index f562f68..5afb123 100644
--- a/include/time.h
+++ b/include/time.h
@@ -50,13 +50,13 @@ extern void __tzset_parse_tz (const char *tz) attribute_hidden;
 extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
   __THROW attribute_hidden;
 
-/* Subroutine of `mktime'.  Return the `time_t' representation of TP and
-   normalize TP, given that a `struct tm *' maps to a `time_t' as performed
+/* Subroutine of `mktime'.  Return the `__time64_t' representation of TP and
+   normalize TP, given that a `struct tm *' maps to a `__time64_t' as performed
    by FUNC.  Keep track of next guess for time_t offset in *OFFSET.  */
-extern time_t __mktime_internal (struct tm *__tp,
-				 struct tm *(*__func) (const time_t *,
-						       struct tm *),
-				 time_t *__offset) attribute_hidden;
+extern __time64_t __mktime_internal (struct tm *__tp,
+				     struct tm *(*__func) (const __time64_t *,
+							   struct tm *),
+				     __time64_t *__offset) attribute_hidden;
 
 /* nis/nis_print.c needs ctime, so even if ctime is not declared here,
    we define __ctime64 as ctime so that nis/nis_print.c can get linked
@@ -131,5 +131,12 @@ extern double __difftime (time_t time1, time_t time0);
    actual clock ID.  */
 #define CLOCK_IDFIELD_SIZE	3
 
+/* Check whether a time64_t value fits in a time_t.  */
+static inline bool
+fits_in_time_t (__time64_t t)
+{
+  return t == (time_t) t;
+} 
+
 #endif
 #endif
diff --git a/time/mktime.c b/time/mktime.c
index 5f038a2..18837c8 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -1,4 +1,4 @@
-/* Convert a 'struct tm' to a time_t value.
+/* Convert a 'struct tm' to a __time64_t value.
    Copyright (C) 1993-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Eggert <eggert@twinsun.com>.
@@ -35,6 +35,7 @@
 #include <time.h>
 
 #include <limits.h>
+#include <errno.h>
 
 #include <string.h>		/* For the real memcpy prototype.  */
 
@@ -92,50 +93,36 @@ verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2);
 #define SHR(a, b)                                               \
   ((-1 >> 1 == -1                                               \
     && (long_int) -1 >> 1 == -1                                 \
-    && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t)))      \
+    && (__time64_t) -1 >> 1 == -1)                              \
    ? (a) >> (b)                                                 \
    : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
 
 /* The extra casts in the following macros work around compiler bugs,
    e.g., in Cray C 5.0.3.0.  */
 
-/* True if the arithmetic type T is an integer type.  bool counts as
-   an integer.  */
-#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
-
 /* True if negative values of the signed integer type T use two's
    complement, or if T is an unsigned integer type.  */
 #define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
 
-/* True if the arithmetic type T is signed.  */
-#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
-
 /* The maximum and minimum values for the integer type T.  These
    macros have undefined behavior if T is signed and has padding bits.
    If this is a problem for you, please let us know how to fix it for
    your host.  */
-#define TYPE_MINIMUM(t) \
-  ((t) (! TYPE_SIGNED (t) \
-	? (t) 0 \
-	: ~ TYPE_MAXIMUM (t)))
-#define TYPE_MAXIMUM(t) \
-  ((t) (! TYPE_SIGNED (t) \
-	? (t) -1 \
-	: ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
-
-#ifndef TIME_T_MIN
-# define TIME_T_MIN TYPE_MINIMUM (time_t)
+#define TYPE_MINIMUM(t) (~ TYPE_MAXIMUM (t))
+#define TYPE_MAXIMUM(t) ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)
+
+#ifndef TIME64_T_MIN
+# define TIME64_T_MIN TYPE_MINIMUM (__time64_t)
 #endif
-#ifndef TIME_T_MAX
-# define TIME_T_MAX TYPE_MAXIMUM (time_t)
+#ifndef TIME64_T_MAX
+# define TIME64_T_MAX TYPE_MAXIMUM (__time64_t)
 #endif
-#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
+#define TIME_T_MIDPOINT (SHR (TIME64_T_MIN + TIME64_T_MAX, 1) + 1)
 
-verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
 verify (twos_complement_arithmetic,
 	(TYPE_TWOS_COMPLEMENT (int)
 	 && TYPE_TWOS_COMPLEMENT (long_int)
-	 && TYPE_TWOS_COMPLEMENT (time_t)));
+	 && TYPE_TWOS_COMPLEMENT (__time64_t)));
 
 #define EPOCH_YEAR 1970
 #define TM_YEAR_BASE 1900
@@ -196,7 +183,7 @@ isdst_differ (int a, int b)
    The result may overflow.  It is the caller's responsibility to
    detect overflow.  */
 
-static time_t
+static __time64_t
 ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
 	    int year0, int yday0, int hour0, int min0, int sec0)
 {
@@ -212,80 +199,73 @@ ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
   int b400 = SHR (b100, 2);
   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
 
-  /* Compute the desired time in time_t precision.  Overflow might
+  /* Compute the desired time in __time64_t precision.  Overflow might
      occur here.  */
-  time_t tyear1 = year1;
-  time_t years = tyear1 - year0;
-  time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
-  time_t hours = 24 * days + hour1 - hour0;
-  time_t minutes = 60 * hours + min1 - min0;
-  time_t seconds = 60 * minutes + sec1 - sec0;
+  __time64_t tyear1 = year1;
+  __time64_t years = tyear1 - year0;
+  __time64_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+  __time64_t hours = 24 * days + hour1 - hour0;
+  __time64_t minutes = 60 * hours + min1 - min0;
+  __time64_t seconds = 60 * minutes + sec1 - sec0;
   return seconds;
 }
 
 /* Return the average of A and B, even if A + B would overflow.  */
-static time_t
-time_t_avg (time_t a, time_t b)
+static __time64_t
+time_t_avg (__time64_t a, __time64_t b)
 {
   return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
 }
 
-/* Return 1 if A + B does not overflow.  If time_t is unsigned and if
-   B's top bit is set, assume that the sum represents A - -B, and
-   return 1 if the subtraction does not wrap around.  */
+/* Return 1 if A + B does not overflow.  */
 static int
-time_t_add_ok (time_t a, time_t b)
+time_t_add_ok (__time64_t a, __time64_t b)
 {
-  if (! TYPE_SIGNED (time_t))
-    {
-      time_t sum = a + b;
-      return (sum < a) == (TIME_T_MIDPOINT <= b);
-    }
-  else if (WRAPV)
+  if (WRAPV)
     {
-      time_t sum = a + b;
+      __time64_t sum = a + b;
       return (sum < a) == (b < 0);
     }
   else
     {
-      time_t avg = time_t_avg (a, b);
-      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+      __time64_t avg = time_t_avg (a, b);
+      return TIME64_T_MIN / 2 <= avg && avg <= TIME64_T_MAX / 2;
     }
 }
 
 /* Return 1 if A + B does not overflow.  */
 static int
-time_t_int_add_ok (time_t a, int b)
+time_t_int_add_ok (__time64_t a, int b)
 {
-  verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX);
+  verify (int_no_wider_than_time_t, INT_MAX <= TIME64_T_MAX);
   if (WRAPV)
     {
-      time_t sum = a + b;
+      __time64_t sum = a + b;
       return (sum < a) == (b < 0);
     }
   else
     {
       int a_odd = a & 1;
-      time_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
-      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+      __time64_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
+      return TIME64_T_MIN / 2 <= avg && avg <= TIME64_T_MAX / 2;
     }
 }
 
-/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+/* Return a __time64_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
    assuming that *T corresponds to *TP and that no clock adjustments
    occurred between *TP and the desired time.
    If TP is null, return a value not equal to *T; this avoids false matches.
    If overflow occurs, yield the minimal or maximal value, except do not
    yield a value equal to *T.  */
-static time_t
+static __time64_t
 guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
-	       const time_t *t, const struct tm *tp)
+	       const __time64_t *t, const struct tm *tp)
 {
   if (tp)
     {
-      time_t d = ydhms_diff (year, yday, hour, min, sec,
-			     tp->tm_year, tp->tm_yday,
-			     tp->tm_hour, tp->tm_min, tp->tm_sec);
+      __time64_t d = ydhms_diff (year, yday, hour, min, sec,
+				 tp->tm_year, tp->tm_yday,
+				 tp->tm_hour, tp->tm_min, tp->tm_sec);
       if (time_t_add_ok (*t, d))
 	return *t + d;
     }
@@ -296,30 +276,30 @@ guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
      match; and don't oscillate between two values, as that would
      confuse the spring-forward gap detector.  */
   return (*t < TIME_T_MIDPOINT
-	  ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
-	  : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+	  ? (*t <= TIME64_T_MIN + 1 ? *t + 1 : TIME64_T_MIN)
+	  : (TIME64_T_MAX - 1 <= *t ? *t - 1 : TIME64_T_MAX));
 }
 
 /* Use CONVERT to convert *T to a broken down time in *TP.
    If *T is out of range for conversion, adjust it so that
    it is the nearest in-range value and then convert that.  */
 static struct tm *
-ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
-		time_t *t, struct tm *tp)
+ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
+		__time64_t *t, struct tm *tp)
 {
   struct tm *r = convert (t, tp);
 
   if (!r && *t)
     {
-      time_t bad = *t;
-      time_t ok = 0;
+      __time64_t bad = *t;
+      __time64_t ok = 0;
 
-      /* BAD is a known unconvertible time_t, and OK is a known good one.
+      /* BAD is a known unconvertible __time64_t, and OK is a known good one.
 	 Use binary search to narrow the range between BAD and OK until
 	 they differ by 1.  */
       while (bad != ok + (bad < 0 ? -1 : 1))
 	{
-	  time_t mid = *t = time_t_avg (ok, bad);
+	  __time64_t mid = *t = time_t_avg (ok, bad);
 	  r = convert (t, tp);
 	  if (r)
 	    ok = mid;
@@ -340,18 +320,18 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
 }
 
 
-/* Convert *TP to a time_t value, inverting
+/* Convert *TP to a __time64_t value, inverting
    the monotonic and mostly-unit-linear conversion function CONVERT.
    Use *OFFSET to keep track of a guess at the offset of the result,
    compared to what the result would be for UTC without leap seconds.
    If *OFFSET's guess is correct, only one CONVERT call is needed.
    This function is external because it is used also by timegm.c.  */
-time_t
+__time64_t
 __mktime_internal (struct tm *tp,
-		   struct tm *(*convert) (const time_t *, struct tm *),
-		   time_t *offset)
+		   struct tm *(*convert) (const __time64_t *, struct tm *),
+		   __time64_t *offset)
 {
-  time_t t, gt, t0, t1, t2;
+  __time64_t t, gt, t0, t1, t2;
   struct tm tm;
 
   /* The maximum number of probes (calls to CONVERT) should be enough
@@ -382,7 +362,7 @@ __mktime_internal (struct tm *tp,
 
   /* The other values need not be in range:
      the remaining code handles minor overflows correctly,
-     assuming int and time_t arithmetic wraps around.
+     assuming int and __time64_t arithmetic wraps around.
      Major overflows are caught at the end.  */
 
   /* Calculate day of year from year, month, and day of month.
@@ -393,7 +373,7 @@ __mktime_internal (struct tm *tp,
   long_int lmday = mday;
   long_int yday = mon_yday + lmday;
 
-  time_t guessed_offset = *offset;
+  __time64_t guessed_offset = *offset;
 
   int sec_requested = sec;
 
@@ -413,12 +393,12 @@ __mktime_internal (struct tm *tp,
   t0 = ydhms_diff (year, yday, hour, min, sec,
 		   EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
 
-  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+  if (TIME64_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
     {
-      /* time_t isn't large enough to rule out overflows, so check
-	 for major overflows.  A gross check suffices, since if t0
-	 has overflowed, it is off by a multiple of TIME_T_MAX -
-	 TIME_T_MIN + 1.  So ignore any component of the difference
+      /* __time64_t is large enough to rule out overflows, but check
+	 for major overflows anyway.  A gross check suffices, since if t0
+	 has overflowed, it is off by a multiple of TIME64_T_MAX -
+	 TIME64_T_MIN + 1.  So ignore any component of the difference
 	 that is bounded by a small value.  */
 
       /* Approximate log base 2 of the number of time units per
@@ -447,20 +427,21 @@ __mktime_internal (struct tm *tp,
       int diff = approx_biennia - approx_requested_biennia;
       int approx_abs_diff = diff < 0 ? -1 - diff : diff;
 
-      /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
+      /* IRIX 4.0.5 cc miscalculates 32-bit TIME_T_MIN / 3: it erroneously
 	 gives a positive value of 715827882.  Setting a variable
-	 first then doing math on it seems to work.
-	 (ghazi@caip.rutgers.edu) */
-      time_t time_t_max = TIME_T_MAX;
-      time_t time_t_min = TIME_T_MIN;
-      time_t overflow_threshold =
+	 first then doing math on it seems to work (ghazi@caip.rutgers.edu).
+	 Do this with 64-bit TIME64_T_MIN too just in case.
+	 */
+      __time64_t time_t_max = TIME64_T_MAX;
+      __time64_t time_t_min = TIME64_T_MIN;
+      __time64_t overflow_threshold =
 	(time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
 
       if (overflow_threshold < approx_abs_diff)
 	{
 	  /* Overflow occurred.  Try repairing it; this might work if
 	     the time zone offset is enough to undo the overflow.  */
-	  time_t repaired_t0 = -1 - t0;
+	  __time64_t repaired_t0 = -1 - t0;
 	  approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
 	  diff = approx_biennia - approx_requested_biennia;
 	  approx_abs_diff = diff < 0 ? -1 - diff : diff;
@@ -533,7 +514,7 @@ __mktime_internal (struct tm *tp,
 	for (direction = -1; direction <= 1; direction += 2)
 	  if (time_t_int_add_ok (t, delta * direction))
 	    {
-	      time_t ot = t + delta * direction;
+	      __time64_t ot = t + delta * direction;
 	      struct tm otm;
 	      ranged_convert (convert, &ot, &otm);
 	      if (! isdst_differ (isdst, otm.tm_isdst))
@@ -575,11 +556,11 @@ __mktime_internal (struct tm *tp,
    offset in seconds.  'int' should be good enough for GNU code.  We
    can't fix this unilaterally though, as other modules invoke
    __mktime_internal.  */
-static time_t localtime_offset;
+static __time64_t localtime_offset;
 
-/* Convert *TP to a time_t value.  */
-time_t
-mktime (struct tm *tp)
+/* Convert *TP to a __time64_t value.  */
+__time64_t
+__mktime64 (struct tm *tp)
 {
 #ifdef _LIBC
   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
@@ -588,7 +569,22 @@ mktime (struct tm *tp)
   __tzset ();
 #endif
 
-  return __mktime_internal (tp, __localtime_r, &localtime_offset);
+  return __mktime_internal (tp, __localtime64_r, &localtime_offset);
+}
+
+#ifdef weak_alias
+weak_alias (__mktime64, __timelocal64)
+#endif
+
+/* The 32-bit-time wrapper.  */
+time_t
+mktime (struct tm *tp)
+{
+  __time64_t t64 = __mktime64 (tp);
+  if (fits_in_time_t (t64))
+    return (time_t) t64;
+  __set_errno (EOVERFLOW);
+  return -1;
 }
 
 #ifdef weak_alias
diff --git a/time/timegm.c b/time/timegm.c
index fb720e2..b36fef2 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -33,15 +33,27 @@
 # include <time_r.h>
 # undef __gmtime_r
 # define __gmtime_r gmtime_r
-time_t __mktime_internal (struct tm *,
-			  struct tm * (*) (time_t const *, struct tm *),
-			  time_t *);
+time64_t __mktime_internal (struct tm *,
+			  struct tm * (*) (__time64_t const *, struct tm *),
+			  __time64_t *);
 #endif
+# include <limits.h>
+# include <errno.h>
+
+__time64_t
+__timegm64 (struct tm *tmp)
+{
+  static __time64_t gmtime_offset;
+  tmp->tm_isdst = 0;
+  return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset);
+}
 
 time_t
 timegm (struct tm *tmp)
 {
-  static time_t gmtime_offset;
-  tmp->tm_isdst = 0;
-  return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
+  __time64_t t64 = __timegm64(tmp);
+  if (fits_in_time_t (t64))
+    return (time_t) t64;
+  __set_errno (EOVERFLOW);
+  return -1;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=072ff047fd21470e6d31769b8403116ddc1e0acc

commit 072ff047fd21470e6d31769b8403116ddc1e0acc
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jun 18 21:14:43 2018 +0200

    Y2038: make __tz_convert compatible with 64-bit-time
    
    This implies that its callers be 64-bit-time compatible too.
    It is done by creating 64-bit-time versions of these and
    turning their original 32-bit-time versions into wrappers
    (at a slight execution time cost).
    
    The callers affected are:
    
      * localtime
      * localtime_r
      * ctime
      * ctime_r
      * gmtime
      * gmtime_r
    
    Note that in time/tzfile.c we do not need to check for time_t
    overflows anymore as introduced by commit fc79706a323 since we
    now use internal_time_t.

diff --git a/include/time.h b/include/time.h
index a311d30..f562f68 100644
--- a/include/time.h
+++ b/include/time.h
@@ -47,7 +47,7 @@ extern void __tzfile_default (const char *std, const char *dst,
 			      long int stdoff, long int dstoff)
   attribute_hidden;
 extern void __tzset_parse_tz (const char *tz) attribute_hidden;
-extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
+extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
   __THROW attribute_hidden;
 
 /* Subroutine of `mktime'.  Return the `time_t' representation of TP and
@@ -57,18 +57,47 @@ extern time_t __mktime_internal (struct tm *__tp,
 				 struct tm *(*__func) (const time_t *,
 						       struct tm *),
 				 time_t *__offset) attribute_hidden;
+
+/* nis/nis_print.c needs ctime, so even if ctime is not declared here,
+   we define __ctime64 as ctime so that nis/nis_print.c can get linked
+   against a function called ctime. */
+#if __TIMESIZE == 64
+# define __ctime64 ctime
+#endif
+
+#if __TIMESIZE == 64
+# define __localtime64 localtime
+#else
+extern struct tm *__localtime64 (const __time64_t *__timer);
+#endif
+
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
+#if __TIMESIZE == 64
+# define __localtime64_r __localtime_r
+#else
+extern struct tm *__localtime64_r (const __time64_t *__timer,
+				   struct tm *__tp) attribute_hidden;
+#endif
+
 extern struct tm *__gmtime_r (const time_t *__restrict __timer,
 			      struct tm *__restrict __tp);
 libc_hidden_proto (__gmtime_r)
 
-/* Compute the `struct tm' representation of *T,
+#if __TIMESIZE == 64
+# define __gmtime64 gmtime
+# define __gmtime64_r __gmtime_r
+#else
+extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer,
+			        struct tm *__restrict __tp);
+#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.
    Return nonzero if successful.  */
-extern int __offtime (const time_t *__timer,
+extern int __offtime (const __time64_t __timer,
 		      long int __offset,
 		      struct tm *__tp) attribute_hidden;
 
@@ -77,8 +106,8 @@ extern char *__asctime_r (const struct tm *__tp, char *__buf)
 extern void __tzset (void) attribute_hidden;
 
 /* Prototype for the internal function to get information based on TZ.  */
-extern struct tm *__tz_convert (const time_t *timer, int use_localtime,
-				struct tm *tp) attribute_hidden;
+extern struct tm *__tz_convert (const __time64_t timer, int use_localtime,
+			        struct tm *tp) attribute_hidden;
 
 extern int __nanosleep (const struct timespec *__requested_time,
 			struct timespec *__remaining);
diff --git a/time/ctime.c b/time/ctime.c
index 1222614..286c6b5 100644
--- a/time/ctime.c
+++ b/time/ctime.c
@@ -20,9 +20,22 @@
 /* Return a string as returned by asctime which
    is the representation of *T in that form.  */
 char *
-ctime (const time_t *t)
+__ctime64 (const __time64_t *t)
 {
   /* The C Standard says ctime (t) is equivalent to asctime (localtime (t)).
      In particular, ctime and asctime must yield the same pointer.  */
-  return asctime (localtime (t));
+  return asctime (__localtime64 (t));
 }
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
+
+char *
+ctime (const time_t *t)
+{
+  __time64_t t64 = *t;
+  return __ctime64 (&t64);
+}
+
+#endif
diff --git a/time/ctime_r.c b/time/ctime_r.c
index c111146..7ad936f 100644
--- a/time/ctime_r.c
+++ b/time/ctime_r.c
@@ -20,10 +20,23 @@
 #include <time.h>
 
 /* Return a string as returned by asctime which is the representation
-   of *T in that form.  Reentrant version.  */
+   of *T in that form.  */
 char *
-ctime_r (const time_t *t, char *buf)
+__ctime64_r (const __time64_t *t, char *buf)
 {
   struct tm tm;
-  return __asctime_r (__localtime_r (t, &tm), buf);
+  return __asctime_r (__localtime64_r (t, &tm), buf);
 }
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
+
+char *
+ctime_r (const time_t *t, char *buf)
+{
+  __time64_t t64 = *t;
+  return __ctime64_r (&t64, buf);
+}
+
+#endif
diff --git a/time/gmtime.c b/time/gmtime.c
index dc33b3e..8ca1a56 100644
--- a/time/gmtime.c
+++ b/time/gmtime.c
@@ -18,20 +18,49 @@
 
 #include <time.h>
 
-/* Return the `struct tm' representation of *T in UTC,
-   using *TP to store the result.  */
+/* Return the `struct tm' representation of 64-bit-time *T
+   in UTC, using *TP to store the result.  */
+struct tm *
+__gmtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert (*t, 0, tp);
+}
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
+
 struct tm *
 __gmtime_r (const time_t *t, struct tm *tp)
 {
-  return __tz_convert (t, 0, tp);
+  __time64_t t64 = *t;
+  return __gmtime64_r (&t64, tp);
 }
+
+#endif
+
+/* This always works because either __TIMESIZE != 64 and __gmtime_r exists
+   or __TIMESIZE == 64 and the definition of __gmtime64_r above actually
+   defined __gmtime_r.  */
 libc_hidden_def (__gmtime_r)
 weak_alias (__gmtime_r, gmtime_r)
 
+/* Return the `struct tm' representation of 64-bit-time *T in UTC.	*/
+struct tm *
+__gmtime64 (const __time64_t *t)
+{
+  return __tz_convert (*t, 0, &_tmbuf);
+}
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
 
-/* Return the `struct tm' representation of *T in UTC.	*/
 struct tm *
 gmtime (const time_t *t)
 {
-  return __tz_convert (t, 0, &_tmbuf);
+  __time64_t t64 = *t;
+  return __gmtime64 (&t64);
 }
+
+#endif
diff --git a/time/localtime.c b/time/localtime.c
index 8684a8a..e36d6cc 100644
--- a/time/localtime.c
+++ b/time/localtime.c
@@ -21,21 +21,49 @@
 /* The C Standard says that localtime and gmtime return the same pointer.  */
 struct tm _tmbuf;
 
-
 /* Return the `struct tm' representation of *T in local time,
    using *TP to store the result.  */
 struct tm *
+__localtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert (*t, 1, tp);
+}
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
+
+struct tm *
 __localtime_r (const time_t *t, struct tm *tp)
 {
-  return __tz_convert (t, 1, tp);
+  __time64_t t64 = *t;
+  return __localtime64_r (&t64, tp);
 }
-weak_alias (__localtime_r, localtime_r)
 
+#endif
+
+/* This always works because either __TIMESIZE != 64 and __localtime_r
+   exists or __TIMESIZE == 64 and the definition of __localtime64_r above
+   actually defined __localtime_r.  */
+weak_alias (__localtime_r, localtime_r)
 
 /* Return the `struct tm' representation of *T in local time.  */
 struct tm *
+__localtime64 (const __time64_t *t)
+{
+  return __tz_convert (*t, 1, &_tmbuf);
+}
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
+
+struct tm *
 localtime (const time_t *t)
 {
-  return __tz_convert (t, 1, &_tmbuf);
+  __time64_t t64 = *t;
+  return __localtime64 (&t64);
 }
 libc_hidden_def (localtime)
+
+#endif
diff --git a/time/offtime.c b/time/offtime.c
index 04c4838..ede23c4 100644
--- a/time/offtime.c
+++ b/time/offtime.c
@@ -21,18 +21,18 @@
 #define	SECS_PER_HOUR	(60 * 60)
 #define	SECS_PER_DAY	(SECS_PER_HOUR * 24)
 
-/* Compute the `struct tm' representation of *T,
+/* 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.
    Return nonzero if successful.  */
 int
-__offtime (const time_t *t, long int offset, struct tm *tp)
+__offtime (const __time64_t t, long int offset, struct tm *tp)
 {
-  time_t days, rem, y;
+  __time64_t days, rem, y;
   const unsigned short int *ip;
 
-  days = *t / SECS_PER_DAY;
-  rem = *t % SECS_PER_DAY;
+  days = t / SECS_PER_DAY;
+  rem = t % SECS_PER_DAY;
   rem += offset;
   while (rem < 0)
     {
@@ -60,7 +60,7 @@ __offtime (const time_t *t, long int offset, struct tm *tp)
   while (days < 0 || days >= (__isleap (y) ? 366 : 365))
     {
       /* Guess a corrected year, assuming 365 days per year.  */
-      time_t yg = y + days / 365 - (days % 365 < 0);
+      __time64_t yg = y + days / 365 - (days % 365 < 0);
 
       /* Adjust DAYS and Y to match the guessed year.  */
       days -= ((yg - y) * 365
diff --git a/time/tzfile.c b/time/tzfile.c
index d7e391c..972e3ff 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -635,16 +635,10 @@ __tzfile_compute (__time64_t timer, int use_localtime,
 
 	  /* Convert to broken down structure.  If this fails do not
 	     use the string.  */
-	  {
-	    time_t truncated = timer;
-	    if (__glibc_unlikely (truncated != timer
-				  || ! __offtime (&truncated, 0, tp)))
-	      goto use_last;
-	  }
-
-	  /* Use the rules from the TZ string to compute the change.
-	     timer fits into time_t due to the truncation check
-	     above.  */
+	  if (__glibc_unlikely (! __offtime (timer, 0, tp)))
+	    goto use_last;
+
+	  /* Use the rules from the TZ string to compute the change.  */
 	  __tz_compute (timer, tp, 1);
 
 	  /* If tzspec comes from posixrules loaded by __tzfile_default,
diff --git a/time/tzset.c b/time/tzset.c
index a828b9f..89d25e2 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -16,7 +16,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <ctype.h>
-#include <errno.h>
 #include <libc-lock.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -27,7 +26,7 @@
 
 #include <timezone/tzfile.h>
 
-#define SECSPERDAY ((time_t) 86400)
+#define SECSPERDAY ((__time64_t) 86400)
 
 char *__tzname[2] = { (char *) "GMT", (char *) "GMT" };
 int __daylight = 0;
@@ -55,7 +54,7 @@ typedef struct
 
     /* We cache the computed time of change for a
        given year so we don't have to recompute it.  */
-    time_t change;	/* When to change to this zone.  */
+    __time64_t change;	/* When to change to this zone.  */
     int computed_for;	/* Year above is computed for.  */
   } tz_rule;
 
@@ -416,7 +415,7 @@ tzset_internal (int always)
       tz_rules[0].name = tz_rules[1].name = "UTC";
       if (J0 != 0)
 	tz_rules[0].type = tz_rules[1].type = J0;
-      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+      tz_rules[0].change = tz_rules[1].change = -1;
       update_vars ();
       return;
     }
@@ -424,13 +423,13 @@ tzset_internal (int always)
   __tzset_parse_tz (tz);
 }
 
-/* Figure out the exact time (as a time_t) in YEAR
+/* Figure out the exact time (as a __time64_t) in YEAR
    when the change described by RULE will occur and
    put it in RULE->change, saving YEAR in RULE->computed_for.  */
 static void
 compute_change (tz_rule *rule, int year)
 {
-  time_t t;
+  __time64_t t;
 
   if (year != -1 && rule->computed_for == year)
     /* Operations on times in 2 BC will be slower.  Oh well.  */
@@ -516,7 +515,7 @@ compute_change (tz_rule *rule, int year)
 /* Figure out the correct timezone for TM and set `__tzname',
    `__timezone', and `__daylight' accordingly.  */
 void
-__tz_compute (time_t timer, struct tm *tm, int use_localtime)
+__tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
 {
   compute_change (&tz_rules[0], 1900 + tm->tm_year);
   compute_change (&tz_rules[1], 1900 + tm->tm_year);
@@ -562,20 +561,14 @@ __tzset (void)
 }
 weak_alias (__tzset, tzset)
 
-/* Return the `struct tm' representation of *TIMER in the local timezone.
+/* Return the `struct tm' representation of TIMER in the local timezone.
    Use local time if USE_LOCALTIME is nonzero, UTC otherwise.  */
 struct tm *
-__tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
+__tz_convert (const __time64_t timer, int use_localtime, struct tm *tp)
 {
   long int leap_correction;
   int leap_extra_secs;
 
-  if (timer == NULL)
-    {
-      __set_errno (EINVAL);
-      return NULL;
-    }
-
   __libc_lock_lock (tzset_lock);
 
   /* Update internal database according to current TZ setting.
@@ -584,14 +577,14 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
   tzset_internal (tp == &_tmbuf && use_localtime);
 
   if (__use_tzfile)
-    __tzfile_compute (*timer, use_localtime, &leap_correction,
+    __tzfile_compute (timer, use_localtime, &leap_correction,
 		      &leap_extra_secs, tp);
   else
     {
       if (! __offtime (timer, 0, tp))
 	tp = NULL;
       else
-	__tz_compute (*timer, tp, use_localtime);
+	__tz_compute (timer, tp, use_localtime);
       leap_correction = 0L;
       leap_extra_secs = 0;
     }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=ee79b8608175d03d9c1641132d70420756776439

commit ee79b8608175d03d9c1641132d70420756776439
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jun 18 21:14:42 2018 +0200

    Y2038: Add 64-bit time for all architectures
    
    * Add macro __TIMESIZE equal to the bit size of time_t.
      It equals the architecture __WORDSIZE except for x32
      where it equals 64.
    
    * Add type __time64_t which is always 64-bit. On 64-bit
      architectures and on x32, it is #defined as time_t.
      On other architectures, it has its own type.
    
    * Replace all occurrences of internal_time_t with
      __time64_t.
    
    The  __time64_t type is public so that the public time_t type
    can be a typedef or #define of __time64_t when we switch the
    public API to 64-bit time.

diff --git a/bits/time64.h b/bits/time64.h
new file mode 100644
index 0000000..a524588
--- /dev/null
+++ b/bits/time64.h
@@ -0,0 +1,37 @@
+/* bits/time64.h -- underlying types for __time64_t.  Generic version.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_TYPES_H
+# error "Never include <bits/time64.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef	_BITS_TIME64_H
+#define	_BITS_TIME64_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#if __TIMESIZE == 64
+/* If we already have 64-bit time then use it.  */
+# define __TIME64_T_TYPE		__TIME_T_TYPE
+#else
+/* Define a 64-bit type alongsize the 32-bit one.  */
+# define __TIME64_T_TYPE		__SQUAD_TYPE
+#endif
+
+#endif /* bits/time64.h */
diff --git a/bits/timesize.h b/bits/timesize.h
new file mode 100644
index 0000000..d8a7804
--- /dev/null
+++ b/bits/timesize.h
@@ -0,0 +1,22 @@
+/* Bit size of the time_t type at glibc build time, general case.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <bits/wordsize.h>
+
+/* Size in bits of the 'time_t' type.  */
+#define __TIMESIZE	__WORDSIZE
diff --git a/include/time.h b/include/time.h
index 23d2580..a311d30 100644
--- a/include/time.h
+++ b/include/time.h
@@ -3,6 +3,7 @@
 
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
+# include <stdbool.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -26,10 +27,6 @@ extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 /* Now define the internal interfaces.  */
 struct tm;
 
-/* time_t variant for representing time zone data, independent of
-   time_t.  */
-typedef __int64_t internal_time_t;
-
 /* Defined in mktime.c.  */
 extern const unsigned short int __mon_yday[2][13] attribute_hidden;
 
@@ -43,7 +40,7 @@ extern int __use_tzfile attribute_hidden;
 
 extern void __tzfile_read (const char *file, size_t extra,
 			   char **extrap) attribute_hidden;
-extern void __tzfile_compute (internal_time_t timer, int use_localtime,
+extern void __tzfile_compute (__time64_t timer, int use_localtime,
 			      long int *leap_correct, int *leap_hit,
 			      struct tm *tp) attribute_hidden;
 extern void __tzfile_default (const char *std, const char *dst,
@@ -101,7 +98,6 @@ extern char * __strptime_internal (const char *rp, const char *fmt,
 
 extern double __difftime (time_t time1, time_t time0);
 
-
 /* Use in the clock_* functions.  Size of the field representing the
    actual clock ID.  */
 #define CLOCK_IDFIELD_SIZE	3
diff --git a/posix/bits/types.h b/posix/bits/types.h
index 5e22ce4..f363381 100644
--- a/posix/bits/types.h
+++ b/posix/bits/types.h
@@ -25,6 +25,7 @@
 
 #include <features.h>
 #include <bits/wordsize.h>
+#include <bits/timesize.h>
 
 /* Convenience types.  */
 typedef unsigned char __u_char;
@@ -138,6 +139,7 @@ __extension__ typedef unsigned long long int __uintmax_t;
 # error
 #endif
 #include <bits/typesizes.h>	/* Defines __*_T_TYPE macros.  */
+#include <bits/time64.h>	/* Defines __TIME*_T_TYPE macros.  */
 
 
 __STD_TYPE __DEV_T_TYPE __dev_t;	/* Type of device numbers.  */
@@ -211,6 +213,12 @@ __STD_TYPE __U32_TYPE __socklen_t;
    It is not currently necessary for this to be machine-specific.  */
 typedef int __sig_atomic_t;
 
+#if __TIMESIZE == 64
+# define __time64_t __time_t
+#else
+__STD_TYPE __TIME64_T_TYPE __time64_t;	/* Seconds since the Epoch (_TIME_BITS==64).  */
+#endif
+
 #undef __STD_TYPE
 
 #endif /* bits/types.h */
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 808a8ce..aab5340 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -29,7 +29,7 @@ headers	:= stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h      \
 	   ucontext.h sys/ucontext.h					      \
 	   alloca.h fmtmsg.h						      \
 	   bits/stdlib-bsearch.h sys/random.h bits/stdint-intn.h	      \
-	   bits/stdint-uintn.h
+	   bits/stdint-uintn.h bits/time64.h bits/timesize.h		      \
 
 routines	:=							      \
 	atof atoi atol atoll						      \
diff --git a/sysdeps/unix/sysv/linux/x86/bits/time64.h b/sysdeps/unix/sysv/linux/x86/bits/time64.h
new file mode 100644
index 0000000..a5e97a0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/bits/time64.h
@@ -0,0 +1,40 @@
+/* bits/time64.h -- underlying types for __time64_t.  Linux/x86-64 version.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_TYPES_H
+# error "Never include <bits/time64.h> directly; use <sys/types.h> instead."
+#endif
+
+#ifndef	_BITS_TIME64_H
+#define	_BITS_TIME64_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#if defined __x86_64__ && defined __ILP32__
+/* For x32, time is 64-bit even though word size is 32-bit.  */
+# define __TIME64_T_TYPE		__SQUAD_TYPE
+#elif __TIMESIZE == 64
+/* If we already have 64-bit time then use it.  */
+# define __TIME64_T_TYPE		__TIME_T_TYPE
+#else
+/* Define a 64-bit type alongsize the 32-bit one.  */
+# define __TIME64_T_TYPE		__SQUAD_TYPE
+#endif
+
+#endif /* bits/time64.h */
diff --git a/sysdeps/unix/sysv/linux/x86/bits/timesize.h b/sysdeps/unix/sysv/linux/x86/bits/timesize.h
new file mode 100644
index 0000000..8b88ab8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/bits/timesize.h
@@ -0,0 +1,25 @@
+/* Bit size of the time_t type at glibc build time, x86-64 and x32 case.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if defined __x86_64__ && defined __ILP32__
+/* For x32, time is 64-bit even though word size is 32-bit.  */
+# define __TIMESIZE	64
+#else
+/* For others, time size is word size.  */
+# define __TIMESIZE	__WORDSIZE
+#endif
diff --git a/time/tzfile.c b/time/tzfile.c
index 2a385b9..d7e391c 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -44,12 +44,12 @@ struct ttinfo
 
 struct leap
   {
-    internal_time_t transition;	/* Time the transition takes effect.  */
+    __time64_t transition;	/* Time the transition takes effect.  */
     long int change;		/* Seconds of correction to apply.  */
   };
 
 static size_t num_transitions;
-libc_freeres_ptr (static internal_time_t *transitions);
+libc_freeres_ptr (static __time64_t *transitions);
 static unsigned char *type_idxs;
 static size_t num_types;
 static struct ttinfo *types;
@@ -113,8 +113,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   size_t tzspec_len;
   char *new = NULL;
 
-  _Static_assert (sizeof (internal_time_t) == 8,
-		  "internal_time_t must be eight bytes");
+  _Static_assert (sizeof (__time64_t) == 8,
+		  "__time64_t must be eight bytes");
 
   __use_tzfile = 0;
 
@@ -220,9 +220,9 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
 
   if (__builtin_expect (num_transitions
 			> ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
-			   / (sizeof (internal_time_t) + 1)), 0))
+			   / (sizeof (__time64_t) + 1)), 0))
     goto lose;
-  total_size = num_transitions * (sizeof (internal_time_t) + 1);
+  total_size = num_transitions * (sizeof (__time64_t) + 1);
   total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
 		& ~(__alignof__ (struct ttinfo) - 1));
   types_idx = total_size;
@@ -279,7 +279,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
     goto lose;
 
   type_idxs = (unsigned char *) transitions + (num_transitions
-					       * sizeof (internal_time_t));
+					       * sizeof (__time64_t));
   types = (struct ttinfo *) ((char *) transitions + types_idx);
   zone_names = (char *) types + num_types * sizeof (struct ttinfo);
   leaps = (struct leap *) ((char *) transitions + leaps_idx);
@@ -580,7 +580,7 @@ __tzfile_default (const char *std, const char *dst,
 }
 
 void
-__tzfile_compute (internal_time_t timer, int use_localtime,
+__tzfile_compute (__time64_t timer, int use_localtime,
 		  long int *leap_correct, int *leap_hit,
 		  struct tm *tp)
 {
@@ -669,7 +669,7 @@ __tzfile_compute (internal_time_t timer, int use_localtime,
 	     initial search spot from it.  Half of a gregorian year
 	     has on average 365.2425 * 86400 / 2 = 15778476 seconds.
 	     The value i can be truncated if size_t is smaller than
-	     internal_time_t, but this is harmless because it is just
+	     __time64_t, but this is harmless because it is just
 	     a guess.  */
 	  i = (transitions[num_transitions - 1] - timer) / 15778476;
 	  if (i < num_transitions)

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


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