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.28.9000-192-gc3645f1


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  c3645f126c2c0decfa289651f349dfa15bd681ca (commit)

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

commit c3645f126c2c0decfa289651f349dfa15bd681ca
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 5bed0a4..47eb58b 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 a1092f5..93ba4be 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=d0b478221cdd8e0e83d529da41e5adb1f73b8ce6

commit d0b478221cdd8e0e83d529da41e5adb1f73b8ce6
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=296b1e231c83efaf5b9bb88214b54f03a782b207

commit 296b1e231c83efaf5b9bb88214b54f03a782b207
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=fdd14fb321493bf2fd09fd2c346c84acb10d2035

commit fdd14fb321493bf2fd09fd2c346c84acb10d2035
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=eb68d772a87dc8df30dc494b5877146b72532014

commit eb68d772a87dc8df30dc494b5877146b72532014
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=376a5a53b281dd543c6db8e4263dba0fbf4136f4

commit 376a5a53b281dd543c6db8e4263dba0fbf4136f4
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=e5de7f45f0e909f4291d37178bfebc2d83bde060

commit e5de7f45f0e909f4291d37178bfebc2d83bde060
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 b4d40c7..42ccf2b 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=af3b2108d320bc1832d159adf11951bd819e88b1

commit af3b2108d320bc1832d159adf11951bd819e88b1
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=c588833cf11e0be4961eece806ba3538cba1b72d

commit c588833cf11e0be4961eece806ba3538cba1b72d
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=597cd097950656ee22d557e689d2fc8184398353

commit 597cd097950656ee22d557e689d2fc8184398353
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=ac7f49ecf35e141e4be7ebaea36e93c8e090837c

commit ac7f49ecf35e141e4be7ebaea36e93c8e090837c
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..a45e684 100644
--- a/resource/Versions
+++ b/resource/Versions
@@ -22,6 +22,9 @@ libc {
     # s*
     setrlimit64;
   }
+  GLIBC_2.29 {
+    __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=f2e3bd488677b0c9027b70826698435d0b88d42f

commit f2e3bd488677b0c9027b70826698435d0b88d42f
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 e7f691d..a205706 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -269,6 +269,7 @@ libpthread {
   GLIBC_2.22 {
   }
 
+<<<<<<< HEAD
   # C11 thread symbols.
   GLIBC_2.28 {
     thrd_create; thrd_detach; thrd_exit; thrd_join;
@@ -277,6 +278,14 @@ libpthread {
     cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
   }
 
+  GLIBC_2.29 {
+    __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 ebf07ca..072375c 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 4844d6b..e57de23 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 af82a4c..e1a2ade 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -27,6 +27,9 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.29 __pthread_cond_timedwait64 F
+GLIBC_2.29 __pthread_mutex_timedlock64 F
+GLIBC_2.29 __sem_timedwait64 F
 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 58e5f4b..88b61f3 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,3 +1,4 @@
+GLIBC_2.29 __aio_suspend64 F
 GLIBC_2.29 __mq_timedreceive64 F
 GLIBC_2.29 __mq_timedsend_time64 F
 GLIBC_2.29 __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 09e8447..228d45c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -227,6 +227,9 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.29 __pthread_cond_timedwait64 F
+GLIBC_2.29 __pthread_mutex_timedlock64 F
+GLIBC_2.29 __sem_timedwait64 F
 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 7027d8a..d384de8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -27,6 +27,7 @@ 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.29 __aio_suspend64 F
 GLIBC_2.29 __mq_timedreceive64 F
 GLIBC_2.29 __mq_timedsend_time64 F
 GLIBC_2.29 __timer_gettime64 F

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

commit 30d4da7015cda72d62e7b065864ab84f2572c6c5
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 155180e..e7368ac 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=e6c079c298881f7a390b291ed4985b65b1413a68

commit e6c079c298881f7a390b291ed4985b65b1413a68
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 a965b69..155180e 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=784ee48747a6c16512888d9c144631e73123cc18

commit 784ee48747a6c16512888d9c144631e73123cc18
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=4e35bda3fc138e126be6f0663d91a19ffb7b449f

commit 4e35bda3fc138e126be6f0663d91a19ffb7b449f
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 ec5c6d7..34075a8 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 \
 	   bits/statx.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 statx		\
diff --git a/io/Versions b/io/Versions
index 90956fe..58dca72 100644
--- a/io/Versions
+++ b/io/Versions
@@ -137,6 +137,7 @@ libc {
     __xstat64_time64;
     __lxstat64_time64;
     __fxstatat64_time64;
+    __utime64;
   }
   GLIBC_PRIVATE {
     __libc_fcntl64;
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=b0d1cb2c81b56cbc08010cd73f3729f103581a3c

commit b0d1cb2c81b56cbc08010cd73f3729f103581a3c
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 c28dab6..a965b69 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=9878ed751296b83118d2ceef3e9920ae383faf53

commit 9878ed751296b83118d2ceef3e9920ae383faf53
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 a66d6db..f40096c 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 deb1be1..56b8f6f 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -139,6 +139,7 @@ libc {
   }
   GLIBC_2.29 {
     __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=c35bf85e71f13ee95cba1969bc341153546091f7

commit c35bf85e71f13ee95cba1969bc341153546091f7
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 8316212..a66d6db 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..deb1be1 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -137,6 +137,9 @@ libc {
   GLIBC_2.27 {
     glob; glob64;
   }
+  GLIBC_2.29 {
+    __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=af62d2a2f50e5e80e8bc4510b1a8b8bfcd816b58

commit af62d2a2f50e5e80e8bc4510b1a8b8bfcd816b58
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=055a30a0792e7d84fa5d6ad7d59bef7d6020d614

commit 055a30a0792e7d84fa5d6ad7d59bef7d6020d614
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 25202cf..4844d6b 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 a056a93..58e5f4b 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,4 +1,5 @@
 GLIBC_2.29 __mq_timedreceive64 F
+GLIBC_2.29 __mq_timedsend_time64 F
 GLIBC_2.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
 GLIBC_2.29 __timerfd_gettime64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index 8142325..7027d8a 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.29 __mq_timedreceive64 F
+GLIBC_2.29 __mq_timedsend_time64 F
 GLIBC_2.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
 GLIBC_2.29 __timerfd_gettime64 F

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

commit 678b84d4785eb03deafdeb989aeb0bebd83a9a75
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 8f757ed..25202cf 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 344fa5b..a056a93 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,3 +1,4 @@
+GLIBC_2.29 __mq_timedreceive64 F
 GLIBC_2.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
 GLIBC_2.29 __timerfd_gettime64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
index f34ae35..8142325 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -27,6 +27,7 @@ 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.29 __mq_timedreceive64 F
 GLIBC_2.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
 GLIBC_2.29 __timerfd_gettime64 F

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

commit 11b0c3541041efaa33d048975d9acddd88041f6c
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 875f368..b4d40c7 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 dd64bf2..4bca299 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 e8b63d2..c28dab6 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=3f7dd7d8c3e112d55dc2fe939e9326f145f1c29a

commit 3f7dd7d8c3e112d55dc2fe939e9326f145f1c29a
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 b5e070f..e8b63d2 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=4c592df421985cbde195c4fedb4566769c7633ec

commit 4c592df421985cbde195c4fedb4566769c7633ec
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 1b178e4..b5e070f 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=429b387674dea0364afe57f937462f69e98ba362

commit 429b387674dea0364afe57f937462f69e98ba362
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 f1b4cbf..1b178e4 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=f4a14ad580fb09334e46ee1ecf85ccca9b775b16

commit f4a14ad580fb09334e46ee1ecf85ccca9b775b16
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 f22ce38..f1b4cbf 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=7f1fc22d765c8cbce6b8e0f3666719c04be6ab25

commit 7f1fc22d765c8cbce6b8e0f3666719c04be6ab25
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 46f9d4c..90956fe 100644
--- a/io/Versions
+++ b/io/Versions
@@ -136,6 +136,7 @@ libc {
     __fxstat64_time64;
     __xstat64_time64;
     __lxstat64_time64;
+    __fxstatat64_time64;
   }
   GLIBC_PRIVATE {
     __libc_fcntl64;
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=992435ed1deb01fa161fb035349731fabd9aff2d

commit 992435ed1deb01fa161fb035349731fabd9aff2d
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 821e375..46f9d4c 100644
--- a/io/Versions
+++ b/io/Versions
@@ -135,6 +135,7 @@ libc {
   GLIBC_2.29 {
     __fxstat64_time64;
     __xstat64_time64;
+    __lxstat64_time64;
   }
   GLIBC_PRIVATE {
     __libc_fcntl64;
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=b9ea2a4e9c60d7a0b0a5194b84d05f31657f4676

commit b9ea2a4e9c60d7a0b0a5194b84d05f31657f4676
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 0d8f63c..821e375 100644
--- a/io/Versions
+++ b/io/Versions
@@ -134,6 +134,7 @@ libc {
   }
   GLIBC_2.29 {
     __fxstat64_time64;
+    __xstat64_time64;
   }
   GLIBC_PRIVATE {
     __libc_fcntl64;
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=a159e8b84c432482a0944e9b0d9d9d6e016b3bfe

commit a159e8b84c432482a0944e9b0d9d9d6e016b3bfe
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 f7e5dbe..0d8f63c 100644
--- a/io/Versions
+++ b/io/Versions
@@ -132,6 +132,9 @@ libc {
     fcntl64;
     statx;
   }
+  GLIBC_2.29 {
+    __fxstat64_time64;
+  }
   GLIBC_PRIVATE {
     __libc_fcntl64;
     __fcntl_nocancel;
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=bbcc0180b381e74e39fcac761cf633b9d4a7d532

commit bbcc0180b381e74e39fcac761cf633b9d4a7d532
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=d7bb79771132eebc477dd773ef317fd4129b3e59

commit d7bb79771132eebc477dd773ef317fd4129b3e59
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 7cee855..8f757ed 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 bcfdc22..344fa5b 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,6 +1,7 @@
 GLIBC_2.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
 GLIBC_2.29 __timerfd_gettime64 F
+GLIBC_2.29 __timerfd_settime64 F
 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 eabb760..f34ae35 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.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
 GLIBC_2.29 __timerfd_gettime64 F
+GLIBC_2.29 __timerfd_settime64 F
 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/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=584a80fbd09117bfe17a37de0111d641bf5e3b1b

commit 584a80fbd09117bfe17a37de0111d641bf5e3b1b
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 c8703cb..7cee855 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -40,5 +40,6 @@ librt {
   GLIBC_2.29 {
    __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 b92173e..bcfdc22 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,5 +1,6 @@
 GLIBC_2.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
+GLIBC_2.29 __timerfd_gettime64 F
 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 e7774ee..eabb760 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.29 __timer_gettime64 F
 GLIBC_2.29 __timer_settime64 F
+GLIBC_2.29 __timerfd_gettime64 F
 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/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=e434ce792ad7fdaed01638e02a6f8d688d995593

commit e434ce792ad7fdaed01638e02a6f8d688d995593
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 e55faa0..c8703cb 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -39,5 +39,6 @@ librt {
   }
   GLIBC_2.29 {
    __timer_gettime64;
+   __timer_settime64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index e18f5ee..b92173e 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,4 +1,5 @@
 GLIBC_2.29 __timer_gettime64 F
+GLIBC_2.29 __timer_settime64 F
 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 cb6ba72..e7774ee 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.29 __timer_gettime64 F
+GLIBC_2.29 __timer_settime64 F
 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_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=7205d506d7138a541b71217df34ffbeabb3dee8a

commit 7205d506d7138a541b71217df34ffbeabb3dee8a
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..e55faa0 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -37,4 +37,7 @@ librt {
   GLIBC_2.7 {
    __mq_open_2;
   }
+  GLIBC_2.29 {
+   __timer_gettime64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist
index cfbbd27..e18f5ee 100644
--- a/sysdeps/unix/sysv/linux/arm/librt.abilist
+++ b/sysdeps/unix/sysv/linux/arm/librt.abilist
@@ -1,3 +1,4 @@
+GLIBC_2.29 __timer_gettime64 F
 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..cb6ba72 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist
@@ -27,6 +27,7 @@ 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.29 __timer_gettime64 F
 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=91fc280dc6feb29744882188926e526a1397e778

commit 91fc280dc6feb29744882188926e526a1397e778
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=35a8e3330782bc98f7e47e7f87693e19776e1c93

commit 35a8e3330782bc98f7e47e7f87693e19776e1c93
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 0a55284..f22ce38 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=e092b67f12cb718ec8aeef4d5c53a0fcf07c2c90

commit e092b67f12cb718ec8aeef4d5c53a0fcf07c2c90
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 8e5f021..0a55284 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=16ecf2019a499928854d56ab14c45a0bd9953cd5

commit 16ecf2019a499928854d56ab14c45a0bd9953cd5
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=4161c9334bc11c63bd1b95ad7205b7e6a0ac1ed5

commit 4161c9334bc11c63bd1b95ad7205b7e6a0ac1ed5
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 5614729..8e5f021 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=d51f971aca2197233ce657b2e3953838e705f2f9

commit d51f971aca2197233ce657b2e3953838e705f2f9
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 c5f6336..5614729 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=01c3e48a3e10e67995ea05ebe9228259f8ada612

commit 01c3e48a3e10e67995ea05ebe9228259f8ada612
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 1e4d81b..c5f6336 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=e12e86bb26d4cb52ff27f85d8b7e7006071b7da6

commit e12e86bb26d4cb52ff27f85d8b7e7006071b7da6
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 5dfe984..1e4d81b 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=bd7df147e3aa47fd3aba220dcf528d69d9b19fbb

commit bd7df147e3aa47fd3aba220dcf528d69d9b19fbb
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 d5bddeb..875f368 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 52feca6..5dfe984 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=d2ec99f8bc0d6fafe800e63ae85033e582addc93

commit d2ec99f8bc0d6fafe800e63ae85033e582addc93
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 5a65822..d5bddeb 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 c07dff1..52feca6 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=d5d5c1bf1e164aaa890ac08d483602e5e7573e7f

commit d5d5c1bf1e164aaa890ac08d483602e5e7573e7f
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 9efd153..5a65822 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..c07dff1 100644
--- a/time/Versions
+++ b/time/Versions
@@ -65,11 +65,12 @@ libc {
   GLIBC_2.16 {
     timespec_get;
   }
-  GLIBC_2.28 {
+  GLIBC_2.29 {
     __ctime64; __ctime64_r;
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r; __timegm64;
     __clock_gettime64;
+    __clock_settime64;
   }
 }

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

commit 76313603ca7a06c992a23933d3f8b18bced4a28c
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 162afa1..9efd153 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..88c1955 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_sec))
+	    {
+	      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..5fd43b6 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_GETTIME_CPUTIME;						\
+  case CLOCK_REALTIME:							\
+  case CLOCK_MONOTONIC:							\
+    DO_CLOCK_GETTIME_64;						\
     break
 
 /* We handled the REALTIME clock here.  */
@@ -40,8 +75,10 @@
 #define HANDLED_CPUTIME	1
 
 #define SYSDEP_GETTIME_CPU(clock_id, tp) \
-  retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \
+  DO_CLOCK_GETTIME_64;							\
   break
-#define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */
+
+#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=ace09db3d797930bcad2fe33c162fddfb8062e22

commit ace09db3d797930bcad2fe33c162fddfb8062e22
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 0c5c002..162afa1 100644
--- a/include/time.h
+++ b/include/time.h
@@ -145,5 +145,87 @@ fits_in_time_t (__time64_t t64)
   return t == t64;
 }
 
+/* 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 6b0e9fa..db00642 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 762c853..a1092f5 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=1ff442400ae87378b773593d39e5c8c99c09fed3

commit 1ff442400ae87378b773593d39e5c8c99c09fed3
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)
    * Default implementation (covering non-Linux kernels) always
      returns 0 (no support).

diff --git a/misc/Makefile b/misc/Makefile
index 9a87e81..dd64bf2 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..e242bf7 100644
--- a/misc/Versions
+++ b/misc/Versions
@@ -158,6 +158,10 @@ libc {
   GLIBC_2.26 {
     preadv2; preadv64v2; pwritev2; pwritev64v2;
   }
+  GLIBC_2.29 {
+    __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..7dcbe0b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/y2038-support.h
@@ -0,0 +1,30 @@
+/* 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 (some) support
+ * < 0 means support is broken
+ * Can be read directly from within libc linux-related files.
+ * Can be written non-zero to indicate support or lack thereof.
+ */
+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=6f1cd69475a4ff50bdbe77a3265a892a81c4b68c

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

    Y2038: add function __difftime64
    
    * __difftime: provide a 64-bit-time version (but do not assume
      __time64_t is a signed int so that Gnulib can reuse the code)
      and make the 32-bit version a wrapper of it.

diff --git a/include/time.h b/include/time.h
index 62c0e11..0c5c002 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..e3a4e57 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -31,9 +31,9 @@
    time_t is known to be an integer type.  */
 
 static double
-subtract (time_t time1, time_t time0)
+subtract (__time64_t time1, __time64_t time0)
 {
-  if (! TYPE_SIGNED (time_t))
+  if (! TYPE_SIGNED (__time64_t))
     return time1 - time0;
   else
     {
@@ -76,9 +76,9 @@ subtract (time_t time1, time_t time0)
              1 is unsigned in C, so it need not be compared to zero.  */
 
 	  uintmax_t hdt = dt / 2;
-	  time_t ht1 = time1 / 2;
-	  time_t ht0 = time0 / 2;
-	  time_t dht = ht1 - ht0;
+	  __time64_t ht1 = time1 / 2;
+	  __time64_t ht0 = time0 / 2;
+	  __time64_t dht = ht1 - ht0;
 
 	  if (2 < dht - hdt + 1)
 	    {
@@ -99,18 +99,18 @@ subtract (time_t time1, time_t time0)
 
 /* 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
      result.  */
 
-  if (TYPE_BITS (time_t) <= DBL_MANT_DIG
-      || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double)))
+  if (TYPE_BITS (__time64_t) <= DBL_MANT_DIG
+      || (TYPE_FLOATING (__time64_t) && sizeof (__time64_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 || TYPE_FLOATING (__time64_t))
     return (long double) time1 - (long double) time0;
 
   /* Subtract the smaller integer from the larger, convert the difference to
@@ -118,4 +118,17 @@ __difftime (time_t time1, time_t time0)
 
   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
 }
+
+/* Provide a 32-bit wrapper if needed */
+
+#if __TIMESIZE != 64
+
+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=19b99883da7cb8e9397c4bec4387350f1218716d

commit 19b99883da7cb8e9397c4bec4387350f1218716d
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Fri Aug 31 23:45:31 2018 -0700

    Add support for __time64_t to mktime, timegm
    
    * include/time.h, time/mktime.c, time/timegm.c:
    Change externally-visible names to their __xxx64yyy version.
    * include/time.h (fits_in_time_t): New static function.
    * time/mktime.c (mktime) [_LIBC]: New wrapper function.
    * time/timegm.c (timegm) [_LIBC]: New wrapper function.

diff --git a/include/time.h b/include/time.h
index c2b43ad..62c0e11 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.  Record next guess for localtime-gmtime offset in *OFFSET.  */
-extern time_t __mktime_internal (struct tm *__tp,
-				 struct tm *(*__func) (const time_t *,
-						       struct tm *),
-				 long int *__offset) attribute_hidden;
+extern __time64_t __mktime_internal (struct tm *__tp,
+				     struct tm *(*__func) (const __time64_t *,
+							   struct tm *),
+				     long int *__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,13 @@ 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 t64)
+{
+  time_t t = t64;
+  return t == t64;
+}
+
 #endif
 #endif
diff --git a/time/mktime.c b/time/mktime.c
index 4ff7490..d8bbae4 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -51,6 +51,7 @@
 
 #include <time.h>
 
+#include <errno.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -125,11 +126,11 @@ my_tzset (void)
    to be subtracted from each other, and sometimes with an offset
    added to them, without worrying about overflow.
 
-   Much of the code uses long_int to represent time_t values, to
-   lessen the hassle of dealing with platforms where time_t is
-   unsigned, and because long_int should suffice to represent all
-   time_t values that mktime can generate even on platforms where
-   time_t is excessively wide.  */
+   Much of the code uses long_int to represent __time64_t values, to
+   lessen the hassle of dealing with Gnulib-using platforms where
+   __time64_t is time_t and time_t is unsigned, and because long_int
+   should suffice to represent all __time64_t values that mktime can
+   generate even on platforms where __time64_t is excessively wide.  */
 
 #if INT_MAX <= LONG_MAX / 3 / 366 / 24 / 60 / 60
 typedef long int long_int;
@@ -157,16 +158,17 @@ shr (long_int a, int b)
 	  : a / (one << b) - (a % (one << b) < 0));
 }
 
-/* Bounds for the intersection of time_t and long_int.  */
+/* Bounds for the intersection of __time64_t and long_int.  */
 
 static long_int const mktime_min
-  = ((TYPE_SIGNED (time_t) && TYPE_MINIMUM (time_t) < TYPE_MINIMUM (long_int))
-     ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (time_t));
+  = ((TYPE_SIGNED (__time64_t)
+      && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
+     ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
 static long_int const mktime_max
-  = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (time_t)
-     ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (time_t));
+  = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
+     ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
 
-verify (TYPE_IS_INTEGER (time_t));
+verify (TYPE_IS_INTEGER (__time64_t));
 
 #define EPOCH_YEAR 1970
 #define TM_YEAR_BASE 1900
@@ -247,11 +249,11 @@ long_int_avg (long_int a, long_int b)
   return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
 }
 
-/* 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.
    Although T and the returned value are of type long_int,
-   they represent time_t values and must be in time_t range.
+   they represent __time64_t values and must be in __time64_t range.
    If TP is null, return a value not equal to T; this avoids false matches.
    YEAR and YDAY must not be so large that multiplying them by three times the
    number of seconds in a year (or day, respectively) would overflow long_int.
@@ -282,22 +284,22 @@ guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
 }
 
 /* Use CONVERT to convert T to a struct tm value in *TM.  T must be in
-   range for time_t.  Return TM if successful, NULL if T is out of
+   range for __time64_t.  Return TM if successful, NULL if T is out of
    range for CONVERT.  */
 static struct tm *
-convert_time (struct tm *(*convert) (const time_t *, struct tm *),
+convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
 	      long_int t, struct tm *tm)
 {
-  time_t x = t;
+  __time64_t x = t;
   return convert (&x, tm);
 }
 
 /* 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.
-   A value is in range if it fits in both time_t and long_int.  */
+   A value is in range if it fits in both __time64_t and long_int.  */
 static struct tm *
-ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
+ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
 		long_int *t, struct tm *tp)
 {
   struct tm *r;
@@ -339,15 +341,15 @@ 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 *),
+		   struct tm *(*convert) (const __time64_t *, struct tm *),
 		   mktime_offset_t *offset)
 {
   long_int t, gt, t0, t1, t2, dt;
@@ -518,9 +520,9 @@ __mktime_internal (struct tm *tp,
 
 #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
 
-/* 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)
 {
   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
      time zone names contained in the external variable 'tzname' shall
@@ -529,7 +531,7 @@ mktime (struct tm *tp)
 
 # if defined __LIBC || NEED_MKTIME_WORKING
   static mktime_offset_t localtime_offset;
-  return __mktime_internal (tp, __localtime_r, &localtime_offset);
+  return __mktime_internal (tp, __localtime64_r, &localtime_offset);
 # else
 #  undef mktime
   return mktime (tp);
@@ -537,8 +539,22 @@ mktime (struct tm *tp)
 }
 #endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
 
+#ifdef _LIBC
+/* The 32-bit-time wrapper.  */
+time_t
+mktime (struct tm *tp)
+{
+  __time64_t t64 = __mktime64 (tp);
+  if (fits_in_time_t (t64))
+    return t64;
+  __set_errno (EOVERFLOW);
+  return -1;
+}
+#endif
+
 #ifdef weak_alias
 weak_alias (mktime, timelocal)
+weak_alias (__mktime64, __timelocal64)
 #endif
 
 #ifdef _LIBC
diff --git a/time/timegm.c b/time/timegm.c
index 229fff2..99b5436 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -24,11 +24,26 @@
 #include <time.h>
 
 #include "mktime-internal.h"
+#include <errno.h>
+
+__time64_t
+__timegm64 (struct tm *tmp)
+{
+  static long int gmtime_offset;
+  tmp->tm_isdst = 0;
+  return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset);
+}
+
+#ifdef _LIBC
 
 time_t
 timegm (struct tm *tmp)
 {
-  static mktime_offset_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 t64;
+  __set_errno (EOVERFLOW);
+  return -1;
 }
+
+#endif

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

commit 1cf24b9a71be9dd184cc1e18283bebd016610e63
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
    
    * __tz_compute: Pass timer as a __time64_t rather than time_t.
    * __offtime: Pass __timer as a __time64_t value rather than
      a const time_t pointer.
    * __tz_convert: Likewise.
    * localtime: provide a 64-bit time version and make the 32-bit
      time version a wrapper of it.
    * localtime_r: Likewise.
    * ctime: Likewise.
    * ctime_r: Likewise.
    * gmtime: Likewise.
    * gmtime_r: Likewise.

diff --git a/include/time.h b/include/time.h
index 082b574..c2b43ad 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 *),
 				 long int *__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 (__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 (__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..8408959 100644
--- a/time/ctime_r.c
+++ b/time/ctime_r.c
@@ -22,8 +22,21 @@
 /* Return a string as returned by asctime which is the representation
    of *T in that form.  Reentrant version.  */
 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..d485a38 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,
+/* Return the `struct tm' representation of 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..3309fcd 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 (__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..834cc3c 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 (__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=c38b85e42f29f0166ceb82e0b84f70b3005bb062

commit c38b85e42f29f0166ceb82e0b84f70b3005bb062
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 definition.
    * Replace all occurrences of internal_time_t with
      __time64_t.

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 e30c5fc..082b574 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 01194bb..bdb0a18 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 bits/indirect-return.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)

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

commit ca32c3f13c38f9fadaf426604ea32c00dc255e9b
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Sun Sep 9 09:06:25 2018 -0700

    Fix mktime localtime offset confusion
    
    [BZ #23603]
    * include/time.h (__mktime_internal): The localtime offset is now
    of type long int instead of time_t.  This is the longstanding type
    in glibc, and it is more than enough to represent difference
    between localtime and gmtime even if it is 32 bits and time_t is
    64.  Changing it now will let us avoid an unnecessary change when
    time_t is widened to 64 bits on 32-bit platforms.
    * time/mktime-internal.h (mktime_offset_t): Now long int.

diff --git a/include/time.h b/include/time.h
index 23d2580..e30c5fc 100644
--- a/include/time.h
+++ b/include/time.h
@@ -55,11 +55,11 @@ extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
 
 /* 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
-   by FUNC.  Keep track of next guess for time_t offset in *OFFSET.  */
+   by FUNC.  Record next guess for localtime-gmtime offset in *OFFSET.  */
 extern time_t __mktime_internal (struct tm *__tp,
 				 struct tm *(*__func) (const time_t *,
 						       struct tm *),
-				 time_t *__offset) attribute_hidden;
+				 long int *__offset) attribute_hidden;
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
diff --git a/time/mktime-internal.h b/time/mktime-internal.h
index ba1d9c7..cfd9127 100644
--- a/time/mktime-internal.h
+++ b/time/mktime-internal.h
@@ -1 +1 @@
-typedef time_t mktime_offset_t;
+typedef long int mktime_offset_t;

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

commit 326841eb597beba02ce20aa4c9a1c7981ebb389b
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Sun Sep 9 09:06:24 2018 -0700

    Merge mktime, timegm from upstream Gnulib
    
    [BZ #23603][BZ #16346]
    This fixes some obscure problems with integer overflow.
    Although it looks scary, it is almost all a byte-for-byte copy
    from Gnulib, and the Gnulib code has been tested reasonably well.
    * include/intprops.h: New file, copied from Gnulib.
    * include/verify.h, time/mktime-internal.h:
    New tiny files, simplified from Gnulib.
    * time/mktime.c: Copy from Gnulib.  This has the following changes:
    Do not include config.h if DEBUG_MKTIME is nonzero.
    Include stdbool.h, intprops.h, verify.h.
    Include string.h only if needed.
    Include stdlib.h on MS-Windows.
    Include mktime-internal.h.
    (DEBUG_MKTIME): Default to 0, and simplify later uses.
    (NEED_MKTIME_INTERNAL, NEED_MKTIME_WINDOWS)
    (NEED_MKTIME_WORKING): Give default values to pacify -Wundef,
    which glibc uses.  Default NEED_MKTIME_WORKING to DEBUG_MKTIME, to
    simplify later conditionals; default the others to zero.  Use
    these conditionals to express only the code needed on the current
    platform.  In uses of these conditionals, explicitly spell out how
    _LIBC affects things, so itâ??s easier to review from a glibc
    viewpoint.
    (WRAPV): Remove; no longer needed now that we have
    systematic overflow checking.
    (my_tzset, __tzset) [!_LIBC]: New function and macro, to better
    compartmentalize tzset issues.  Move system-dependent tzsettish
    code here from mktime.
    (verify): Remove; now done by verify.h.  All uses changed.
    (long_int): Use a more-conservative definition, to avoid
    integer overflow.
    (SHR): Remove, replacing with ...
    (shr): New function, which means we neednâ??t worry about side
    effects in args, and conversion analysis is simpler.
    (TYPE_IS_INTEGER, TYPE_TWOS_COMPLEMENT, TYPE_SIGNED, TYPE_MINIMUM)
    (TYPE_MAXIMUM, TIME_T_MIN, TIME_T_MAX, TIME_T_MIDPOINT)
    (time_t_avg, time_t_add_ok): Remove.
    (mktime_min, mktime_max): New constants.
    (leapyear, isdst_differ): Use bool for booleans.
    (ydhms_diff, guess_time_tm, ranged_convert, __mktime_internal):
    Use long_int, not time_t, for mktime differences.
    (long_int_avg): New function, replacing time_t_avg.
    INT_ADD_WRAPV replaces time_t_add_ok.
    (guess_time_tm): 6th arg is now long_int, not time_t const *.
    All uses changed.
    (convert_time): New function.
    (ranged_convert): Use it.
    (__mktime_internal): Last arg now points to mktime_offset_t, not
    time_t.  All uses changed.  This is a no-op on glibc, where
    mktime_offset_t is always time_t.  Use int, not time_t, for UTC
    offset guess.  Directly check for integer overflow instead of
    using a heuristic that works only 99.9...% of the time.
    Access *OFFSET only once, to avoid an unlikely race if the
    compiler delays a load and if this cascades into a signed integer
    overflow.
    (mktime): Move tzsettish code to my_tzset, and move
    localtime_offset to within mktime so that it doesnâ??t
    need a separate ifdef.
    (main) [DEBUG_MKTIME]: Speed up by using localtime_r
    instead of localtime.
    * time/timegm.c: Copy from Gnulib.  This has the following changes:
    Include mktime-internal.h.
    [!_LIBC]: Include config.h and time.h.  Do not include
    timegm.h or time_r.h.  Make __mktime_internal a macro,
    and include mktime-internal.h to get its declaration.
    (timegm): Temporary is now mktime_offset_t, not time_t.
    This affects only Gnulib.

diff --git a/include/intprops.h b/include/intprops.h
new file mode 100644
index 0000000..9702aec
--- /dev/null
+++ b/include/intprops.h
@@ -0,0 +1,455 @@
+/* intprops.h -- properties of integer types
+
+   Copyright (C) 2001-2018 Free Software Foundation, Inc.
+
+   This program 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.
+
+   This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert.  */
+
+#ifndef _GL_INTPROPS_H
+#define _GL_INTPROPS_H
+
+#include <limits.h>
+
+/* Return a value with the common real type of E and V and the value of V.
+   Do not evaluate E.  */
+#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
+
+/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
+   <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>.  */
+#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
+
+/* 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 the real type T is signed.  */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* Return 1 if the real expression E, after promotion, has a
+   signed or floating type.  Do not evaluate E.  */
+#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
+
+
+/* Minimum and maximum values for integer types and expressions.  */
+
+/* The width in bits of the integer type or expression T.
+   Do not evaluate T.
+   Padding bits are not supported; this is checked at compile-time below.  */
+#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
+
+/* The maximum and minimum values for the integer type T.  */
+#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
+#define TYPE_MAXIMUM(t)                                                 \
+  ((t) (! TYPE_SIGNED (t)                                               \
+        ? (t) -1                                                        \
+        : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
+
+/* The maximum and minimum values for the type of the expression E,
+   after integer promotion.  E is not evaluated.  */
+#define _GL_INT_MINIMUM(e)                                              \
+  (EXPR_SIGNED (e)                                                      \
+   ? ~ _GL_SIGNED_INT_MAXIMUM (e)                                       \
+   : _GL_INT_CONVERT (e, 0))
+#define _GL_INT_MAXIMUM(e)                                              \
+  (EXPR_SIGNED (e)                                                      \
+   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
+   : _GL_INT_NEGATE_CONVERT (e, 1))
+#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
+  (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1)
+
+/* Work around OpenVMS incompatibility with C99.  */
+#if !defined LLONG_MAX && defined __INT64_MAX
+# define LLONG_MAX __INT64_MAX
+# define LLONG_MIN __INT64_MIN
+#endif
+
+/* This include file assumes that signed types are two's complement without
+   padding bits; the above macros have undefined behavior otherwise.
+   If this is a problem for you, please let us know how to fix it for your host.
+   This assumption is tested by the intprops-tests module.  */
+
+/* Does the __typeof__ keyword work?  This could be done by
+   'configure', but for now it's easier to do it by hand.  */
+#if (2 <= __GNUC__ \
+     || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
+     || (0x5110 <= __SUNPRO_C && !__STDC__))
+# define _GL_HAVE___TYPEOF__ 1
+#else
+# define _GL_HAVE___TYPEOF__ 0
+#endif
+
+/* Return 1 if the integer type or expression T might be signed.  Return 0
+   if it is definitely unsigned.  This macro does not evaluate its argument,
+   and expands to an integer constant expression.  */
+#if _GL_HAVE___TYPEOF__
+# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t))
+#else
+# define _GL_SIGNED_TYPE_OR_EXPR(t) 1
+#endif
+
+/* Bound on length of the string representing an unsigned integer
+   value representable in B bits.  log10 (2.0) < 146/485.  The
+   smallest value of B where this bound is not tight is 2621.  */
+#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
+
+/* Bound on length of the string representing an integer type or expression T.
+   Subtract 1 for the sign bit if T is signed, and then add 1 more for
+   a minus sign if needed.
+
+   Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is
+   signed, this macro may overestimate the true bound by one byte when
+   applied to unsigned types of size 2, 4, 16, ... bytes.  */
+#define INT_STRLEN_BOUND(t)                                     \
+  (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
+   + _GL_SIGNED_TYPE_OR_EXPR (t))
+
+/* Bound on buffer size needed to represent an integer type or expression T,
+   including the terminating null.  */
+#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
+
+
+/* Range overflow checks.
+
+   The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C
+   operators might not yield numerically correct answers due to
+   arithmetic overflow.  They do not rely on undefined or
+   implementation-defined behavior.  Their implementations are simple
+   and straightforward, but they are a bit harder to use than the
+   INT_<op>_OVERFLOW macros described below.
+
+   Example usage:
+
+     long int i = ...;
+     long int j = ...;
+     if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX))
+       printf ("multiply would overflow");
+     else
+       printf ("product is %ld", i * j);
+
+   Restrictions on *_RANGE_OVERFLOW macros:
+
+   These macros do not check for all possible numerical problems or
+   undefined or unspecified behavior: they do not check for division
+   by zero, for bad shift counts, or for shifting negative numbers.
+
+   These macros may evaluate their arguments zero or multiple times,
+   so the arguments should not have side effects.  The arithmetic
+   arguments (including the MIN and MAX arguments) must be of the same
+   integer type after the usual arithmetic conversions, and the type
+   must have minimum value MIN and maximum MAX.  Unsigned types should
+   use a zero MIN of the proper type.
+
+   These macros are tuned for constant MIN and MAX.  For commutative
+   operations such as A + B, they are also tuned for constant B.  */
+
+/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  */
+#define INT_ADD_RANGE_OVERFLOW(a, b, min, max)          \
+  ((b) < 0                                              \
+   ? (a) < (min) - (b)                                  \
+   : (max) - (b) < (a))
+
+/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  */
+#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max)     \
+  ((b) < 0                                              \
+   ? (max) + (b) < (a)                                  \
+   : (a) < (min) + (b))
+
+/* Return 1 if - A would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  */
+#define INT_NEGATE_RANGE_OVERFLOW(a, min, max)          \
+  ((min) < 0                                            \
+   ? (a) < - (max)                                      \
+   : 0 < (a))
+
+/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Avoid && and || as they tickle
+   bugs in Sun C 5.11 2010/08/13 and other compilers; see
+   <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>.  */
+#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
+  ((b) < 0                                              \
+   ? ((a) < 0                                           \
+      ? (a) < (max) / (b)                               \
+      : (b) == -1                                       \
+      ? 0                                               \
+      : (min) / (b) < (a))                              \
+   : (b) == 0                                           \
+   ? 0                                                  \
+   : ((a) < 0                                           \
+      ? (a) < (min) / (b)                               \
+      : (max) / (b) < (a)))
+
+/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Do not check for division by zero.  */
+#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max)       \
+  ((min) < 0 && (b) == -1 && (a) < - (max))
+
+/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Do not check for division by zero.
+   Mathematically, % should never overflow, but on x86-like hosts
+   INT_MIN % -1 traps, and the C standard permits this, so treat this
+   as an overflow too.  */
+#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max)    \
+  INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max)
+
+/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic.
+   See above for restrictions.  Here, MIN and MAX are for A only, and B need
+   not be of the same type as the other arguments.  The C standard says that
+   behavior is undefined for shifts unless 0 <= B < wordwidth, and that when
+   A is negative then A << B has undefined behavior and A >> B has
+   implementation-defined behavior, but do not check these other
+   restrictions.  */
+#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max)   \
+  ((a) < 0                                              \
+   ? (a) < (min) >> (b)                                 \
+   : (max) >> (b) < (a))
+
+/* True if __builtin_add_overflow (A, B, P) works when P is non-null.  */
+#if 5 <= __GNUC__ && !defined __ICC
+# define _GL_HAS_BUILTIN_OVERFLOW 1
+#else
+# define _GL_HAS_BUILTIN_OVERFLOW 0
+#endif
+
+/* True if __builtin_add_overflow_p (A, B, C) works.  */
+#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+
+/* The _GL*_OVERFLOW macros have the same restrictions as the
+   *_RANGE_OVERFLOW macros, except that they do not assume that operands
+   (e.g., A and B) have the same type as MIN and MAX.  Instead, they assume
+   that the result (e.g., A + B) has that type.  */
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define _GL_ADD_OVERFLOW(a, b, min, max)                               \
+   __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0)
+# define _GL_SUBTRACT_OVERFLOW(a, b, min, max)                          \
+   __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0)
+# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                          \
+   __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0)
+#else
+# define _GL_ADD_OVERFLOW(a, b, min, max)                                \
+   ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max)                  \
+    : (a) < 0 ? (b) <= (a) + (b)                                         \
+    : (b) < 0 ? (a) <= (a) + (b)                                         \
+    : (a) + (b) < (b))
+# define _GL_SUBTRACT_OVERFLOW(a, b, min, max)                           \
+   ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max)             \
+    : (a) < 0 ? 1                                                        \
+    : (b) < 0 ? (a) - (b) <= (a)                                         \
+    : (a) < (b))
+# define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
+   (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
+    || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
+#endif
+#define _GL_DIVIDE_OVERFLOW(a, b, min, max)                             \
+  ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max)  \
+   : (a) < 0 ? (b) <= (a) + (b) - 1                                     \
+   : (b) < 0 && (a) + (b) <= (a))
+#define _GL_REMAINDER_OVERFLOW(a, b, min, max)                          \
+  ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max)  \
+   : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b)                     \
+   : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max))
+
+/* Return a nonzero value if A is a mathematical multiple of B, where
+   A is unsigned, B is negative, and MAX is the maximum value of A's
+   type.  A's type must be the same as (A % B)'s type.  Normally (A %
+   -B == 0) suffices, but things get tricky if -B would overflow.  */
+#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max)                            \
+  (((b) < -_GL_SIGNED_INT_MAXIMUM (b)                                   \
+    ? (_GL_SIGNED_INT_MAXIMUM (b) == (max)                              \
+       ? (a)                                                            \
+       : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1))   \
+    : (a) % - (b))                                                      \
+   == 0)
+
+/* Check for integer overflow, and report low order bits of answer.
+
+   The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
+   might not yield numerically correct answers due to arithmetic overflow.
+   The INT_<op>_WRAPV macros also store the low-order bits of the answer.
+   These macros work correctly on all known practical hosts, and do not rely
+   on undefined behavior due to signed arithmetic overflow.
+
+   Example usage, assuming A and B are long int:
+
+     if (INT_MULTIPLY_OVERFLOW (a, b))
+       printf ("result would overflow\n");
+     else
+       printf ("result is %ld (no overflow)\n", a * b);
+
+   Example usage with WRAPV flavor:
+
+     long int result;
+     bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
+     printf ("result is %ld (%s)\n", result,
+             overflow ? "after overflow" : "no overflow");
+
+   Restrictions on these macros:
+
+   These macros do not check for all possible numerical problems or
+   undefined or unspecified behavior: they do not check for division
+   by zero, for bad shift counts, or for shifting negative numbers.
+
+   These macros may evaluate their arguments zero or multiple times, so the
+   arguments should not have side effects.
+
+   The WRAPV macros are not constant expressions.  They support only
+   +, binary -, and *.  The result type must be signed.
+
+   These macros are tuned for their last argument being a constant.
+
+   Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
+   A % B, and A << B would overflow, respectively.  */
+
+#define INT_ADD_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
+#define INT_SUBTRACT_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
+#if _GL_HAS_BUILTIN_OVERFLOW_P
+# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a)
+#else
+# define INT_NEGATE_OVERFLOW(a) \
+   INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+#endif
+#define INT_MULTIPLY_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
+#define INT_DIVIDE_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
+#define INT_REMAINDER_OVERFLOW(a, b) \
+  _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW)
+#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
+  INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
+                                 _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
+
+/* Return 1 if the expression A <op> B would overflow,
+   where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
+   assuming MIN and MAX are the minimum and maximum for the result type.
+   Arguments should be free of side effects.  */
+#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
+  op_result_overflow (a, b,                                     \
+                      _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \
+                      _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b)))
+
+/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
+   Return 1 if the result overflows.  See above for restrictions.  */
+#define INT_ADD_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW)
+#define INT_SUBTRACT_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
+#define INT_MULTIPLY_WRAPV(a, b, r) \
+  _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
+
+/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390.  See:
+   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
+   https://llvm.org/bugs/show_bug.cgi?id=25390
+   For now, assume all versions of GCC-like compilers generate bogus
+   warnings for _Generic.  This matters only for older compilers that
+   lack __builtin_add_overflow.  */
+#if __GNUC__
+# define _GL__GENERIC_BOGUS 1
+#else
+# define _GL__GENERIC_BOGUS 0
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+   the operation.  BUILTIN is the builtin operation, and OVERFLOW the
+   overflow predicate.  Return 1 if the result overflows.  See above
+   for restrictions.  */
+#if _GL_HAS_BUILTIN_OVERFLOW
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r)
+#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+   (_Generic \
+    (*(r), \
+     signed char: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        signed char, SCHAR_MIN, SCHAR_MAX), \
+     short int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        short int, SHRT_MIN, SHRT_MAX), \
+     int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                        int, INT_MIN, INT_MAX), \
+     long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        long int, LONG_MIN, LONG_MAX), \
+     long long int: \
+       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                        long long int, LLONG_MIN, LLONG_MAX)))
+#else
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+   (sizeof *(r) == sizeof (signed char) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       signed char, SCHAR_MIN, SCHAR_MAX) \
+    : sizeof *(r) == sizeof (short int) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       short int, SHRT_MIN, SHRT_MAX) \
+    : sizeof *(r) == sizeof (int) \
+    ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+                       int, INT_MIN, INT_MAX) \
+    : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
+# ifdef LLONG_MAX
+#  define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+    (sizeof *(r) == sizeof (long int) \
+     ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                        long int, LONG_MIN, LONG_MAX) \
+     : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+                        long long int, LLONG_MIN, LLONG_MAX))
+# else
+#  define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+    _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+                     long int, LONG_MIN, LONG_MAX)
+# endif
+#endif
+
+/* Store the low-order bits of A <op> B into *R, where the operation
+   is given by OP.  Use the unsigned type UT for calculation to avoid
+   overflow problems.  *R's type is T, with extrema TMIN and TMAX.
+   T must be a signed integer type.  Return 1 if the result overflows.  */
+#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
+  (sizeof ((a) op (b)) < sizeof (t) \
+   ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \
+   : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax))
+#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \
+  ((overflow (a, b) \
+    || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
+    || (tmax) < ((a) op (b))) \
+   ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
+   : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
+
+/* Return the low-order bits of A <op> B, where the operation is given
+   by OP.  Use the unsigned type UT for calculation to avoid undefined
+   behavior on signed integer overflow, and convert the result to type T.
+   UT is at least as wide as T and is no narrower than unsigned int,
+   T is two's complement, and there is no padding or trap representations.
+   Assume that converting UT to T yields the low-order bits, as is
+   done in all known two's-complement C compilers.  E.g., see:
+   https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
+
+   According to the C standard, converting UT to T yields an
+   implementation-defined result or signal for values outside T's
+   range.  However, code that works around this theoretical problem
+   runs afoul of a compiler bug in Oracle Studio 12.3 x86.  See:
+   https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html
+   As the compiler bug is real, don't try to work around the
+   theoretical problem.  */
+
+#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
+  ((t) ((ut) (a) op (ut) (b)))
+
+#endif /* _GL_INTPROPS_H */
diff --git a/include/verify.h b/include/verify.h
new file mode 100644
index 0000000..00e78d3
--- /dev/null
+++ b/include/verify.h
@@ -0,0 +1,2 @@
+/* Gnulib <verify.h>, simplified by assuming GCC 4.6 or later.  */
+#define verify(R) _Static_assert (R, "verify (" #R ")")
diff --git a/time/mktime-internal.h b/time/mktime-internal.h
new file mode 100644
index 0000000..ba1d9c7
--- /dev/null
+++ b/time/mktime-internal.h
@@ -0,0 +1 @@
+typedef time_t mktime_offset_t;
diff --git a/time/mktime.c b/time/mktime.c
index 5f038a2..4ff7490 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -15,13 +15,30 @@
 
    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/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
-/* Define this to have a standalone program to test this implementation of
+/* Define this to 1 to have a standalone program to test this implementation of
    mktime.  */
-/* #define DEBUG_MKTIME 1 */
+#ifndef DEBUG_MKTIME
+# define DEBUG_MKTIME 0
+#endif
 
-#ifndef _LIBC
+/* The following macros influence what gets defined when this file is compiled:
+
+   Macro/expression            Which gnulib module    This compilation unit
+                                                      should define
+
+   _LIBC                       (glibc proper)         mktime
+
+   NEED_MKTIME_WORKING         mktime                 rpl_mktime
+   || NEED_MKTIME_WINDOWS
+
+   NEED_MKTIME_INTERNAL        mktime-internal        mktime_internal
+
+   DEBUG_MKTIME                (defined manually)     my_mktime, main
+ */
+
+#if !defined _LIBC && !DEBUG_MKTIME
 # include <config.h>
 #endif
 
@@ -35,114 +52,128 @@
 #include <time.h>
 
 #include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
 
-#include <string.h>		/* For the real memcpy prototype.  */
+#include <intprops.h>
+#include <verify.h>
 
-#if defined DEBUG_MKTIME && DEBUG_MKTIME
+#if DEBUG_MKTIME
 # include <stdio.h>
-# include <stdlib.h>
 /* Make it work even if the system's libc has its own mktime routine.  */
 # undef mktime
 # define mktime my_mktime
 #endif /* DEBUG_MKTIME */
 
-/* Some of the code in this file assumes that signed integer overflow
-   silently wraps around.  This assumption can't easily be programmed
-   around, nor can it be checked for portably at compile-time or
-   easily eliminated at run-time.
-
-   Define WRAPV to 1 if the assumption is valid and if
-     #pragma GCC optimize ("wrapv")
-   does not trigger GCC bug 51793
-   <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51793>.
-   Otherwise, define it to 0; this forces the use of slower code that,
-   while not guaranteed by the C Standard, works on all production
-   platforms that we know about.  */
-#ifndef WRAPV
-# if (((__GNUC__ == 4 && 4 <= __GNUC_MINOR__) || 4 < __GNUC__) \
-      && defined __GLIBC__)
-#  pragma GCC optimize ("wrapv")
-#  define WRAPV 1
-# else
-#  define WRAPV 0
+#ifndef NEED_MKTIME_INTERNAL
+# define NEED_MKTIME_INTERNAL 0
+#endif
+#ifndef NEED_MKTIME_WINDOWS
+# define NEED_MKTIME_WINDOWS 0
+#endif
+#ifndef NEED_MKTIME_WORKING
+# define NEED_MKTIME_WORKING DEBUG_MKTIME
+#endif
+
+#include "mktime-internal.h"
+
+#ifndef _LIBC
+static void
+my_tzset (void)
+{
+# if NEED_MKTIME_WINDOWS
+  /* Rectify the value of the environment variable TZ.
+     There are four possible kinds of such values:
+       - Traditional US time zone names, e.g. "PST8PDT".  Syntax: see
+         <https://msdn.microsoft.com/en-us/library/90s5c885.aspx>
+       - Time zone names based on geography, that contain one or more
+         slashes, e.g. "Europe/Moscow".
+       - Time zone names based on geography, without slashes, e.g.
+         "Singapore".
+       - Time zone names that contain explicit DST rules.  Syntax: see
+         <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
+     The Microsoft CRT understands only the first kind.  It produces incorrect
+     results if the value of TZ is of the other kinds.
+     But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
+     of the second kind for most geographies, or of the first kind in a few
+     other geographies.  If it is of the second kind, neutralize it.  For the
+     Microsoft CRT, an absent or empty TZ means the time zone that the user
+     has set in the Windows Control Panel.
+     If the value of TZ is of the third or fourth kind -- Cygwin programs
+     understand these syntaxes as well --, it does not matter whether we
+     neutralize it or not, since these values occur only when a Cygwin user
+     has set TZ explicitly; this case is 1. rare and 2. under the user's
+     responsibility.  */
+  const char *tz = getenv ("TZ");
+  if (tz != NULL && strchr (tz, '/') != NULL)
+    _putenv ("TZ=");
+# elif HAVE_TZSET
+  tzset ();
 # endif
+}
+# undef __tzset
+# define __tzset() my_tzset ()
 #endif
 
-/* Verify a requirement at compile-time (unlike assert, which is runtime).  */
-#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
+
+/* A signed type that can represent an integer number of years
+   multiplied by three times the number of seconds in a year.  It is
+   needed when converting a tm_year value times the number of seconds
+   in a year.  The factor of three comes because these products need
+   to be subtracted from each other, and sometimes with an offset
+   added to them, without worrying about overflow.
+
+   Much of the code uses long_int to represent time_t values, to
+   lessen the hassle of dealing with platforms where time_t is
+   unsigned, and because long_int should suffice to represent all
+   time_t values that mktime can generate even on platforms where
+   time_t is excessively wide.  */
 
-/* A signed type that is at least one bit wider than int.  */
-#if INT_MAX <= LONG_MAX / 2
+#if INT_MAX <= LONG_MAX / 3 / 366 / 24 / 60 / 60
 typedef long int long_int;
 #else
 typedef long long int long_int;
 #endif
-verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2);
+verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 3 / 366 / 24 / 60 / 60);
 
 /* Shift A right by B bits portably, by dividing A by 2**B and
-   truncating towards minus infinity.  A and B should be free of side
-   effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
-   INT_BITS is the number of useful bits in an int.  GNU code can
-   assume that INT_BITS is at least 32.
+   truncating towards minus infinity.  B should be in the range 0 <= B
+   <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful
+   bits in a long_int.  LONG_INT_BITS is at least 32.
 
    ISO C99 says that A >> B is implementation-defined if A < 0.  Some
    implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
    right in the usual way when A < 0, so SHR falls back on division if
    ordinary A >> B doesn't seem to be the usual signed shift.  */
-#define SHR(a, b)                                               \
-  ((-1 >> 1 == -1                                               \
-    && (long_int) -1 >> 1 == -1                                 \
-    && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t)))      \
-   ? (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)
-#endif
-#ifndef TIME_T_MAX
-# define TIME_T_MAX TYPE_MAXIMUM (time_t)
-#endif
-#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_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)));
+static long_int
+shr (long_int a, int b)
+{
+  long_int one = 1;
+  return (-one >> 1 == -1
+	  ? a >> b
+	  : a / (one << b) - (a % (one << b) < 0));
+}
+
+/* Bounds for the intersection of time_t and long_int.  */
+
+static long_int const mktime_min
+  = ((TYPE_SIGNED (time_t) && TYPE_MINIMUM (time_t) < TYPE_MINIMUM (long_int))
+     ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (time_t));
+static long_int const mktime_max
+  = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (time_t)
+     ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (time_t));
+
+verify (TYPE_IS_INTEGER (time_t));
 
 #define EPOCH_YEAR 1970
 #define TM_YEAR_BASE 1900
-verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
+verify (TM_YEAR_BASE % 100 == 0);
 
-/* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
-static int
+/* Is YEAR + TM_YEAR_BASE a leap year?  */
+static bool
 leapyear (long_int year)
 {
   /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
@@ -166,20 +197,9 @@ const unsigned short int __mon_yday[2][13] =
   };
 
 
-#ifndef _LIBC
-/* Portable standalone applications should supply a <time.h> that
-   declares a POSIX-compliant localtime_r, for the benefit of older
-   implementations that lack localtime_r or have a nonstandard one.
-   See the gnulib time_r module for one way to implement this.  */
-# undef __localtime_r
-# define __localtime_r localtime_r
-# define __mktime_internal mktime_internal
-# include "mktime-internal.h"
-#endif
-
-/* Return 1 if the values A and B differ according to the rules for
-   tm_isdst: A and B differ if one is zero and the other positive.  */
-static int
+/* Do the values A and B differ according to the rules for tm_isdst?
+   A and B differ if one is zero and the other positive.  */
+static bool
 isdst_differ (int a, int b)
 {
   return (!a != !b) && (0 <= a) && (0 <= b);
@@ -187,107 +207,68 @@ isdst_differ (int a, int b)
 
 /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
    (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
-   were not adjusted between the time stamps.
+   were not adjusted between the timestamps.
 
    The YEAR values uses the same numbering as TP->tm_year.  Values
-   need not be in the usual range.  However, YEAR1 must not be less
-   than 2 * INT_MIN or greater than 2 * INT_MAX.
-
-   The result may overflow.  It is the caller's responsibility to
-   detect overflow.  */
+   need not be in the usual range.  However, YEAR1 must not overflow
+   when multiplied by three times the number of seconds in a year, and
+   likewise for YDAY1 and three times the number of seconds in a day.  */
 
-static time_t
+static long_int
 ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
 	    int year0, int yday0, int hour0, int min0, int sec0)
 {
-  verify (C99_integer_division, -1 / 2 == 0);
+  verify (-1 / 2 == 0);
 
   /* Compute intervening leap days correctly even if year is negative.
      Take care to avoid integer overflow here.  */
-  int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
-  int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
+  int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
+  int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
   int a100 = a4 / 25 - (a4 % 25 < 0);
   int b100 = b4 / 25 - (b4 % 25 < 0);
-  int a400 = SHR (a100, 2);
-  int b400 = SHR (b100, 2);
+  int a400 = shr (a100, 2);
+  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
-     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;
+  /* Compute the desired time without overflowing.  */
+  long_int years = year1 - year0;
+  long_int days = 365 * years + yday1 - yday0 + intervening_leap_days;
+  long_int hours = 24 * days + hour1 - hour0;
+  long_int minutes = 60 * hours + min1 - min0;
+  long_int 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)
+/* Return the average of A and B, even if A + B would overflow.
+   Round toward positive infinity.  */
+static long_int
+long_int_avg (long_int a, long_int 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.  */
-static int
-time_t_add_ok (time_t a, time_t b)
-{
-  if (! TYPE_SIGNED (time_t))
-    {
-      time_t sum = a + b;
-      return (sum < a) == (TIME_T_MIDPOINT <= b);
-    }
-  else if (WRAPV)
-    {
-      time_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;
-    }
-}
-
-/* Return 1 if A + B does not overflow.  */
-static int
-time_t_int_add_ok (time_t a, int b)
-{
-  verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX);
-  if (WRAPV)
-    {
-      time_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;
-    }
+  return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
 }
 
 /* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
-   assuming that *T corresponds to *TP and that no clock adjustments
+   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
+   Although T and the returned value are of type long_int,
+   they represent time_t values and must be in time_t range.
+   If TP is null, return a value not equal to T; this avoids false matches.
+   YEAR and YDAY must not be so large that multiplying them by three times the
+   number of seconds in a year (or day, respectively) would overflow long_int.
+   If the returned value would be out of range, yield the minimal or
+   maximal in-range value, except do not yield a value equal to T.  */
+static long_int
 guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
-	       const time_t *t, const struct tm *tp)
+	       long_int 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);
-      if (time_t_add_ok (*t, d))
-	return *t + d;
+      long_int result;
+      long_int d = ydhms_diff (year, yday, hour, min, sec,
+			       tp->tm_year, tp->tm_yday,
+			       tp->tm_hour, tp->tm_min, tp->tm_sec);
+      if (! INT_ADD_WRAPV (t, d, &result))
+	return result;
     }
 
   /* Overflow occurred one way or another.  Return the nearest result
@@ -295,32 +276,51 @@ guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
      if the actual difference is nonzero, as that would cause a false
      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));
+  return (t < long_int_avg (mktime_min, mktime_max)
+	  ? (t <= mktime_min + 1 ? t + 1 : mktime_min)
+	  : (mktime_max - 1 <= t ? t - 1 : mktime_max));
+}
+
+/* Use CONVERT to convert T to a struct tm value in *TM.  T must be in
+   range for time_t.  Return TM if successful, NULL if T is out of
+   range for CONVERT.  */
+static struct tm *
+convert_time (struct tm *(*convert) (const time_t *, struct tm *),
+	      long_int t, struct tm *tm)
+{
+  time_t x = t;
+  return convert (&x, tm);
 }
 
 /* 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.  */
+   it is the nearest in-range value and then convert that.
+   A value is in range if it fits in both time_t and long_int.  */
 static struct tm *
 ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
-		time_t *t, struct tm *tp)
+		long_int *t, struct tm *tp)
 {
-  struct tm *r = convert (t, tp);
+  struct tm *r;
+  if (*t < mktime_min)
+    *t = mktime_min;
+  else if (mktime_max < *t)
+    *t = mktime_max;
+  r = convert_time (convert, *t, tp);
 
   if (!r && *t)
     {
-      time_t bad = *t;
-      time_t ok = 0;
+      long_int bad = *t;
+      long_int ok = 0;
 
-      /* BAD is a known unconvertible time_t, and OK is a known good one.
+      /* BAD is a known unconvertible value, 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))
+      while (true)
 	{
-	  time_t mid = *t = time_t_avg (ok, bad);
-	  r = convert (t, tp);
+	  long_int mid = long_int_avg (ok, bad);
+	  if (mid != ok && mid != bad)
+	    break;
+	  r = convert_time (convert, mid, tp);
 	  if (r)
 	    ok = mid;
 	  else
@@ -331,8 +331,7 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
 	{
 	  /* The last conversion attempt failed;
 	     revert to the most recent successful attempt.  */
-	  *t = ok;
-	  r = convert (t, tp);
+	  r = convert_time (convert, ok, tp);
 	}
     }
 
@@ -349,9 +348,9 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
 time_t
 __mktime_internal (struct tm *tp,
 		   struct tm *(*convert) (const time_t *, struct tm *),
-		   time_t *offset)
+		   mktime_offset_t *offset)
 {
-  time_t t, gt, t0, t1, t2;
+  long_int t, gt, t0, t1, t2, dt;
   struct tm tm;
 
   /* The maximum number of probes (calls to CONVERT) should be enough
@@ -381,9 +380,7 @@ __mktime_internal (struct tm *tp,
   long_int year = lyear_requested + mon_years;
 
   /* The other values need not be in range:
-     the remaining code handles minor overflows correctly,
-     assuming int and time_t arithmetic wraps around.
-     Major overflows are caught at the end.  */
+     the remaining code handles overflows correctly.  */
 
   /* Calculate day of year from year, month, and day of month.
      The result need not be in range.  */
@@ -393,7 +390,8 @@ __mktime_internal (struct tm *tp,
   long_int lmday = mday;
   long_int yday = mon_yday + lmday;
 
-  time_t guessed_offset = *offset;
+  mktime_offset_t off = *offset;
+  int negative_offset_guess;
 
   int sec_requested = sec;
 
@@ -410,71 +408,14 @@ __mktime_internal (struct tm *tp,
   /* Invert CONVERT by probing.  First assume the same offset as last
      time.  */
 
+  INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess);
   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)
-    {
-      /* 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
-	 that is bounded by a small value.  */
-
-      /* Approximate log base 2 of the number of time units per
-	 biennium.  A biennium is 2 years; use this unit instead of
-	 years to avoid integer overflow.  For example, 2 average
-	 Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
-	 which is 63113904 seconds, and rint (log2 (63113904)) is
-	 26.  */
-      int ALOG2_SECONDS_PER_BIENNIUM = 26;
-      int ALOG2_MINUTES_PER_BIENNIUM = 20;
-      int ALOG2_HOURS_PER_BIENNIUM = 14;
-      int ALOG2_DAYS_PER_BIENNIUM = 10;
-      int LOG2_YEARS_PER_BIENNIUM = 1;
-
-      int approx_requested_biennia =
-	(SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
-	 - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
-	 + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
-	 + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
-	 + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
-	 + (LEAP_SECONDS_POSSIBLE
-	    ? 0
-	    : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
-
-      int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
-      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
-	 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 =
-	(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;
-	  approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
-	  diff = approx_biennia - approx_requested_biennia;
-	  approx_abs_diff = diff < 0 ? -1 - diff : diff;
-	  if (overflow_threshold < approx_abs_diff)
-	    return -1;
-	  guessed_offset += repaired_t0 - t0;
-	  t0 = repaired_t0;
-	}
-    }
+		   EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, negative_offset_guess);
 
   /* Repeatedly use the error to improve the guess.  */
 
   for (t = t1 = t2 = t0, dst2 = 0;
-       (gt = guess_time_tm (year, yday, hour, min, sec, &t,
+       (gt = guess_time_tm (year, yday, hour, min, sec, t,
 			    ranged_convert (convert, &t, &tm)),
 	t != gt);
        t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
@@ -531,65 +472,70 @@ __mktime_internal (struct tm *tp,
 
       for (delta = stride; delta < delta_bound; delta += stride)
 	for (direction = -1; direction <= 1; direction += 2)
-	  if (time_t_int_add_ok (t, delta * direction))
-	    {
-	      time_t ot = t + delta * direction;
-	      struct tm otm;
-	      ranged_convert (convert, &ot, &otm);
-	      if (! isdst_differ (isdst, otm.tm_isdst))
-		{
-		  /* We found the desired tm_isdst.
-		     Extrapolate back to the desired time.  */
-		  t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
-		  ranged_convert (convert, &t, &tm);
-		  goto offset_found;
-		}
-	    }
+	  {
+	    long_int ot;
+	    if (! INT_ADD_WRAPV (t, delta * direction, &ot))
+	      {
+		struct tm otm;
+		ranged_convert (convert, &ot, &otm);
+		if (! isdst_differ (isdst, otm.tm_isdst))
+		  {
+		    /* We found the desired tm_isdst.
+		       Extrapolate back to the desired time.  */
+		    t = guess_time_tm (year, yday, hour, min, sec, ot, &otm);
+		    ranged_convert (convert, &t, &tm);
+		    goto offset_found;
+		  }
+	      }
+	  }
     }
 
  offset_found:
-  *offset = guessed_offset + t - t0;
+  /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS.
+     This is just a heuristic to speed up the next mktime call, and
+     correctness is unaffected if integer overflow occurs here.  */
+  INT_SUBTRACT_WRAPV (t, t0, &dt);
+  INT_SUBTRACT_WRAPV (dt, negative_offset_guess, offset);
 
   if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
     {
       /* Adjust time to reflect the tm_sec requested, not the normalized value.
 	 Also, repair any damage from a false match due to a leap second.  */
-      int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
-      if (! time_t_int_add_ok (t, sec_requested))
-	return -1;
-      t1 = t + sec_requested;
-      if (! time_t_int_add_ok (t1, sec_adjustment))
-	return -1;
-      t2 = t1 + sec_adjustment;
-      if (! convert (&t2, &tm))
+      long_int sec_adjustment = sec == 0 && tm.tm_sec == 60;
+      sec_adjustment -= sec;
+      sec_adjustment += sec_requested;
+      if (INT_ADD_WRAPV (t, sec_adjustment, &t)
+	  || ! (mktime_min <= t && t <= mktime_max)
+	  || ! convert_time (convert, t, &tm))
 	return -1;
-      t = t2;
     }
 
   *tp = tm;
   return t;
 }
 
+#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */
 
-/* FIXME: This should use a signed type wide enough to hold any UTC
-   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;
+#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
 
 /* Convert *TP to a time_t value.  */
 time_t
 mktime (struct tm *tp)
 {
-#ifdef _LIBC
   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
      time zone names contained in the external variable 'tzname' shall
      be set as if the tzset() function had been called.  */
   __tzset ();
-#endif
 
+# if defined __LIBC || NEED_MKTIME_WORKING
+  static mktime_offset_t localtime_offset;
   return __mktime_internal (tp, __localtime_r, &localtime_offset);
+# else
+#  undef mktime
+  return mktime (tp);
+# endif
 }
+#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
 
 #ifdef weak_alias
 weak_alias (mktime, timelocal)
@@ -600,7 +546,7 @@ libc_hidden_def (mktime)
 libc_hidden_weak (timelocal)
 #endif
 
-#if defined DEBUG_MKTIME && DEBUG_MKTIME
+#if DEBUG_MKTIME
 
 static int
 not_equal_tm (const struct tm *a, const struct tm *b)
@@ -652,6 +598,14 @@ main (int argc, char **argv)
   time_t tk, tl, tl1;
   char trailer;
 
+  /* Sanity check, plus call tzset.  */
+  tl = 0;
+  if (! localtime (&tl))
+    {
+      printf ("localtime (0) fails\n");
+      status = 1;
+    }
+
   if ((argc == 3 || argc == 4)
       && (sscanf (argv[1], "%d-%d-%d%c",
 		  &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
@@ -665,12 +619,7 @@ main (int argc, char **argv)
       tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
       tmk = tm;
       tl = mktime (&tmk);
-      lt = localtime (&tl);
-      if (lt)
-	{
-	  tml = *lt;
-	  lt = &tml;
-	}
+      lt = localtime_r (&tl, &tml);
       printf ("mktime returns %ld == ", (long int) tl);
       print_tm (&tmk);
       printf ("\n");
@@ -685,16 +634,16 @@ main (int argc, char **argv)
       if (argc == 4)
 	for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
 	  {
-	    lt = localtime (&tl);
+	    lt = localtime_r (&tl, &tml);
 	    if (lt)
 	      {
-		tmk = tml = *lt;
+		tmk = tml;
 		tk = mktime (&tmk);
 		status |= check_result (tk, tmk, tl, &tml);
 	      }
 	    else
 	      {
-		printf ("localtime (%ld) yields 0\n", (long int) tl);
+		printf ("localtime_r (%ld) yields 0\n", (long int) tl);
 		status = 1;
 	      }
 	    tl1 = tl + by;
@@ -705,16 +654,16 @@ main (int argc, char **argv)
 	for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
 	  {
 	    /* Null benchmark.  */
-	    lt = localtime (&tl);
+	    lt = localtime_r (&tl, &tml);
 	    if (lt)
 	      {
-		tmk = tml = *lt;
+		tmk = tml;
 		tk = tl;
 		status |= check_result (tk, tmk, tl, &tml);
 	      }
 	    else
 	      {
-		printf ("localtime (%ld) yields 0\n", (long int) tl);
+		printf ("localtime_r (%ld) yields 0\n", (long int) tl);
 		status = 1;
 	      }
 	    tl1 = tl + by;
diff --git a/time/timegm.c b/time/timegm.c
index fb720e2..229fff2 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -17,31 +17,18 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#ifdef HAVE_CONFIG_H
+#ifndef _LIBC
 # include <config.h>
 #endif
 
-#ifdef _LIBC
-# include <time.h>
-#else
-# include "timegm.h"
-
-/* Portable standalone applications should supply a "time_r.h" that
-   declares a POSIX-compliant gmtime_r, for the benefit of older
-   implementations that lack gmtime_r or have a nonstandard one.
-   See the gnulib time_r module for one way to implement this.  */
-# 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 *);
-#endif
+#include <time.h>
+
+#include "mktime-internal.h"
 
 time_t
 timegm (struct tm *tmp)
 {
-  static time_t gmtime_offset;
+  static mktime_offset_t gmtime_offset;
   tmp->tm_isdst = 0;
   return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
 }

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


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]