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-2.25 created. glibc-2.25-57-g1830c22


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-2.25 has been created
        at  1830c222ea62a5344ffa1740050b597e530c654a (commit)

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

commit 1830c222ea62a5344ffa1740050b597e530c654a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Aug 2 12:56:01 2017 +0200

    Y2038: add Y2038-ready getrusage

diff --git a/resource/Makefile b/resource/Makefile
index 8235770..9606ccb 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
 
 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..84f3a79 100644
--- a/resource/Versions
+++ b/resource/Versions
@@ -25,4 +25,11 @@ libc {
   GLIBC_PRIVATE {
     __getrlimit;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __getrusage_t64;
+  }
 }
diff --git a/resource/getrusage64.c b/resource/getrusage64.c
new file mode 100644
index 0000000..0e76f15
--- /dev/null
+++ b/resource/getrusage64.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 1996-2017 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>
+
+/* 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 __rusage_t64
+  {
+    /* 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 __rusage_t64 *__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;
+}
diff --git a/resource/sys/resource.h b/resource/sys/resource.h
index 423ac62..642fe79 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 double __REDIRECT (getrusage, (__rusage_who_t __who, 
+                                      struct rusage *__usage),
+     __getrusage_t64) __THROW;
+# else
+# define getrusage __getrusage_t64
+# 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

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

commit e2a6c2109e8aeeae596735c9e52a2edb225cf2da
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Aug 2 10:36:45 2017 +0200

    Y2038: implement Y2038-ready futex-based APIs
    
    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 0ae5def..9ed0872 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -272,4 +272,15 @@ libpthread {
     __pthread_barrier_init; __pthread_barrier_wait;
     __shm_directory;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __pthread_rwlock_rdlock_t64;
+    __pthread_rwlock_wrlock_t64;
+    __pthread_mutex_timedlock_t64;
+    __sem_timedwait_t64;
+    __pthread_cond_timedwait_t64;
+  }
 }
diff --git a/nptl/lll_timedlock_wait.c b/nptl/lll_timedlock_wait.c
index 604953c..d757d9d 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_wait_t64 (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 7812b94..4246e25 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_common_t64 (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_cancelable_t64
+			(cond->__data.__g_signals + g, 0, &rt64, private);
+		}
+	      else
+		{
+		  /* Use CLOCK_REALTIME.  */
+		  err = futex_abstimed_wait_cancelable_t64
+		      (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_timedwait_t64 (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_common_t64 (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 a4beb7b..11800fa 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -32,6 +32,10 @@
 #define lll_timedlock_elision(a,dummy,b,c) lll_timedlock(a, b, c)
 #endif
 
+#ifndef lll_timedlock_elision_t64
+#define lll_timedlock_elision_t64(a,dummy,b,c) lll_timedlock_t64(a, b, c)
+#endif
+
 #ifndef lll_trylock_elision
 #define lll_trylock_elision(a,t) lll_trylock(a)
 #endif
@@ -634,3 +638,612 @@ pthread_mutex_timedlock (pthread_mutex_t *mutex,
  out:
   return result;
 }
+
+/* 64-bit time version */
+
+int
+pthread_mutex_timedlock_t64 (pthread_mutex_t *mutex,
+			 const struct __timespec64 *abstime)
+{
+  int oldval;
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+  int result = 0;
+
+  LIBC_PROBE (mutex_timedlock_entry, 2, mutex, abstime);
+
+  /* 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_timedlock_t64 (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_timedlock_t64 (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_elision_t64 (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_timedlock_t64 (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)
+			      && (atomic_compare_and_exchange_bool_acq
+				  (&mutex->__data.__lock,
+				   id | assume_other_futex_waiters, 0) == 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_bitset_t64 (&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_not_cancel (&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;
+}
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index 256508c..c2d33a4 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -508,6 +508,240 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   return 0;
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+__pthread_rwlock_rdlock_full_t64 (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_wait_t64 (&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_wait_t64 (&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)
@@ -922,3 +1156,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_full_t64 (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_wait_t64 (&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_wait_t64 (&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 9f084f8..174ddf1 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_timedrdlock_t64 (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_full_t64 (rwlock, abstime);
+}
diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
index 5626505..7b954d4 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_timedwrlock_t64 (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_full_t64 (rwlock, abstime);
+}
diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
index 22b0778..893954a 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_timedwait_t64 (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_slow_t64 ((struct new_sem *) sem, abstime);
+}
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index 625bf08..b9f37f4 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_wait_t64 (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_slow_t64 ((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 a3412a0..d5bfe04 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_wait_t64 (struct new_sem *sem, const struct __timespec64 *abstime)
+{
+  int err;
+
+#if __HAVE_64B_ATOMICS
+  err = futex_abstimed_wait_cancelable_t64 (
+      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
+      sem->private);
+#else
+  err = futex_abstimed_wait_cancelable_t64 (&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_slow_t64 (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_wait_t64 (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_wait_t64 (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 4f6f54d..c880a41 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -45,5 +45,6 @@ librt {
     __timer_gettime64; __timer_settime64;
     __timerfd_gettime64; __timerfd_settime64;
     __mq_timedreceive_t64; __mq_timedsend_t64;
+    __aio_suspend_t64;
   }
 }
diff --git a/sysdeps/nptl/aio_misc.h b/sysdeps/nptl/aio_misc.h
index 47b1a36..3c74f84 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_wait_t64 ((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 42d9658..1a6b812 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_wait_t64 (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_timedlock_t64(futex, abstime, private)                \
+  ({                                                                \
+    int *__futex = (futex);                                         \
+    int __val = 0;                                                  \
+                                                                    \
+    if (__glibc_unlikely                                            \
+        (atomic_compare_and_exchange_bool_acq (__futex, 1, 0)))     \
+      __val = __lll_timedlock_wait_t64 (__futex, abstime, private); \
+    __val;                                                          \
+  })
+#define lll_timedlock_t64(futex, abstime, private)  \
+  __lll_timedlock_t64 (&(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/nptl/pthread.h b/sysdeps/nptl/pthread.h
index 632ea7b..4289d99 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -765,6 +765,16 @@ 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 struct tm * __REDIRECT (pthread_mutex_timedlock,
+                               (pthread_mutex_t *__restrict __mutex,
+                                const struct timespec *__restrict __abstime),
+       __pthread_mutex_timedlock_t64) __THROWNL __nonnull ((1, 2));
+# else
+# define pthread_mutex_timedlock __pthread_mutex_timedlock_t64
+# endif
+#endif
 extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
 				    const struct timespec *__restrict
 				    __abstime) __THROWNL __nonnull ((1, 2));
@@ -904,6 +914,16 @@ 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 struct tm * __REDIRECT (pthread_rwlock_timedrdlock,
+                               (pthread_rwlock_t *__restrict __rwlock,
+                                struct timespec *__restrict __abstime),
+       __pthread_rwlock_timedrdlock_t64) __THROWNL __nonnull ((1, 2));
+# else
+# define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_t64
+# endif
+#endif
 extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
 				       const struct timespec *__restrict
 				       __abstime) __THROWNL __nonnull ((1, 2));
@@ -919,6 +939,16 @@ 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 struct tm * __REDIRECT (pthread_rwlock_timedwrlock,
+                               (pthread_rwlock_t *__restrict __rwlock,
+                                struct timespec *__restrict __abstime),
+       __pthread_rwlock_timedwrlock_t64) __THROWNL __nonnull ((1, 2));
+# else
+# define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_t64
+# endif
+#endif
 extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
 				       const struct timespec *__restrict
 				       __abstime) __THROWNL __nonnull ((1, 2));
@@ -998,6 +1028,17 @@ 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 struct tm * __REDIRECT (pthread_cond_timedwait,
+                               (pthread_cond_t *__restrict __cond,
+                                pthread_mutex_t *__restrict __mutex,
+                                const struct timespec *__restrict __abstime),
+       __pthread_cond_timedwait_t64) __nonnull ((1, 2, 3));
+# else
+# define pthread_cond_timedwait __pthread_cond_timedwait_t64
+# 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/aio_suspend.c b/sysdeps/pthread/aio_suspend.c
index c739285..8a38754 100644
--- a/sysdeps/pthread/aio_suspend.c
+++ b/sysdeps/pthread/aio_suspend.c
@@ -254,3 +254,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_wait_t64 (unsigned int *cntr, 
+		      const struct __timespec64 *timeout)
+{
+  int result = 0;
+
+  AIO_MISC_WAIT_T64 (result, *cntr, timeout, 1);
+
+  return result;
+}
+#endif
+
+int
+aio_suspend_t64 (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_wait_t64 (&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_timedwait_t64 (&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/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
index 0b095a8..f1dd8d2 100644
--- a/sysdeps/pthread/semaphore.h
+++ b/sysdeps/pthread/semaphore.h
@@ -57,6 +57,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_timedwait_t64);
+# else
+# define sem_timedwait __sem_timedwait_t64
+# endif
+#endif
 extern int sem_timedwait (sem_t *__restrict __sem,
 			  const struct timespec *__restrict __abstime);
 #endif
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
index 1386807..ceffa90 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_wait_t64 (unsigned int *futex_word, unsigned int expected,
+		         const struct __timespec64 *reltime, int private)
+{
+  int err = lll_futex_timed_wait_t64 (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_cancelable_t64 (unsigned int *futex_word,
+				    unsigned int expected,
+			            const struct __timespec64 *reltime,
+                                    int private)
+{
+  int oldtype;
+  oldtype = __pthread_enable_asynccancel ();
+  int err = lll_futex_timed_wait_t64 (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_wait_t64 (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_bitset_t64 (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_cancelable_t64 (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_bitset_t64 (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 bb4fbae..e1cad10 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -97,6 +97,16 @@
 		     __lll_private_flag (FUTEX_WAIT, private),  \
 		     val, timeout)
 
+#define lll_futex_timed_wait_t64(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), \
@@ -104,6 +114,18 @@
 		     val, timeout, NULL /* Unused.  */,                 \
 		     FUTEX_BITSET_MATCH_ANY)
 
+#define lll_futex_timed_wait_bitset_t64(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)

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

commit 36588886b4300679d8ca0eff51d8e51df6d66a52
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jul 31 21:23:44 2017 +0200

    Y2038: add Y2038-ready getitimer, setitimer

diff --git a/include/time.h b/include/time.h
index e7dc9ea..32e8b1e 100644
--- a/include/time.h
+++ b/include/time.h
@@ -55,6 +55,12 @@ struct __itimerspec64
   struct __timespec64 it_value;
 };
 
+struct __itimerval_t64
+{
+  struct __timeval64 it_interval;
+  struct __timeval64 it_value;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;
diff --git a/time/Makefile b/time/Makefile
index d50c3dd..5a36d12 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,8 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
 	    timespec_get                                 \
-	    settimeofday64 nanosleep64
+	    settimeofday64 nanosleep64                   \
+	    getitimer64 setitimer64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index 8f6f865..10b1cce 100644
--- a/time/Versions
+++ b/time/Versions
@@ -75,5 +75,6 @@ libc {
     __gettimeofday_t64; __settimeofday_t64;
     __nanosleep_t64;
     __adjtime_t64;
+    __getitimer_t64; __setitimer_t64;
   }
 }
diff --git a/time/getitimer64.c b/time/getitimer64.c
new file mode 100644
index 0000000..edc08a2
--- /dev/null
+++ b/time/getitimer64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1991-2017 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
+__getitimer_t64 (enum __itimer_which which,
+                 struct __itimerval_t64 *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;
+}
diff --git a/time/setitimer64.c b/time/setitimer64.c
new file mode 100644
index 0000000..86efa76
--- /dev/null
+++ b/time/setitimer64.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 1991-2017 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
+__setitimer_t64 (enum __itimer_which which,
+                 const struct __itimerval_t64 *new,
+                 struct __itimerval_t64 *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;
+}
diff --git a/time/sys/time.h b/time/sys/time.h
index d2e1ef1..614ff32 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -148,12 +148,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), __getitimer_t64)
+       __THROW;
+# else
+# define getitimer __getitimer_t64
+# 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), __setitimer_t64)
+       __THROW;
+# else
+# define setitimer __setitimer_t64
+# endif
+#endif
 extern int setitimer (__itimer_which_t __which,
 		      const struct itimerval *__restrict __new,
 		      struct itimerval *__restrict __old) __THROW;

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

commit 0d29df06b9ed4c21ea4598f45f57a3e9690786ce
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jul 26 13:10:25 2017 +0200

    Y2038: implement Y2038-ready utime

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/Versions b/io/Versions
index 03d621b..6fe7b02 100644
--- a/io/Versions
+++ b/io/Versions
@@ -134,5 +134,6 @@ libc {
     __fxstat64_t64;
     __lxstat64_t64;
     __fxstatat64_t64;
+    __utime_t64;
   }
 }
diff --git a/io/utime.c b/io/utime.c
index 242ccd1..7762038 100644
--- a/io/utime.c
+++ b/io/utime.c
@@ -37,3 +37,19 @@ utime (const char *file, const struct utimbuf *times)
 libc_hidden_def (utime)
 
 stub_warning (utime)
+
+/* 64-bit time version */
+
+int
+__utime_t64 (const char *file, const struct utimbuf *times)
+{
+  if (file == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utime_t64)
diff --git a/io/utime.h b/io/utime.h
index 44a4e9c..3222b12 100644
--- a/io/utime.h
+++ b/io/utime.h
@@ -32,15 +32,24 @@ __BEGIN_DECLS
 # 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),
+     __utime_t64) __THROW __nonnull ((1));
+# else
+# define utime __utime_t64
+# endif
+#endif
 extern int utime (const char *__file,
 		  const struct utimbuf *__file_times)
      __THROW __nonnull ((1));
diff --git a/sysdeps/posix/utime.c b/sysdeps/posix/utime.c
index c8fe60b..d9f4aae 100644
--- a/sysdeps/posix/utime.c
+++ b/sysdeps/posix/utime.c
@@ -45,3 +45,28 @@ utime (const char *file, const struct utimbuf *times)
   return __utimes (file, tvp);
 }
 libc_hidden_def (utime)
+
+/* 64-bit time version */
+
+extern int __utimes64 (const char *file,
+                       const struct __timeval64 tvp[2]);
+
+int
+__utime_t64 (const char *file, const struct __utimbuf64 *times)
+{
+  struct timeval timevals[2];
+  struct timeval *tvp;
+
+  if (times != NULL)
+    {
+      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;
+
+  return __utimes (file, tvp);
+}

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

commit 6f87a2f3c05b38d202ba42c5e4e59da8c8d21e9b
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jul 26 10:51:44 2017 +0200

    Y2038: implement Y2038-ready adjtime

diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index d98d770..28a75a2 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -90,3 +90,46 @@ ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv)
 #ifdef NO_LOCAL_ADJTIME
 weak_alias (__adjtime, adjtime)
 #endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int __adjtime_t64 (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;
+}
diff --git a/time/Versions b/time/Versions
index d7626cc..8f6f865 100644
--- a/time/Versions
+++ b/time/Versions
@@ -74,5 +74,6 @@ libc {
     __time_t64; __stime_t64;
     __gettimeofday_t64; __settimeofday_t64;
     __nanosleep_t64;
+    __adjtime_t64;
   }
 }
diff --git a/time/adjtime.c b/time/adjtime.c
index 180bf48..8c01bd0 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
+__adjtime_t64 (const struct __timeval64 *delta, struct __timeval64 *olddelta)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__adjtime_t64)
diff --git a/time/sys/time.h b/time/sys/time.h
index 3080740..d2e1ef1 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -98,6 +98,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),
+                    __adjtime_t64) __THROW;
+#  else
+#   define adjtime __adjtime_t64
+#  endif
+# endif
 extern int adjtime (const struct timeval *__delta,
 		    struct timeval *__olddelta) __THROW;
 #endif

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

commit f84c53b64ef544557e30dd20dbc162807bc09468
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Sat Jul 8 17:22:08 2017 +0200

    Y2038: implement Y2038-ready nanosleep64

diff --git a/time/Makefile b/time/Makefile
index 5fb26f6..d50c3dd 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
 	    timespec_get                                 \
-	    settimeofday64
+	    settimeofday64 nanosleep64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index a007efa..d7626cc 100644
--- a/time/Versions
+++ b/time/Versions
@@ -73,5 +73,6 @@ libc {
     __timespec_get64;
     __time_t64; __stime_t64;
     __gettimeofday_t64; __settimeofday_t64;
+    __nanosleep_t64;
   }
 }
diff --git a/time/nanosleep64.c b/time/nanosleep64.c
new file mode 100644
index 0000000..a099f93
--- /dev/null
+++ b/time/nanosleep64.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 1996-2017 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>
+
+extern int __y2038_linux_support;
+
+/* Pause execution for a number of nanoseconds.  */
+int
+__nanosleep_t64 (const struct __timespec64 *requested_time,
+	         struct __timespec64 *remaining)
+{
+  struct timespec treq32, *treqp32 = NULL;
+  struct timespec trem32, *tremp32 = NULL;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: use 64-bit time syscalls */
+  }
+
+  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;
+}
diff --git a/time/time.h b/time/time.h
index 58faa7c..1ce762e 100644
--- a/time/time.h
+++ b/time/time.h
@@ -310,6 +310,14 @@ 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), __nanosleep_t64);
+# else
+# define nanosleep __nanosleep_t64
+# endif
+#endif
 extern int nanosleep (const struct timespec *__requested_time,
 		      struct timespec *__remaining);
 

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

commit a7478751c7abac419e501dd9ffb56c38c14ce3e8
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Sat Jul 8 16:43:24 2017 +0200

    Y2038: implement Y2038-ready sched_rr_get_interval

diff --git a/posix/Makefile b/posix/Makefile
index 8f23d64..4c398b9 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -59,7 +59,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		:= tstgetopt testfnm runtests runptests	     \
diff --git a/posix/Versions b/posix/Versions
index bb481a5..dd6d834 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -137,4 +137,11 @@ libc {
   GLIBC_PRIVATE {
     __libc_fork; __libc_pread; __libc_pwrite;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __sched_rr_get_interval_t64;
+  }
 }
diff --git a/posix/sched.h b/posix/sched.h
index 7037ab3..c4f50f6 100644
--- a/posix/sched.h
+++ b/posix/sched.h
@@ -72,6 +72,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_t64) __THROW;
+# else
+# define sched_rr_get_interval __sched_rr_get_interval_t64
+# endif
+#endif
 extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW;
 
 
diff --git a/posix/sched_rr_gi64.c b/posix/sched_rr_gi64.c
new file mode 100644
index 0000000..187a8a4
--- /dev/null
+++ b/posix/sched_rr_gi64.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1996-2017 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>
+
+extern int __y2038_linux_support;
+
+/* Get the SCHED_RR interval for the named process.  */
+
+int
+__sched_rr_get_interval_t64 (pid_t pid, struct __timespec64 *t)
+{
+  struct timespec ts32;
+  int result;
+
+  if (t == NULL)
+  {
+    __set_errno(EINVAL);
+    return -1;
+  }
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: use 64-bit syscall */
+  }
+
+  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=9bca8bc4e86b496ddb7bb536221329af8e16f6b0

commit 9bca8bc4e86b496ddb7bb536221329af8e16f6b0
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Sat Jul 8 15:00:23 2017 +0200

    Y2038: implement Y2038-ready msgctl

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 202ffcc..3fcd1c2 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -172,4 +172,11 @@ libc {
     # functions used by nscd
     __netlink_assert_response;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __msgctl_t64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/bits/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
index 31c4863..ba3f24f 100644
--- a/sysdeps/unix/sysv/linux/bits/msq.h
+++ b/sysdeps/unix/sysv/linux/bits/msq.h
@@ -35,6 +35,25 @@ 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 */
+  unsigned long int __glibc_reserved1;
+  __time64_t msg_rtime;		/* time of last msgrcv command */
+  unsigned long int __glibc_reserved2;
+  __time64_t msg_ctime;		/* time of last change */
+  unsigned long int __glibc_reserved3;
+  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 +71,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/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index e5ae621..cd8e389 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -69,3 +69,75 @@ __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_ds_t64
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved1;
+  __time64_t msg_rtime;		/* time of last msgrcv command */
+  unsigned long int __glibc_reserved2;
+  __time64_t msg_ctime;		/* time of last change */
+  unsigned long int __glibc_reserved3;
+  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;
+};
+
+extern int __y2038_linux_support;
+
+int
+__msgctl_t64 (int msqid, int cmd, struct __msqid_ds_t64 *buf)
+{
+  int result;
+  struct msqid_ds buf32, *pbuf32 = NULL;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: use 64-bit syscalls */
+  }
+
+  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->__glibc_reserved1 = buf32.__glibc_reserved1;
+    buf->msg_rtime = buf32.msg_rtime;
+    buf->__glibc_reserved2 = buf32.__glibc_reserved2;
+    buf->msg_ctime = buf32.msg_ctime;
+    buf->__glibc_reserved3 = buf32.__glibc_reserved3;
+    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;
+    buf->__glibc_reserved4 = buf32.__glibc_reserved4;
+    buf->__glibc_reserved5 = buf32.__glibc_reserved5;
+  }
+
+  return result;
+}
diff --git a/sysvipc/sys/msg.h b/sysvipc/sys/msg.h
index 3610050..4a6a947 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),
+                       __msgctl_t64) __THROW;
+# else
+# define msgctl __msgctl_t64
+# endif
+#endif
 extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) __THROW;
 
 /* Get messages queue.  */

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

commit 3c989fdbc1573c8230ab7b250104ce934d3e4644
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Thu Jul 6 19:31:15 2017 +0200

    Y2038: implement Y2038-ready mq_timedsend, mq_timedreceive

diff --git a/rt/Makefile b/rt/Makefile
index 4713497..a63e6bf 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_timedreceive_t64 mq_timedsend_t64
 
 routines = $(clock-routines)
 
diff --git a/rt/Versions b/rt/Versions
index d14a87f..4f6f54d 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -44,5 +44,6 @@ librt {
   GLIBC_Y2038 {
     __timer_gettime64; __timer_settime64;
     __timerfd_gettime64; __timerfd_settime64;
+    __mq_timedreceive_t64; __mq_timedsend_t64;
   }
 }
diff --git a/rt/mq_timedreceive_t64.c b/rt/mq_timedreceive_t64.c
new file mode 100644
index 0000000..d24937a
--- /dev/null
+++ b/rt/mq_timedreceive_t64.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2004-2017 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>
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+/* Receive the oldest from highest priority messages in message queue
+   MQDES, stop waiting if ABS_TIMEOUT expires.  */
+ssize_t
+__mq_timedreceive_t64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len,
+		 unsigned int *__restrict msg_prio,
+		 const struct timespec *__restrict abs_timeout)
+{
+  struct timespec ts32, *tsp32 = NULL;
+  if (__y2038_linux_support)
+  {
+    /* TODO: use 64-bit syscall */
+  }
+
+  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/rt/mq_timedsend_t64.c b/rt/mq_timedsend_t64.c
new file mode 100644
index 0000000..b585d99
--- /dev/null
+++ b/rt/mq_timedsend_t64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2004-2017 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>
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+/* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
+   on full message queue if ABS_TIMEOUT expires.  */
+int
+__mq_timedsend_t64 (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;
+  if (__y2038_linux_support)
+  {
+    /* TODO: use 64-bit syscall */
+  }
+
+  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/rt/mqueue.h b/rt/mqueue.h
index d65871e..1ca165f 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_timedreceive_t64) __nonnull((2, 5));
+#  else
+#   define mq_timedreceive __mq_timedreceive_t64
+#  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_timedsend_t64) __nonnull((2, 5));
+#  else
+#   define mq_timedsend __mq_timedsend_t64
+#  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)

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

commit b565efd17dc76a342d3c583ef7dafbe26a1b0304
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jun 28 14:27:28 2017 +0200

    Y2038: implement Y2038-ready gettimeofday, settimeofday
    
    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/sysdeps/unix/sysv/linux/gettimeofday.c b/sysdeps/unix/sysv/linux/gettimeofday.c
index 6afa407..aab64ce 100644
--- a/sysdeps/unix/sysv/linux/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/gettimeofday.c
@@ -37,3 +37,29 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
 libc_hidden_def (__gettimeofday)
 weak_alias (__gettimeofday, gettimeofday)
 libc_hidden_weak (gettimeofday)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__gettimeofday_t64 (struct __timeval64 *tv, struct timezone *tz)
+{
+  struct timeval tv32;
+  int result;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using 64-bit time syscall */
+  }
+
+  result = INLINE_VSYSCALL (gettimeofday, 2, &tv32, tz);
+
+  if (result == 0)
+  {
+    tv->tv_sec = tv32.tv_sec;
+    tv->tv_usec = tv32.tv_usec;
+  }
+
+  return result;
+}
diff --git a/time/settimeofday.c b/sysdeps/unix/sysv/linux/settimeofday64.c
similarity index 65%
copy from time/settimeofday.c
copy to sysdeps/unix/sysv/linux/settimeofday64.c
index 317c93d..16fb16c 100644
--- a/time/settimeofday.c
+++ b/sysdeps/unix/sysv/linux/settimeofday64.c
@@ -15,17 +15,30 @@
    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)
+extern int __y2038_linux_support;
+
+int __settimeofday_t64(const struct __timeval64 *tv,
+                       const struct timezone *tz)
 {
-  __set_errno (ENOSYS);
-  return -1;
-}
-stub_warning (settimeofday)
+  struct timeval tv32;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: use 64-bit syscall */
+  }
 
-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 317c4d8..5fb26f6 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -36,7 +36,8 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
-	    timespec_get
+	    timespec_get                                 \
+	    settimeofday64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index d3cc6f4..a007efa 100644
--- a/time/Versions
+++ b/time/Versions
@@ -72,5 +72,6 @@ libc {
   GLIBC_Y2038 {
     __timespec_get64;
     __time_t64; __stime_t64;
+    __gettimeofday_t64; __settimeofday_t64;
   }
 }
diff --git a/time/gettimeofday.c b/time/gettimeofday.c
index 1d675b6..b21d7d4 100644
--- a/time/gettimeofday.c
+++ b/time/gettimeofday.c
@@ -32,3 +32,13 @@ weak_alias (__gettimeofday, gettimeofday)
 libc_hidden_weak (gettimeofday)
 
 stub_warning (gettimeofday)
+
+/* 64-bit time version */
+
+int
+__gettimeofday_t64 (struct timeval *tv, struct timezone *tz)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__gettimeofday_t64)
diff --git a/time/settimeofday.c b/time/settimeofday.c
index 317c93d..65db5ab 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
+__settimeofday_t64 (const struct timeval *tv, const struct timezone *tz)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__settimeofday_t64)
diff --git a/time/sys/time.h b/time/sys/time.h
index e60b962..3080740 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -65,12 +65,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),
+                    __gettimeofday_t64) __THROW __nonnull((1));
+# else
+# define gettimeofday __gettimeofday_t64
+# 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),
+                    __settimeofday_t64) __THROW;
+#  else
+#   define settimeofday __settimeofday_t64
+#  endif
+# endif
 extern int settimeofday (const struct timeval *__tv,
 			 const struct timezone *__tz)
      __THROW;

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

commit be6bc9db14202da17608e9ce1e74b916d397c086
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jun 28 13:45:16 2017 +0200

    Y2038: implement Y2038-ready utimes

diff --git a/misc/utimes.c b/misc/utimes.c
index 73d91ac..56718fe 100644
--- a/misc/utimes.c
+++ b/misc/utimes.c
@@ -37,3 +37,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/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 2679ec3..0bc3902 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -35,6 +35,7 @@ libc {
     __futimens64;
     __utimensat64;
     __sigtimedwait64;
+    __utimes_t64;
     __futimes64;
     __lutimes64;
   }
diff --git a/sysdeps/unix/sysv/linux/utimes.c b/sysdeps/unix/sysv/linux/utimes.c
index 038ff20..b5d72ab 100644
--- a/sysdeps/unix/sysv/linux/utimes.c
+++ b/sysdeps/unix/sysv/linux/utimes.c
@@ -34,3 +34,34 @@ __utimes (const char *file, const struct timeval tvp[2])
 }
 
 weak_alias (__utimes, utimes)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+{
+  struct timeval tv32[2], *tvp32 = NULL;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using 64-bit time syscall */
+  }
+
+  if (tvp != NULL)
+  {
+    if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+    {
+      __set_errno(EOVERFLOW);
+      return -1;
+    }
+    tv32[0].tv_sec = tvp[0].tv_sec;
+    tv32[0].tv_usec = tvp[0].tv_usec;
+    tv32[1].tv_sec = tvp[1].tv_sec;
+    tv32[1].tv_usec = tvp[1].tv_usec;
+    tvp32 = tv32;
+  }
+
+  return INLINE_SYSCALL (utimes, 2, file, tvp32);
+}
diff --git a/time/sys/time.h b/time/sys/time.h
index c179227..e60b962 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -132,6 +132,15 @@ 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));
 
@@ -140,7 +149,8 @@ extern int utimes (const char *__file, const struct timeval __tvp[2])
 #ifdef __USE_TIME_BITS64
 # if defined(__REDIRECT)
 extern int __REDIRECT (lutimes, (const char *__file,
-       const struct timeval __tvp[2]), __lutimes64) __THROW;
+       const struct timeval __tvp[2]), __lutimes64)
+       __THROW __nonnull ((1));
 # else
 # define lutimes __lutimes64
 # endif

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

commit 4cbfd9cb0a4196c0920dd3f1bbd64d4ec38e8bde
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jun 28 09:10:11 2017 +0200

    Y2038: implement Y2038-ready time, stime
    
    These implementations use only 32-bit time
    kernel syscalls.
    
    Therefore, stime() will always set errno to
    EOVERFLOW and return -1 for dates beyond Y2038.

diff --git a/sysdeps/posix/time.c b/sysdeps/posix/time.c
index 32ca177..a4c4a03 100644
--- a/sysdeps/posix/time.c
+++ b/sysdeps/posix/time.c
@@ -38,3 +38,29 @@ time (time_t *t)
   return result;
 }
 libc_hidden_def (time)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+__time64_t
+__time_t64 (__time64_t *t)
+{
+  struct timeval tv32;
+  __time64_t result;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using 64-bit time syscall */
+  }
+
+  if (__gettimeofday (&tv32, (struct timezone *) NULL))
+    result = (__time64_t) -1;
+  else
+    result = (__time64_t) tv32.tv_sec;
+
+  if (t != NULL)
+    *t = result;
+
+  return result;
+}
diff --git a/sysdeps/unix/stime.c b/sysdeps/unix/stime.c
index 526ba13..177c933 100644
--- a/sysdeps/unix/stime.c
+++ b/sysdeps/unix/stime.c
@@ -37,3 +37,34 @@ stime (const time_t *when)
   tv.tv_usec = 0;
   return __settimeofday (&tv, (struct timezone *) 0);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__stime_t64 (const __time64_t *when)
+{
+  struct timeval tv32;
+
+  if (when == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement 64-bit-time syscall case */
+  }
+
+  if (*when > INT_MAX)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  tv32.tv_sec = *when;
+  tv32.tv_usec = 0;
+  return __settimeofday (&tv32, (struct timezone *) 0);
+}
diff --git a/sysdeps/unix/sysv/linux/time.c b/sysdeps/unix/sysv/linux/time.c
index 72d4040..475367b 100644
--- a/sysdeps/unix/sysv/linux/time.c
+++ b/sysdeps/unix/sysv/linux/time.c
@@ -34,6 +34,28 @@ time (time_t *t)
 }
 libc_hidden_def (time)
 
+/* 64-BIT TIME VERSION */
+
+extern int __y2038_linux_support;
+
+__time64_t
+__time_t64 (__time64_t *t)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  __time64_t res;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using 64-bit time syscall */
+  }
+
+  res = INTERNAL_SYSCALL (time, err, 1, NULL);
+  /* There cannot be any error.  */
+  if (t != NULL)
+    *t = res;
+  return res;
+}
+
 #else
 
 # include <sysdeps/posix/time.c>
diff --git a/time/Versions b/time/Versions
index 3fe8608..d3cc6f4 100644
--- a/time/Versions
+++ b/time/Versions
@@ -71,5 +71,6 @@ libc {
 
   GLIBC_Y2038 {
     __timespec_get64;
+    __time_t64; __stime_t64;
   }
 }
diff --git a/time/stime.c b/time/stime.c
index 723eeda..c1c7c4c 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
+__stime_t64 (const __time64_t *when)
+{
+  if (when == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__stime_t64)
diff --git a/time/time.c b/time/time.c
index e375035..a487068 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
+__time_t64 (__time64_ *timer)
+{
+  __set_errno (ENOSYS);
+
+  if (timer != NULL)
+    *timer = (__time64_t) -1;
+  return (__time64_t) -1;
+}
+libc_hidden_def (__time_t64)
diff --git a/time/time.h b/time/time.h
index 8b2954f..58faa7c 100644
--- a/time/time.h
+++ b/time/time.h
@@ -73,6 +73,14 @@ __BEGIN_NAMESPACE_STD
 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),
+     __time_t64) __THROW;
+# else
+# define time __time_t64
+# endif
+#endif
 extern time_t time (time_t *__timer) __THROW;
 
 /* Return the difference between TIME1 and TIME0.  */
@@ -250,6 +258,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), __stime_t64)
+           __THROW;
+# else
+# define stime __stime_t64
+# endif
+#endif
 extern int stime (const time_t *__when) __THROW;
 #endif
 

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

commit 883d2525fca68e86b68ca61300c1d18461e4596e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 24 10:27:17 2017 +0200

    Y2038: implement Y2038-ready fstatat64, fxstatat (WIP)
    
    WIP: there is no Y2038-proof linux struct stat for now,
    so these implementations just use the existing syscalls
    and convert from kernel 32-bit-time struct stat64 to
    GLIBC Y2038-ready struct stat64

diff --git a/io/Versions b/io/Versions
index c02e9ca..03d621b 100644
--- a/io/Versions
+++ b/io/Versions
@@ -133,5 +133,6 @@ libc {
     __xstat64_t64;
     __fxstat64_t64;
     __lxstat64_t64;
+    __fxstatat64_t64;
   }
 }
diff --git a/io/fstatat64.c b/io/fstatat64.c
index 13a9ebc..4e13f07 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_t64 (int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  return __fxstatat64_t64 (_STAT_VER, fd, file, buf, flag);
+}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 68fa91c..b60a5ef 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -443,6 +443,10 @@ extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64_t64)
      __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
+					const char *__filename,
+					struct stat *__stat_buf, int __flag),
+			   __fxstatat64_t64) __nonnull ((3, 4));
 #  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
@@ -453,11 +457,11 @@ extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64)
      __nonnull ((2, 3));
-#  endif
 extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 					const char *__filename,
 					struct stat *__stat_buf, int __flag),
 			   __fxstatat64) __nonnull ((3, 4));
+#  endif
 
 # else
 #  ifdef __USE_TIME_BITS64
@@ -488,6 +492,9 @@ extern int __lxstat64_t64 (int __ver, const char *__filename,
 extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
 			 struct stat64 *__stat_buf, int __flag)
      __THROW __nonnull ((3, 4));
+extern int __fxstatat64_t64 (int __ver, int __fildes, const char *__filename,
+			 struct __stat64_t64 *__stat_buf, int __flag)
+     __THROW __nonnull ((3, 4));
 #endif
 extern int __xmknod (int __ver, const char *__path, __mode_t __mode,
 		     __dev_t *__dev) __THROW __nonnull ((2, 4));
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index ef1e132..c3631b6 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -26,6 +26,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 /* Get information about the file NAME in BUF.  */
 
 int
@@ -45,3 +47,46 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
 								      err));
 }
 libc_hidden_def (__fxstatat64)
+
+int
+__fxstatat64_t64 (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;
+    buf->__pad1		     = st64.__pad1;
+
+    buf->__st_ino        = st64.__st_ino;
+    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->__pad2          = st64.__pad2;
+    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=30bec5b027c43378b654212daa631996b8ca6608

commit 30bec5b027c43378b654212daa631996b8ca6608
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 24 08:51:53 2017 +0200

    Y2038: implement Y2038-ready lstat64, lxstat64 (WIP)
    
    WIP: there is no Y2038-proof linux struct stat for now,
    so these implementations just use the existing syscalls
    and convert from kernel 32-bit-time struct stat64 to
    GLIBC Y2038-ready struct stat64

diff --git a/io/Versions b/io/Versions
index 2f0e137..c02e9ca 100644
--- a/io/Versions
+++ b/io/Versions
@@ -132,5 +132,6 @@ libc {
   GLIBC_Y2038 {
     __xstat64_t64;
     __fxstat64_t64;
+    __lxstat64_t64;
   }
 }
diff --git a/io/lstat64.c b/io/lstat64.c
index c29492a..50bf7df 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_t64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __lxstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index ef72e07..68fa91c 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -440,6 +440,9 @@ extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 				     struct stat *__stat_buf), __xstat64_t64)
      __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
+				      struct stat *__stat_buf), __lxstat64_t64)
+     __nonnull ((2, 3));
 #  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
@@ -447,10 +450,10 @@ extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 				     struct stat *__stat_buf), __xstat64)
      __nonnull ((2, 3));
-#  endif
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64)
      __nonnull ((2, 3));
+#  endif
 extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 					const char *__filename,
 					struct stat *__stat_buf, int __flag),
@@ -460,11 +463,12 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 #  ifdef __USE_TIME_BITS64
 #   define __fxstat __fxstat64_t64
 #   define __xstat __xstat64_t64
+#   define __lxstat __lxstat64_t64
 #  else
 #   define __fxstat __fxstat64
 #   define __xstat __xstat64
+#   define __lxstat __lxstat64
 #  endif
-#  define __lxstat __lxstat64
 # endif
 #endif
 
@@ -479,6 +483,8 @@ extern int __xstat64_t64 (int __ver, const char *__filename,
 		      struct __stat64_t64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __lxstat64 (int __ver, const char *__filename,
 		       struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
+extern int __lxstat64_t64 (int __ver, const char *__filename,
+		       struct __stat64_t64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
 			 struct stat64 *__stat_buf, int __flag)
      __THROW __nonnull ((3, 4));
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 9bc548f..814fcbc 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file NAME in BUF.  */
@@ -50,3 +52,41 @@ hidden_ver (___lxstat64, __lxstat64)
 strong_alias (___lxstat64, __lxstat64);
 hidden_def (__lxstat64)
 #endif
+
+int
+__lxstat64_t64 (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;
+    buf->__pad1		     = st64.__pad1;
+
+    buf->__st_ino        = st64.__st_ino;
+    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->__pad2          = st64.__pad2;
+    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=06cb92b4426780fb28f30d742f47e36d89df0194

commit 06cb92b4426780fb28f30d742f47e36d89df0194
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue May 23 23:15:15 2017 +0200

    Y2038: implement Y2038 stat64, fstat64, xstat64, fxstat64 (WIP)
    
    WIP: there is no Y2038-proof linux struct stat for now,
    so these implementations just use the existing syscalls
    and convert from kernel 32-bit-time struct stat64 to
    GLIBC Y2038-ready struct stat64

diff --git a/io/Versions b/io/Versions
index 64316cd..2f0e137 100644
--- a/io/Versions
+++ b/io/Versions
@@ -125,4 +125,12 @@ libc {
   GLIBC_2.23 {
     fts64_children; fts64_close; fts64_open; fts64_read; fts64_set;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __xstat64_t64;
+    __fxstat64_t64;
+  }
 }
diff --git a/io/fstat64.c b/io/fstat64.c
index 69c80e5..a972304 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_t64 (int fd, struct __stat64_t64 *buf)
+{
+  return __fxstat64_t64 (_STAT_VER, fd, buf);
+}
diff --git a/io/stat64.c b/io/stat64.c
index 704cbb3..22fc0db 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_t64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __xstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 3e546b5..ef72e07 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -210,14 +210,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_t64)
+     __nonnull ((1, 2));
+extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), __fstat64_t64)
+     __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_t64
+#   define fstat fstat64_t64
+#  else
+#   define stat stat64
+#   define fstat fstat64
+#  endif
 # endif
 #endif
 #ifdef __USE_LARGEFILE64
@@ -420,12 +433,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_t64)
+     __nonnull ((3));
+extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
+				     struct stat *__stat_buf), __xstat64_t64)
+     __nonnull ((2, 3));
+#  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
      __nonnull ((3));
 extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
 				     struct stat *__stat_buf), __xstat64)
      __nonnull ((2, 3));
+#  endif
 extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
 				      struct stat *__stat_buf), __lxstat64)
      __nonnull ((2, 3));
@@ -435,8 +457,13 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 			   __fxstatat64) __nonnull ((3, 4));
 
 # else
-#  define __fxstat __fxstat64
-#  define __xstat __xstat64
+#  ifdef __USE_TIME_BITS64
+#   define __fxstat __fxstat64_t64
+#   define __xstat __xstat64_t64
+#  else
+#   define __fxstat __fxstat64
+#   define __xstat __xstat64
+#  endif
 #  define __lxstat __lxstat64
 # endif
 #endif
@@ -444,8 +471,12 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 #ifdef __USE_LARGEFILE64
 extern int __fxstat64 (int __ver, int __fildes, struct stat64 *__stat_buf)
      __THROW __nonnull ((3));
+extern int __fxstat64_t64 (int __ver, int __fildes, struct __stat64_t64 *__stat_buf)
+     __THROW __nonnull ((3));
 extern int __xstat64 (int __ver, const char *__filename,
 		      struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
+extern int __xstat64_t64 (int __ver, const char *__filename,
+		      struct __stat64_t64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __lxstat64 (int __ver, const char *__filename,
 		       struct stat64 *__stat_buf) __THROW __nonnull ((2, 3));
 extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 8a59d86..18bc209 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file FD in BUF.  */
@@ -51,3 +53,41 @@ hidden_ver (___fxstat64, __fxstat64)
 strong_alias (___fxstat64, __fxstat64)
 hidden_def (__fxstat64)
 #endif
+
+int
+__fxstat64_t64 (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;
+    buf->__pad1		     = st64.__pad1;
+
+    buf->__st_ino        = st64.__st_ino;
+    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->__pad2          = st64.__pad2;
+    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;
+}
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index b3fbe6a..809d6dd 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file NAME in BUF.  */
@@ -52,3 +54,41 @@ hidden_ver (___xstat64, __xstat64)
 strong_alias (___xstat64, __xstat64)
 hidden_def (__xstat64)
 #endif
+
+int
+__xstat64_t64 (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;
+    buf->__pad1		     = st64.__pad1;
+
+    buf->__st_ino        = st64.__st_ino;
+    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->__pad2          = st64.__pad2;
+    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_ctim.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=80c7dd94fa7f998304d5d1c35947f263963adcb1

commit 80c7dd94fa7f998304d5d1c35947f263963adcb1
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 24 08:44:49 2017 +0200

    Y2038: implement struct stat

diff --git a/sysdeps/unix/sysv/linux/bits/stat.h b/sysdeps/unix/sysv/linux/bits/stat.h
index 187590e..3d690b9 100644
--- a/sysdeps/unix/sysv/linux/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/bits/stat.h
@@ -128,6 +128,30 @@ struct stat64
 # endif
     __ino64_t st_ino;			/* File serial number.		*/
   };
+
+#  include <include/time.h>
+
+struct __stat64_t64
+  {
+    __dev_t st_dev;			/* Device.  */
+    unsigned int __pad1;
+
+    __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.  */
+    unsigned int __pad2;
+    __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.		*/
+  };
 #endif
 
 /* Tell code we have these members.  */

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

commit 7d371d071b949da9e8c0c9215f42628b11432449
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 3 12:12:17 2017 +0200

    Y2038: implement Y2038-proof timerfd_gettime, timerfd_settime
    
    Note: this tests the return value of function __y2038_kernel_support()
    rather than the value of variable __y2038_linux_upport, because the
    latter cannot be accessed from librt while the former can.

diff --git a/rt/Makefile b/rt/Makefile
index 5283839..4713497 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 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 7377976..d14a87f 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -43,5 +43,6 @@ librt {
 
   GLIBC_Y2038 {
     __timer_gettime64; __timer_settime64;
+    __timerfd_gettime64; __timerfd_settime64;
   }
 }
diff --git a/rt/timerfd_gettime64.c b/rt/timerfd_gettime64.c
new file mode 100644
index 0000000..9496fca
--- /dev/null
+++ b/rt/timerfd_gettime64.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1999-2016 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>
+
+/* Get current value of timer TIMERID and store it in VLAUE.  */
+int
+__timerfd_gettime64 (int fd, struct itimerspec *value)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_gettime64)
diff --git a/rt/timerfd_settime64.c b/rt/timerfd_settime64.c
new file mode 100644
index 0000000..8551c7a
--- /dev/null
+++ b/rt/timerfd_settime64.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1999-2016 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>
+
+/* Set timer TIMERID to VALUE, returning old value in OVLAUE.  */
+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/sys/timerfd.h b/sysdeps/unix/sysv/linux/sys/timerfd.h
index 6899b5e..78d8fae 100644
--- a/sysdeps/unix/sysv/linux/sys/timerfd.h
+++ b/sysdeps/unix/sysv/linux/sys/timerfd.h
@@ -41,11 +41,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/timerfd_gettime64.c b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
new file mode 100644
index 0000000..5c2105c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   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 "kernel-posix-timers.h"
+
+int
+__timerfd_gettime64 (int fd, struct __itimerspec64 *value)
+{
+  struct itimerspec value32;
+
+  if (__y2038_kernel_support())
+    return INLINE_SYSCALL (timerfd_gettime64, 2, fd, value);
+
+  int 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;
+}
diff --git a/sysdeps/unix/sysv/linux/timerfd_settime64.c b/sysdeps/unix/sysv/linux/timerfd_settime64.c
new file mode 100644
index 0000000..b20f0e1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_settime64.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   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 "kernel-posix-timers.h"
+
+int
+__timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
+	             struct __itimerspec64 *ovalue)
+{
+  int res;
+  struct __itimerspec64 value64;
+  struct itimerspec value32;
+  struct itimerspec ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+  if (__y2038_kernel_support())
+  {
+    value64.it_value.tv_sec = value->it_value.tv_sec;
+    value64.it_value.tv_nsec = value->it_value.tv_nsec;
+    value64.it_value.tv_pad = 0;
+    value64.it_interval.tv_sec = value->it_interval.tv_sec;
+    value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+    value64.it_interval.tv_pad = 0;
+    
+    return INLINE_SYSCALL (timerfd_settime64, 4, fd, flags,
+                           &value64, ovalue);
+  }
+
+  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 (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=38004afade923c4b8dbcc5443f79824ebf458306

commit 38004afade923c4b8dbcc5443f79824ebf458306
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed May 3 09:19:14 2017 +0200

    Y2038: implement Y2038-proof timer_gettime, timer_settime

diff --git a/rt/Versions b/rt/Versions
index 91e3fd2..7377976 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -37,4 +37,11 @@ librt {
   GLIBC_2.7 {
    __mq_open_2;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __timer_gettime64; __timer_settime64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 849c56a..48e16fa 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -39,3 +39,27 @@ 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;
+
+  if (__y2038_kernel_support())
+    return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
+
+  int 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;
+}
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index ba35036..e3caa7f 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -41,3 +41,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)
+{
+  struct timer *kt = (struct timer *) timerid;
+  struct __itimerspec64 value64;
+  struct itimerspec value32, ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+  if (__y2038_kernel_support())
+  {
+    value64.it_value.tv_sec = value->it_value.tv_sec;
+    value64.it_value.tv_nsec = value->it_value.tv_nsec;
+    value64.it_value.tv_pad = 0;
+    value64.it_interval.tv_sec = value->it_interval.tv_sec;
+    value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+    value64.it_interval.tv_pad = 0;
+
+    return INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
+			    &value64, ovalue);
+  }
+
+  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;
+
+  int 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;
+}
diff --git a/time/time.h b/time/time.h
index dd9fff6..8b2954f 100644
--- a/time/time.h
+++ b/time/time.h
@@ -364,11 +364,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;
 

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

commit 10c487e07abc556b6dbb9639823bcbe14998ed52
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jun 12 23:41:11 2017 +0200

    Y2038: implement Y2038-proof struct itimerspec
    
    When time_t was introduced, all time_t based types were modified
    to use a 64-bit time_t. This is indirectly the case for struct
    itimespec too, which contains two struct timerspec fields, it_interval
    and it_value.

diff --git a/include/time.h b/include/time.h
index 06f4084..e7dc9ea 100644
--- a/include/time.h
+++ b/include/time.h
@@ -49,6 +49,12 @@ struct __timeval64
   __int64_t tv_usec;		/* Microseconds */
 };
 
+struct __itimerspec64
+{
+  struct __timespec64 it_interval;
+  struct __timespec64 it_value;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;

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

commit 6549107ac4eed0650f9d2ef91d4ca51cb618f33e
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 26 00:35:05 2017 +0200

    Y2038: implement Y2038-proof lutimes

diff --git a/misc/lutimes.c b/misc/lutimes.c
index c4cce8f..e01b5c9 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/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 3179a00..2679ec3 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -36,5 +36,6 @@ libc {
     __utimensat64;
     __sigtimedwait64;
     __futimes64;
+    __lutimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 433fb06..bf87f58 100644
--- a/sysdeps/unix/sysv/linux/lutimes.c
+++ b/sysdeps/unix/sysv/linux/lutimes.c
@@ -42,3 +42,56 @@ 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 */
+
+extern int __y2038_linux_support;
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  /* The system call expects timespec, not timeval.  */
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (__y2038_linux_support)
+  {
+    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;
+
+      return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, &ts64,
+			     AT_SYMLINK_NOFOLLOW);
+    }
+
+    return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, NULL,
+			   AT_SYMLINK_NOFOLLOW);
+  }
+
+  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;
+
+    return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, &ts32,
+                           AT_SYMLINK_NOFOLLOW);
+  }
+
+  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, NULL,
+                         AT_SYMLINK_NOFOLLOW);
+}
diff --git a/time/sys/time.h b/time/sys/time.h
index 78fa3f3..c179227 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -137,6 +137,14 @@ extern int utimes (const char *__file, const struct timeval __tvp[2])
 
 #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;
+# else
+# define lutimes __lutimes64
+# endif
+#endif
 extern int lutimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 

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

commit 1a2aa5c0140676774b3b51537064a1bd17d23a22
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 26 00:03:32 2017 +0200

    Y2038: implement Y2038-proof futimes

diff --git a/misc/futimes.c b/misc/futimes.c
index 6dad999..e4c9ee2 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/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 3217f00..3179a00 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -35,5 +35,6 @@ libc {
     __futimens64;
     __utimensat64;
     __sigtimedwait64;
+    __futimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index af79cb1..1043d03 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -49,3 +49,55 @@ __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 */
+
+extern int __y2038_linux_support;
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  /* The utimensat system call expects timespec not timeval.  */
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (__y2038_linux_support)
+  {
+    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;
+
+      return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64, 0);
+    }
+
+    return INLINE_SYSCALL (utimensat64, 4, fd, NULL, NULL, 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);
+
+    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;
+
+    return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32, 0);
+  }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, NULL, 0);
+}
diff --git a/time/sys/time.h b/time/sys/time.h
index 165296a..78fa3f3 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -141,6 +141,14 @@ 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
 

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

commit 8fc765839f89a43d56530bdf051200903b746325
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jul 5 21:04:50 2017 +0200

    Y2038: implement Y2038-proof struct timeval
    
    When time_t was introduced, all time_t based types were modified
    to use a 64-bit time_t.
    
    However, struct timeval uses __time_t and __suseconds_t rather than
    time_t, and therefore, is left unaffected by __USE_TIME_BITS64; so
    we introduce a public 64-bit variant with two 64-bit fields, and a
    private variant called struct __timeval64 for use by 64-bit API
    implementations.

diff --git a/include/time.h b/include/time.h
index 18f223a..06f4084 100644
--- a/include/time.h
+++ b/include/time.h
@@ -43,6 +43,12 @@ struct __timespec64
 };
 #endif
 
+struct __timeval64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __int64_t tv_usec;		/* Microseconds */
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;
diff --git a/time/bits/types/struct_timeval.h b/time/bits/types/struct_timeval.h
index 70394ce..85e0cb5 100644
--- a/time/bits/types/struct_timeval.h
+++ b/time/bits/types/struct_timeval.h
@@ -5,9 +5,18 @@
 
 /* A time value that is accurate to the nearest
    microsecond but also has a range of years.  */
+#ifdef __USE_TIME_BITS64
+struct timeval
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  __uint64_t tv_usec;   	/* Microseconds.  */
+};
+#else
 struct timeval
 {
   __time_t tv_sec;		/* Seconds.  */
   __suseconds_t tv_usec;	/* Microseconds.  */
 };
 #endif
+
+#endif

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

commit 900eac1572cb173206c0b7615fe4e212552e1d94
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Apr 25 23:21:28 2017 +0200

    Y2038: implement Y2038-proof sigtimedwait

diff --git a/signal/signal.h b/signal/signal.h
index 2c7f9e1..bec7ca6 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -280,6 +280,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/signal/sigtimedwait.c b/signal/sigtimedwait.c
index 3b42003..c1e0d43 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
+__sigtimedwait64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__sigtimedwait64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 3f514b5..3217f00 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -34,5 +34,6 @@ libc {
     __clock_nanosleep64;
     __futimens64;
     __utimensat64;
+    __sigtimedwait64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index ab1a84e..77339ea 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+#include <stdint.h>
 
 #include <nptl/pthreadP.h>
 #include <sysdep-cancel.h>
@@ -64,6 +65,80 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
 }
 libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__sigtimedwait64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  int result;
+  struct __timespec64 ts64;
+  struct timespec ts32;
+
+#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.  */
+
+  if (__y2038_linux_support)
+  {
+    if (timeout)
+    {
+      ts64.tv_sec = timeout->tv_sec;
+      ts64.tv_nsec = timeout->tv_nsec;
+      ts64.tv_pad = 0;
+      result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts64, _NSIG / 8);
+    }
+    else
+      result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+  }
+  else
+  {
+    if (timeout)
+    {
+      if (timeout->tv_sec > INT32_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      ts32.tv_sec = timeout->tv_sec;
+      ts32.tv_nsec = timeout->tv_nsec;
+      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;
+}
 #else
 # include <signal/sigtimedwait.c>
 #endif

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

commit f18cb908299da4925b515b11462488a40a19f551
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Thu Apr 20 09:17:50 2017 +0200

    Y2038: implement Y2038-proof utimensat

diff --git a/io/sys/stat.h b/io/sys/stat.h
index f58d05c..3e546b5 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -357,6 +357,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)
diff --git a/io/utimensat.c b/io/utimensat.c
index f45eb73..6b9cf43 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
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utimensat64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 5e33f9c..3f514b5 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -33,5 +33,6 @@ libc {
     __vdso_clock_gettime64;
     __clock_nanosleep64;
     __futimens64;
+    __utimensat64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 87f1ef0..eb382b1 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 <stdio.h>
 
 
 /* Change the access time of FILE to TSP[0] and
@@ -34,3 +35,38 @@ 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 */
+
+extern int __y2038_linux_support;
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (file == NULL)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+  if (!tsp)
+    return INLINE_SYSCALL (utimensat64, 4, fd, file, NULL, flags);
+
+  if (__y2038_linux_support)
+  {
+    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;
+    return INLINE_SYSCALL (utimensat64, 4, fd, file, &ts64, flags);
+  }
+
+  ts32[0].tv_sec = tsp[0].tv_sec;
+  ts32[0].tv_nsec = tsp[0].tv_nsec;
+  ts32[1].tv_sec = tsp[1].tv_sec;
+  ts32[1].tv_nsec = tsp[1].tv_nsec;
+  return INLINE_SYSCALL (utimensat, 4, fd, file, &ts32, flags);
+}

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

commit f133fc505fdb1c7058e8b0a40e826a7e323d323c
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 19 10:02:59 2017 +0200

    Y2038: implement Y2038-proof futimens

diff --git a/io/futimens.c b/io/futimens.c
index 27fc1ae..516e64e 100644
--- a/io/futimens.c
+++ b/io/futimens.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <time.h>
 #include <sysdep.h>
+#include <kernel_timespec.h>
 
 
 /* Change the access time of the file associated with FD to TSP[0] and
@@ -32,3 +33,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/io/sys/stat.h b/io/sys/stat.h
index 2ada4a5..f58d05c 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -365,6 +365,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
 
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index a5abd71..5e33f9c 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -32,5 +32,6 @@ libc {
     __clock_gettime64; __clock_settime64; __clock_getres64;
     __vdso_clock_gettime64;
     __clock_nanosleep64;
+    __futimens64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c
index b4985e0..e2f5d28 100644
--- a/sysdeps/unix/sysv/linux/futimens.c
+++ b/sysdeps/unix/sysv/linux/futimens.c
@@ -36,3 +36,41 @@ 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 */
+
+extern int __y2038_linux_support;
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (fd < 0)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+
+  if (__y2038_linux_support)
+  {
+    if (fd < 0)
+      return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+    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;
+    return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64[0], 0);
+  }
+
+  if (tsp[0].tv_sec > INT_MAX || tsp[1].tv_sec > INT_MAX)
+  {
+    return EOVERFLOW;
+  }
+
+  ts32[0].tv_sec = tsp[0].tv_sec;
+  ts32[0].tv_nsec = tsp[0].tv_nsec;
+  ts32[1].tv_sec = tsp[1].tv_sec;
+  ts32[1].tv_nsec = tsp[1].tv_nsec;
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32[0], 0);
+}

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

commit 0dc9169f88bdebe84aaedc75630d311ced2b135a
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Jun 21 01:04:02 2017 +0200

    Y2038: implement Y2038-proof timespec_get

diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index 1f63e57..b43b5ae 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -44,3 +44,38 @@ timespec_get (struct timespec *ts, int base)
 
   return base;
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__timespec_get64 (struct __timespec64 *ts, int base)
+{
+  switch (base)
+    {
+      int res;
+      INTERNAL_SYSCALL_DECL (err);
+    case TIME_UTC:
+      if (__y2038_linux_support)
+      {
+        res = INTERNAL_VSYSCALL (clock_gettime64, err, 2, CLOCK_REALTIME, ts);
+      }
+      else
+      {
+        struct timespec ts32;
+        res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, &ts32);
+        if (INTERNAL_SYSCALL_ERROR_P (res, err))
+	  return 0;
+        ts->tv_sec = ts32.tv_sec;
+        ts->tv_nsec = ts32.tv_nsec;
+        ts->tv_pad = 0;
+      }
+      break;
+
+    default:
+      return 0;
+    }
+
+  return base;
+}
diff --git a/time/Versions b/time/Versions
index fd83818..3fe8608 100644
--- a/time/Versions
+++ b/time/Versions
@@ -65,4 +65,11 @@ libc {
   GLIBC_2.16 {
     timespec_get;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __timespec_get64;
+  }
 }
diff --git a/time/time.h b/time/time.h
index 69eac79..dd9fff6 100644
--- a/time/time.h
+++ b/time/time.h
@@ -379,6 +379,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=9356344a977656834696df03fe34998b2e057eb4

commit 9356344a977656834696df03fe34998b2e057eb4
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Apr 11 22:35:48 2017 +0200

    Y2038: implement Y2038-proof clock_nanosleep

diff --git a/include/time.h b/include/time.h
index 9b29235..18f223a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -51,6 +51,9 @@ extern int __clock_gettime64 (clockid_t __clock_id, struct __timespec64 *__tp) _
 extern __typeof (clock_settime) __clock_settime;
 extern int __clock_settime64 (clockid_t __clock_id, const struct __timespec64 *__tp) __THROW;
 extern __typeof (clock_nanosleep) __clock_nanosleep;
+extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
+			    const struct __timespec64 *__req,
+			    struct __timespec64 *__rem);
 extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
 /* Now define the internal interfaces.  */
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index e3cd16d..a5abd71 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -31,5 +31,6 @@ libc {
     __timegm64;
     __clock_gettime64; __clock_settime64; __clock_getres64;
     __vdso_clock_gettime64;
+    __clock_nanosleep64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 93bc4cf..479619e 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,89 @@ __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 */
+
+extern int __y2038_linux_support;
+
+int
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+		   const struct __timespec64 *req,
+                   struct __timespec64 *rem)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  int r;
+  struct __timespec64 req64;
+  struct timespec req32, rem32;
+
+  if (clock_id == CLOCK_THREAD_CPUTIME_ID)
+    return EINVAL;
+  if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
+    clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
+
+  if (SINGLE_THREAD_P)
+  {
+    if (__y2038_linux_support)
+    {
+      req64.tv_sec = req->tv_sec;
+      req64.tv_nsec = req->tv_nsec;
+      req64.tv_pad = 0;
+      r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+                            &req64, rem);
+    }
+    else if (req->tv_sec > INT_MAX)
+      r = EOVERFLOW;
+    else
+    {
+      req32.tv_sec = req->tv_sec;
+      req32.tv_nsec = req->tv_nsec;
+      r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+                            &req32, &rem32);
+      if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+      {
+        rem->tv_sec = rem32.tv_sec;
+        rem->tv_nsec = rem32.tv_nsec;
+        rem->tv_pad = 0;
+      }
+    }
+  }
+  else
+    {
+      int oldstate = LIBC_CANCEL_ASYNC ();
+
+      if (__y2038_linux_support)
+      {
+        req64.tv_sec = req->tv_sec;
+        req64.tv_nsec = req->tv_nsec;
+        req64.tv_pad = 0;
+        r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+                              &req64, rem);
+      }
+      else if (req->tv_sec > INT_MAX)
+        r = EOVERFLOW;
+      else
+      {
+        req32.tv_sec = req->tv_sec;
+        req32.tv_nsec = req->tv_nsec;
+        r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+                              &req32, &rem32);
+        if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+        {
+          rem->tv_sec = rem32.tv_sec;
+          rem->tv_nsec = rem32.tv_nsec;
+          rem->tv_pad = 0;
+        }
+      }
+      
+      LIBC_CANCEL_RESET (oldstate);
+    }
+
+  if (INTERNAL_SYSCALL_ERROR_P (r, err))
+  {
+    return INTERNAL_SYSCALL_ERRNO (r, err);
+  }
+  else
+  {
+    return 0;
+  }
+}
diff --git a/time/time.h b/time/time.h
index 07ad045..69eac79 100644
--- a/time/time.h
+++ b/time/time.h
@@ -337,6 +337,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);

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

commit 5e09d6036ed8ad0aed641cdff7938142c643c78c
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Jun 20 23:37:11 2017 +0200

    Y2038: implement Y2038-proof clock_gettime, clock_settime, and clock_getres

diff --git a/include/time.h b/include/time.h
index 3f4a4c3..9b29235 100644
--- a/include/time.h
+++ b/include/time.h
@@ -22,6 +22,11 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+/* Indicates whether the underlying kernel has 64-bit time support.
+   This is required for e.g. librt, which cannot directly check the
+   flag variable that init-first.c sets when detecting support. */
+extern int __y2038_kernel_support (void);
+
 #if BYTE_ORDER == BIG_ENDIAN
 struct __timespec64
 {
@@ -40,8 +45,11 @@ struct __timespec64
 
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
+extern int __clock_getres64 (clockid_t __clock_id, struct __timespec64 *__res) __THROW;
 libc_hidden_proto (__clock_gettime)
+extern int __clock_gettime64 (clockid_t __clock_id, struct __timespec64 *__tp) __THROW;
 extern __typeof (clock_settime) __clock_settime;
+extern int __clock_settime64 (clockid_t __clock_id, const struct __timespec64 *__tp) __THROW;
 extern __typeof (clock_nanosleep) __clock_nanosleep;
 extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index b6248be..3b74014 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -23,7 +23,6 @@
 #include <sys/param.h>
 #include <libc-internal.h>
 
-
 #if HP_TIMING_AVAIL
 static long int nsec;		/* Clock frequency of the processor.  */
 
@@ -53,6 +52,33 @@ hp_timing_getres (struct timespec *res)
 
   return 0;
 }
+
+static int
+hp_timing_getres64 (struct __timespec64 *res)
+{
+  if (__glibc_unlikely (nsec == 0))
+    {
+      hp_timing_t freq;
+
+      /* This can only happen if we haven't initialized the `nsec'
+	 variable yet.  Do this now.  We don't have to protect this
+	 code against multiple execution since all of them should
+	 lead to the same result.  */
+      freq = __get_clockfreq ();
+      if (__glibc_unlikely (freq == 0))
+	/* Something went wrong.  */
+	return -1;
+
+      nsec = MAX (UINT64_C (1000000000) / freq, 1);
+    }
+
+  /* Fill in the values.
+     The seconds are always zero (unless we have a 1Hz machine).  */
+  res->tv_sec = 0;
+  res->tv_nsec = nsec;
+
+  return 0;
+}
 #endif
 
 static inline int
@@ -73,6 +99,24 @@ realtime_getres (struct timespec *res)
   return -1;
 }
 
+static inline int
+realtime_getres64 (struct __timespec64 *res)
+{
+  long int clk_tck = sysconf (_SC_CLK_TCK);
+
+  if (__glibc_likely (clk_tck != -1))
+    {
+      /* This implementation assumes that the realtime clock has a
+	 resolution higher than 1 second.  This is the case for any
+	 reasonable implementation.  */
+      res->tv_sec = 0;
+      res->tv_nsec = 1000000000 / clk_tck;
+      return 0;
+    }
+
+  return -1;
+}
+
 
 /* Get resolution of clock.  */
 int
@@ -116,3 +160,44 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
   return retval;
 }
 weak_alias (__clock_getres, clock_getres)
+
+int
+__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
+{
+  int retval = -1;
+
+  switch (clock_id)
+    {
+#ifdef SYSDEP_GETRES64
+      SYSDEP_GETRES64;
+#endif
+
+#ifndef HANDLED_REALTIME64
+    case CLOCK_REALTIME64:
+      retval = realtime_getres64 (res);
+      break;
+#endif	/* handled REALTIME */
+
+    default:
+#ifdef SYSDEP_GETRES_CPU64
+      SYSDEP_GETRES_CPU64;
+#endif
+#if HP_TIMING_AVAIL
+      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+	  == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_getres64 (res);
+      else
+#endif
+	__set_errno (EINVAL);
+      break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+    case CLOCK_PROCESS_CPUTIME_ID:
+    case CLOCK_THREAD_CPUTIME_ID:
+      retval = hp_timing_getres64 (res);
+      break;
+#endif
+    }
+
+  return retval;
+}
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 5262066..ac224c9 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -134,3 +134,49 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
 }
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
+
+/* Get current value of CLOCK and store it in TP, 64-bit version.  */
+int
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
+{
+  int retval = -1;
+
+  switch (clock_id)
+    {
+#ifdef SYSDEP_GETTIME64
+      SYSDEP_GETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      {
+	struct timeval tv;
+	retval = gettimeofday (&tv, NULL);
+	if (retval == 0)
+	  TIMEVAL_TO_TIMESPEC (&tv, tp);
+      }
+      break;
+#endif
+
+    default:
+#ifdef SYSDEP_GETTIME64_CPU
+      SYSDEP_GETTIME64_CPU (clock_id, tp);
+#endif
+#if HP_TIMING_AVAIL
+      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+	  == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_gettime (clock_id, tp);
+      else
+#endif
+	__set_errno (EINVAL);
+      break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+    case CLOCK_PROCESS_CPUTIME_ID:
+      retval = hp_timing_gettime (clock_id, tp);
+      break;
+#endif
+    }
+
+  return retval;
+}
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 957a4b1..3c08558 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -69,8 +69,62 @@ hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
 }
 #endif
 
+/* Set CLOCK to value TP, 64-bit Y2038-safe version.  */
+int
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
+{
+  int retval = EOVERFLOW;
+
+  /* Make sure the time cvalue is OK.  */
+  if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  switch (clock_id)
+    {
+#define HANDLE_REALTIME \
+      do {								      \
+	struct timeval tv;						      \
+	TIMESPEC_TO_TIMEVAL (&tv, tp);					      \
+									      \
+	retval = settimeofday (&tv, NULL);				      \
+      } while (0)
+
+#ifdef SYSDEP_SETTIME64
+      SYSDEP_SETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      HANDLE_REALTIME;
+      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/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index f7feda3..e3cd16d 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -15,6 +15,8 @@ libc {
     __default_sa_restorer; __default_rt_sa_restorer;
     # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
     __vdso_clock_gettime;
+    # __y2038_kernel_support is used by e.g. librt
+    __y2038_kernel_support;
   }
 
   # Y2038 symbols are given their own version until they can be put in
@@ -27,5 +29,7 @@ libc {
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r;
     __timegm64;
+    __clock_gettime64; __clock_settime64; __clock_getres64;
+    __vdso_clock_gettime64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/init-first.c b/sysdeps/unix/sysv/linux/arm/init-first.c
index 3c289c2..61c01a5 100644
--- a/sysdeps/unix/sysv/linux/arm/init-first.c
+++ b/sysdeps/unix/sysv/linux/arm/init-first.c
@@ -23,6 +23,14 @@
 
 int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *) attribute_hidden;
 int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
+
+int __y2038_linux_support;
+
+int __y2038_kernel_support (void)
+{
+  return __y2038_linux_support;
+}
 
 static inline void
 _libc_vdso_platform_setup (void)
@@ -36,6 +44,13 @@ _libc_vdso_platform_setup (void)
   p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
   PTR_MANGLE (p);
   VDSO_SYMBOL (clock_gettime) = p;
+
+  /* (aaribaud) TODO: map to version where clock_gettime64 officially appears */
+  p = _dl_vdso_vsym ("__vdso_clock_gettime64", NULL);
+  PTR_MANGLE (p);
+  VDSO_SYMBOL (clock_gettime64) = p;
+
+  __y2038_linux_support = (p != NULL) ? 1 : 0;
 }
 
 # define VDSO_SETUP _libc_vdso_platform_setup
diff --git a/sysdeps/unix/sysv/linux/arm/libc-vdso.h b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
index ae37b57..ee0e594 100644
--- a/sysdeps/unix/sysv/linux/arm/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
@@ -27,6 +27,7 @@
 extern int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *)
    attribute_hidden;
 extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+extern long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
 
 #endif
 
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 2b7bb65..3da8c0e 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -48,4 +48,44 @@
 #define SYSDEP_GETRES_CPU SYSCALL_GETRES
 #define SYSDEP_GETRES_CPUTIME	/* Default catches them too.  */
 
+/* The 64-bit version */
+
+extern int __y2038_linux_support;
+
+#define SYSCALL_GETRES64 \
+  if (__y2038_linux_support)						      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_getres64, 2, clock_id, res);  	      \
+  }									      \
+  else									      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);	      \
+    if (retval==0)							      \
+    {									      \
+      res->tv_sec = ts32.tv_sec;		                	      \
+      res->tv_nsec = ts32.tv_nsec;					      \
+      res->tv_pad = 0;				                	      \
+    }									      \
+  }									      \
+  break
+
+/* 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/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index e232f69..30d3e12 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -44,4 +44,48 @@
   break
 #define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */
 
+/* 64-bit versions */
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+   kernel.  */
+#define SYSDEP_GETTIME64 \
+  SYSDEP_GETTIME64_CPUTIME;						      \
+  case CLOCK_REALTIME:							      \
+  case CLOCK_MONOTONIC:							      \
+    if (__y2038_linux_support)						      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);	      \
+    }									      \
+    else								      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);	      \
+      if (retval==0)							      \
+      {									      \
+        tp->tv_sec = ts32.tv_sec;					      \
+        tp->tv_nsec = ts32.tv_nsec;					      \
+        tp->tv_pad = 0;							      \
+      }									      \
+    }									      \
+    break
+
+#define SYSDEP_GETTIME64_CPU(clock_id, tp) \
+  if (__y2038_linux_support)						      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);	      \
+  }									      \
+  else									      \
+  {									      \
+    retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);	      \
+    if (retval==0)							      \
+    {									      \
+      tp->tv_sec = ts32.tv_sec;						      \
+      tp->tv_nsec = ts32.tv_nsec;					      \
+      tp->tv_pad = 0;							      \
+    }									      \
+  }									      \
+  break
+#define SYSDEP_GETTIME64_CPUTIME \
+  struct timespec ts32;							      \
+  extern int __y2038_linux_support;
+
 #include <sysdeps/unix/clock_gettime.c>
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 058c518..2821956 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -35,4 +35,27 @@
 #define SYSDEP_SETTIME_CPU \
   retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
 
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+#define SYSDEP_SETTIME64 \
+  case CLOCK_REALTIME:							      \
+    if (__y2038_linux_support)						      \
+    {									      \
+      struct __timespec64 ts64;						      \
+      ts64.tv_sec = tp->tv_sec;						      \
+      ts64.tv_nsec = tp->tv_nsec;					      \
+      ts64.tv_pad = 0;							      \
+      retval = INLINE_SYSCALL (clock_settime64, 2, clock_id, &ts64);	      \
+    }									      \
+    else if (tp->tv_sec <= INT_MAX)					      \
+    {									      \
+      struct timespec ts32;						      \
+      ts32.tv_sec = tp->tv_sec;						      \
+      ts32.tv_nsec = tp->tv_nsec;					      \
+      retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32);	      \
+    }									      \
+    break
+
 #include <sysdeps/unix/clock_settime.c>
diff --git a/time/time.h b/time/time.h
index f89884d..07ad045 100644
--- a/time/time.h
+++ b/time/time.h
@@ -299,12 +299,36 @@ extern int nanosleep (const struct timespec *__requested_time,
 
 
 /* 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;
 

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

commit 5bc5e88f9a39a76c442423009fb13e1def259be7
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Mon Jun 12 23:23:27 2017 +0200

    Y2038: implement Y2038-proof struct timespec
    
    When time_t was introduced, all time_t based types were modified
    to use a 64-bit time_t. This is the case for struct timespec too,
    which made its Y2038-proof variant contain a 64-bit tv_sec field
    and a long (32-bit) tv_nsec field.
    
    While this definition would be compatible with Posix requirements,
    it would result in the GLIBC struct timespec being binary-incompatible
    with the Linux struct timespec, which contains a 64-bit, ot 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.
    
    This change provides both an API (public) and implementation
    (private) version of struct timespec, so that in the API version,
    the padding is made 'invisible' by defining it as an anonymous
    bitfield; whereas the private struct timespec has a named field
    for the padding, allowing implementations to test or set it.

diff --git a/include/time.h b/include/time.h
index f995a2a..3f4a4c3 100644
--- a/include/time.h
+++ b/include/time.h
@@ -4,6 +4,8 @@
 #ifndef _ISOMAC
 # include <xlocale.h>
 
+#include <endian.h>
+
 __BEGIN_DECLS
 
 extern __typeof (strftime_l) __strftime_l;
@@ -20,6 +22,22 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+#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
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h
index 644db9f..9f75a6d 100644
--- a/time/bits/types/struct_timespec.h
+++ b/time/bits/types/struct_timespec.h
@@ -2,13 +2,30 @@
 #define __timespec_defined 1
 
 #include <bits/types.h>
+#include <endian.h>
 
 /* POSIX.1b structure for a time value.  This is like a `struct timeval' but
    has nanoseconds instead of microseconds.  */
+# ifndef __USE_TIME_BITS64
 struct timespec
 {
   __time_t tv_sec;		/* Seconds.  */
   __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
 };
+# elif BYTE_ORDER == BIG_ENDIAN
+struct timespec
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  int: 32;			/* Hidden padding */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+};
+# else
+struct timespec
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+  int: 32;			/* Hidden padding */
+};
+# endif
 
 #endif

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

commit a4b25b246d68a4b876faf4a81f7ace969ed3cb50
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Apr 5 22:51:34 2017 +0200

    Y2038: implement Y2038-proof timegm
    
    The __timegm64' implementation is based on the same __mktime64_internal
    function which was introduced in the 'mktime' implementation change.
    
    Again, the implementation does not require a Y2038-proof kernel.

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 546d7c6..f7feda3 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -26,5 +26,6 @@ libc {
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r;
+    __timegm64;
   }
 }
diff --git a/time/time.h b/time/time.h
index 7260d28..f89884d 100644
--- a/time/time.h
+++ b/time/time.h
@@ -265,6 +265,13 @@ 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'.  */
diff --git a/time/timegm.c b/time/timegm.c
index b0f5d16..89fac10 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -36,6 +36,9 @@
 time_t __mktime_internal (struct tm *,
 			  struct tm * (*) (time_t const *, struct tm *),
 			  time_t *);
+__time64_t __mktime64_internal (struct tm *,
+			  struct tm * (*) (__time64_t const *, struct tm *),
+			  __time64_t *);
 #endif
 
 time_t
@@ -45,3 +48,11 @@ timegm (struct tm *tmp)
   tmp->tm_isdst = 0;
   return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
 }
+
+__time64_t
+__timegm64 (struct tm *tmp)
+{
+  static __time64_t gmtime64_offset;
+  tmp->tm_isdst = 0;
+  return __mktime64_internal (tmp, __gmtime64_r, &gmtime64_offset);
+}

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

commit 6c6f234bc2f11c7a219dda730aeb532929e89380
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Tue Feb 7 22:21:14 2017 +0100

    Y2038: implement Y2038-proof mktime (and timelocal)
    
    API 'mktime' (aka 'timelocal') is implemented by function __mktime64.
    
    __mktime64 is designed similar to mktime, including checks on (64-bit)
    integer limits, and respects the same Posix requirements as __mktime does,
    i.e. calls tzset().
    
    Also, the implementation does not require a Y2038-proof kernel.

diff --git a/include/time.h b/include/time.h
index 09c92e5..f995a2a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -63,6 +63,15 @@ extern time_t __mktime_internal (struct tm *__tp,
 				 struct tm *(*__func) (const time_t *,
 						       struct tm *),
 				 time_t *__offset);
+
+/* Subroutine of `__mktime64'.  Return the `__time64_t' representation of TP and
+   normalize TP, given that a `struct tm *' maps to a `__time64_t' as performed
+   by FUNC.  Keep track of next guess for __time64_t offset in *OFFSET.  */
+extern __time64_t __mktime64_internal (struct tm *__tp,
+				 struct tm *(*__func) (const __time64_t *,
+						       struct tm *),
+				 __time64_t *__offset);
+
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index dd6a160..546d7c6 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -25,5 +25,6 @@ libc {
     __ctime64; __ctime64_r;
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
+    __mktime64; __timelocal64_r;
   }
 }
diff --git a/time/mktime.c b/time/mktime.c
index 4c48d35..3bd2631 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -599,6 +599,412 @@ weak_alias (mktime, timelocal)
 libc_hidden_def (mktime)
 libc_hidden_weak (timelocal)
 #endif
+
+/* 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.
+
+   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.  */
+
+static __time64_t
+ydhms64_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);
+
+  /* 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 a100 = a4 / 25 - (a4 % 25 < 0);
+  int b100 = b4 / 25 - (b4 % 25 < 0);
+  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 __time64_t precision.  Overflow might
+     occur here.  */
+  __time64_t tyear1 = year1;
+  __time64_t years = tyear1 - year0;
+  __time64_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+  __time64_t hours = 24 * days + hour1 - hour0;
+  __time64_t minutes = 60 * hours + min1 - min0;
+  __time64_t seconds = 60 * minutes + sec1 - sec0;
+  return seconds;
+}
+
+/* Return the average of A and B, even if A + B would overflow.  */
+static __time64_t
+time64_t_avg (__time64_t a, __time64_t b)
+{
+  return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
+}
+
+/* Return 1 if A + B does not overflow.  If __time64_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
+time64_t_add_ok (__time64_t a, __time64_t b)
+{
+  if (! TYPE_SIGNED (__time64_t))
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (TIME_T_MIDPOINT <= b);
+    }
+  else if (WRAPV)
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (b < 0);
+    }
+  else
+    {
+      __time64_t avg = time64_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
+time64_t_int_add_ok (__time64_t a, int b)
+{
+  verify (int_no_wider_than_time64_t, INT_MAX <= TIME_T_MAX);
+  if (WRAPV)
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (b < 0);
+    }
+  else
+    {
+      int a_odd = a & 1;
+      __time64_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
+      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+    }
+}
+
+/* Return a __time64_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+   assuming that *T corresponds to *TP and that no clock adjustments
+   occurred between *TP and the desired time.
+   If TP is null, return a value not equal to *T; this avoids false matches.
+   If overflow occurs, yield the minimal or maximal value, except do not
+   yield a value equal to *T.  */
+static __time64_t
+guess_time64_tm (long_int year, long_int yday, int hour, int min, int sec,
+	       const __time64_t *t, const struct tm *tp)
+{
+  if (tp)
+    {
+      __time64_t d = ydhms64_diff (year, yday, hour, min, sec,
+			     tp->tm_year, tp->tm_yday,
+			     tp->tm_hour, tp->tm_min, tp->tm_sec);
+      if (time64_t_add_ok (*t, d))
+	return *t + d;
+    }
+
+  /* Overflow occurred one way or another.  Return the nearest result
+     that is actually in range, except don't report a zero difference
+     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));
+}
+
+/* Use CONVERT to convert *T to a broken down time in *TP.
+   If *T is out of range for conversion, adjust it so that
+   it is the nearest in-range value and then convert that.  */
+static struct tm *
+ranged64_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
+		__time64_t *t, struct tm *tp)
+{
+  struct tm *r = convert (t, tp);
+
+  if (!r && *t)
+    {
+      __time64_t bad = *t;
+      __time64_t ok = 0;
+
+      /* BAD is a known unconvertible __time64_t, and OK is a known good one.
+	 Use binary search to narrow the range between BAD and OK until
+	 they differ by 1.  */
+      while (bad != ok + (bad < 0 ? -1 : 1))
+	{
+	  __time64_t mid = *t = time64_t_avg (ok, bad);
+	  r = convert (t, tp);
+	  if (r)
+	    ok = mid;
+	  else
+	    bad = mid;
+	}
+
+      if (!r && ok)
+	{
+	  /* The last conversion attempt failed;
+	     revert to the most recent successful attempt.  */
+	  *t = ok;
+	  r = convert (t, tp);
+	}
+    }
+
+  return r;
+}
+
+
+/* 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.  */
+__time64_t
+__mktime64_internal (struct tm *tp,
+		   struct tm *(*convert) (const __time64_t *, struct tm *),
+		   __time64_t *offset)
+{
+  __time64_t t, gt, t0, t1, t2;
+  struct tm tm;
+
+  /* The maximum number of probes (calls to CONVERT) should be enough
+     to handle any combinations of time zone rule changes, solar time,
+     leap seconds, and oscillations around a spring-forward gap.
+     POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
+  int remaining_probes = 6;
+
+  /* Time requested.  Copy it in case CONVERT modifies *TP; this can
+     occur if TP is localtime's returned value and CONVERT is localtime.  */
+  int sec = tp->tm_sec;
+  int min = tp->tm_min;
+  int hour = tp->tm_hour;
+  int mday = tp->tm_mday;
+  int mon = tp->tm_mon;
+  int year_requested = tp->tm_year;
+  int isdst = tp->tm_isdst;
+
+  /* 1 if the previous probe was DST.  */
+  int dst2;
+
+  /* Ensure that mon is in range, and set year accordingly.  */
+  int mon_remainder = mon % 12;
+  int negative_mon_remainder = mon_remainder < 0;
+  int mon_years = mon / 12 - negative_mon_remainder;
+  long_int lyear_requested = year_requested;
+  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 __time64_t arithmetic wraps around.
+     Major overflows are caught at the end.  */
+
+  /* Calculate day of year from year, month, and day of month.
+     The result need not be in range.  */
+  int mon_yday = ((__mon_yday[leapyear (year)]
+		   [mon_remainder + 12 * negative_mon_remainder])
+		  - 1);
+  long_int lmday = mday;
+  long_int yday = mon_yday + lmday;
+
+  __time64_t guessed_offset = *offset;
+
+  int sec_requested = sec;
+
+  if (LEAP_SECONDS_POSSIBLE)
+    {
+      /* Handle out-of-range seconds specially,
+	 since ydhms_tm_diff assumes every minute has 60 seconds.  */
+      if (sec < 0)
+	sec = 0;
+      if (59 < sec)
+	sec = 59;
+    }
+
+  /* Invert CONVERT by probing.  First assume the same offset as last
+     time.  */
+
+  t0 = ydhms64_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)
+    {
+      /* __time64_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) */
+      __time64_t time64_t_max = TIME_T_MAX;
+      __time64_t time64_t_min = TIME_T_MIN;
+      __time64_t overflow_threshold =
+	(time64_t_max / 3 - time64_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.  */
+	  __time64_t repaired_t0 = -1 - t0;
+	  approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
+	  diff = approx_biennia - approx_requested_biennia;
+	  approx_abs_diff = diff < 0 ? -1 - diff : diff;
+	  if (overflow_threshold < approx_abs_diff)
+	    return -1;
+	  guessed_offset += repaired_t0 - t0;
+	  t0 = repaired_t0;
+	}
+    }
+
+  /* Repeatedly use the error to improve the guess.  */
+
+  for (t = t1 = t2 = t0, dst2 = 0;
+       (gt = guess_time64_tm (year, yday, hour, min, sec, &t,
+			    ranged64_convert (convert, &t, &tm)),
+	t != gt);
+       t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
+    if (t == t1 && t != t2
+	&& (tm.tm_isdst < 0
+	    || (isdst < 0
+		? dst2 <= (tm.tm_isdst != 0)
+		: (isdst != 0) != (tm.tm_isdst != 0))))
+      /* We can't possibly find a match, as we are oscillating
+	 between two values.  The requested time probably falls
+	 within a spring-forward gap of size GT - T.  Follow the common
+	 practice in this case, which is to return a time that is GT - T
+	 away from the requested time, preferring a time whose
+	 tm_isdst differs from the requested value.  (If no tm_isdst
+	 was requested and only one of the two values has a nonzero
+	 tm_isdst, prefer that value.)  In practice, this is more
+	 useful than returning -1.  */
+      goto offset_found;
+    else if (--remaining_probes == 0)
+      return -1;
+
+  /* We have a match.  Check whether tm.tm_isdst has the requested
+     value, if any.  */
+  if (isdst_differ (isdst, tm.tm_isdst))
+    {
+      /* tm.tm_isdst has the wrong value.  Look for a neighboring
+	 time with the right value, and use its UTC offset.
+
+	 Heuristic: probe the adjacent timestamps in both directions,
+	 looking for the desired isdst.  This should work for all real
+	 time zone histories in the tz database.  */
+
+      /* Distance between probes when looking for a DST boundary.  In
+	 tzdata2003a, the shortest period of DST is 601200 seconds
+	 (e.g., America/Recife starting 2000-10-08 01:00), and the
+	 shortest period of non-DST surrounded by DST is 694800
+	 seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
+	 minimum of these two values, so we don't miss these short
+	 periods when probing.  */
+      int stride = 601200;
+
+      /* The longest period of DST in tzdata2003a is 536454000 seconds
+	 (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
+	 period of non-DST is much longer, but it makes no real sense
+	 to search for more than a year of non-DST, so use the DST
+	 max.  */
+      int duration_max = 536454000;
+
+      /* Search in both directions, so the maximum distance is half
+	 the duration; add the stride to avoid off-by-1 problems.  */
+      int delta_bound = duration_max / 2 + stride;
+
+      int delta, direction;
+
+      for (delta = stride; delta < delta_bound; delta += stride)
+	for (direction = -1; direction <= 1; direction += 2)
+	  if (time64_t_int_add_ok (t, delta * direction))
+	    {
+	      __time64_t ot = t + delta * direction;
+	      struct tm otm;
+	      ranged64_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_time64_tm (year, yday, hour, min, sec, &ot, &otm);
+		  ranged64_convert (convert, &t, &tm);
+		  goto offset_found;
+		}
+	    }
+    }
+
+ offset_found:
+  *offset = guessed_offset + t - t0;
+
+  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 (! time64_t_int_add_ok (t, sec_requested))
+	return -1;
+      t1 = t + sec_requested;
+      if (! time64_t_int_add_ok (t1, sec_adjustment))
+	return -1;
+      t2 = t1 + sec_adjustment;
+      if (! convert (&t2, &tm))
+	return -1;
+      t = t2;
+    }
+
+  *tp = tm;
+  return t;
+}
+
+
+/* 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 __time64_t localtime64_offset;
+
+/* Convert *TP to a __time64_t value.  */
+__time64_t
+__mktime64 (struct tm *tp)
+{
+#ifdef _LIBC
+  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+     time zone names contained in the external variable 'tzname' shall
+     be set as if the tzset() function had been called.  */
+  __tzset ();
+#endif
+
+  return __mktime64_internal (tp, __localtime64_r, &localtime64_offset);
+}
 
 #if defined DEBUG_MKTIME && DEBUG_MKTIME
 
diff --git a/time/time.h b/time/time.h
index cd637bc..7260d28 100644
--- a/time/time.h
+++ b/time/time.h
@@ -88,9 +88,15 @@ 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.  */
@@ -262,6 +268,13 @@ extern int stime (const time_t *__when) __THROW;
 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.  */

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

commit 3a166b60d1aaaeae91fd3c13a9eb6ee6a7da26a9
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Mar 29 12:01:45 2017 +0200

    Y2038: implement Y2038-proof 'struct tm' related APIs
    
    This consists in the following implementation additions:
    
    ([file] 32-bit implementation -> [file] 64-bit addition)
    
    time/ctime.c ctime() -> __ctime64()
    time/ctime_r.c ctime_r() -> __ctime64_r()
    time/gmtime.c gmtime() -> __gmtime64()
    time/gmtime.c gmtime_r() -> __gmtime64_r()
    time/localtime.c localtime() -> __localtime64()
    time/localtime.c localtime_r() -> __localtime64_r()
    
    which require the following internal function additions
    
    time/offtime.c __offtime() -> __offtime64()
    time/tzset.c __tz_convert() -> __tz64_convert()
    
    and internal function (32-bit-time-compatible) changes
    
    time/tzfile.c __tzfile_compute()
    time/tzset.c tzset_internal()
    time/tzset.c compute_change()

diff --git a/include/time.h b/include/time.h
index 684ceb8..09c92e5 100644
--- a/include/time.h
+++ b/include/time.h
@@ -10,6 +10,8 @@ extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
 extern __typeof (strptime_l) __strptime_l;
 
+extern struct tm *__localtime64 (const __time64_t *__timer);
+
 libc_hidden_proto (time)
 libc_hidden_proto (asctime)
 libc_hidden_proto (mktime)
@@ -45,13 +47,13 @@ extern int __use_tzfile attribute_hidden;
 
 extern void __tzfile_read (const char *file, size_t extra,
 			   char **extrap);
-extern void __tzfile_compute (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);
 extern void __tzfile_default (const char *std, const char *dst,
 			      long int stdoff, long int dstoff);
 extern void __tzset_parse_tz (const char *tz);
-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 internal_function;
 
 /* Subroutine of `mktime'.  Return the `time_t' representation of TP and
@@ -64,15 +66,25 @@ extern time_t __mktime_internal (struct tm *__tp,
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
-extern struct tm *__gmtime_r (const time_t *__restrict __timer,
+extern struct tm *__localtime64_r (const __time64_t *__timer,
+				 struct tm *__tp) attribute_hidden;
+
+extern struct tm *__gmtime_r (const __time_t *__restrict __timer,
 			      struct tm *__restrict __tp);
 libc_hidden_proto (__gmtime_r)
 
+extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer,
+			      struct tm *__restrict __tp);
+
 /* Compute the `struct tm' representation of *T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
    Return nonzero if successful.  */
-extern int __offtime (const time_t *__timer,
+extern int __offtime (const __time_t *__timer,
+		      long int __offset,
+		      struct tm *__tp);
+
+extern int __offtime64 (const __time64_t *__timer,
 		      long int __offset,
 		      struct tm *__tp);
 
@@ -80,7 +92,9 @@ extern char *__asctime_r (const struct tm *__tp, char *__buf);
 extern void __tzset (void);
 
 /* 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);
+extern struct tm *__tz_convert (const __time_t *timer, int use_localtime, struct tm *tp);
+
+extern struct tm *__tz_convert64 (const __time64_t *timer, int use_localtime, struct tm *tp);
 
 /* Return the maximum length of a timezone name.
    This is what `sysconf (_SC_TZNAME_MAX)' does.  */
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index d365576..dd6a160 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -22,5 +22,8 @@ libc {
 
   GLIBC_Y2038 {
     __difftime64;
+    __ctime64; __ctime64_r;
+    __gmtime64; __gmtime64_r;
+    __localtime64; __localtime64_r;
   }
 }
diff --git a/time/ctime.c b/time/ctime.c
index 7baca1b..a5150c1 100644
--- a/time/ctime.c
+++ b/time/ctime.c
@@ -26,3 +26,13 @@ ctime (const time_t *t)
      In particular, ctime and asctime must yield the same pointer.  */
   return asctime (localtime (t));
 }
+
+/* Return a string as returned by asctime which
+   is the representation of *T in that form.  */
+char *
+__ctime64 (const __time64_t *t)
+{
+  /* Apply the same rule as ctime:
+     make ctime64 (t) is equivalent to asctime (localtime64 (t)).  */
+  return asctime (__localtime64 (t));
+}
diff --git a/time/ctime_r.c b/time/ctime_r.c
index ecd7731..74d856f 100644
--- a/time/ctime_r.c
+++ b/time/ctime_r.c
@@ -27,3 +27,12 @@ ctime_r (const time_t *t, char *buf)
   struct tm tm;
   return __asctime_r (__localtime_r (t, &tm), buf);
 }
+
+/* Return a string as returned by asctime which is the representation
+   of *T in that form.  Reentrant Y2038-proof version.  */
+char *
+__ctime64_r (const __time64_t *t, char *buf)
+{
+  struct tm tm;
+  return __asctime_r (__localtime64_r (t, &tm), buf);
+}
diff --git a/time/gmtime.c b/time/gmtime.c
index 049d551..7662c1d 100644
--- a/time/gmtime.c
+++ b/time/gmtime.c
@@ -35,3 +35,18 @@ gmtime (const time_t *t)
 {
   return __tz_convert (t, 0, &_tmbuf);
 }
+
+/* Return the `struct tm' representation of 64-bit-time *T
+   in UTC, using *TP to store the result.  */
+struct tm *
+__gmtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert64 (t, 0, tp);
+}
+
+/* Return the `struct tm' representation of 64-bit-time *T in UTC.	*/
+struct tm *
+__gmtime64 (const __time64_t *t)
+{
+  return __tz_convert64 (t, 0, &_tmbuf);
+}
diff --git a/time/localtime.c b/time/localtime.c
index 07dd67c..fd2d997 100644
--- a/time/localtime.c
+++ b/time/localtime.c
@@ -39,3 +39,20 @@ localtime (const time_t *t)
   return __tz_convert (t, 1, &_tmbuf);
 }
 libc_hidden_def (localtime)
+
+/* 64-bit-time versions */
+
+/* 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_convert64 (t, 1, tp);
+}
+
+/* Return the `struct tm' representation of *T in local time.  */
+struct tm *
+__localtime64 (const __time64_t *t)
+{
+  return __tz_convert64 (t, 1, &_tmbuf);
+}
diff --git a/time/offtime.c b/time/offtime.c
index 75a28fe..84237db 100644
--- a/time/offtime.c
+++ b/time/offtime.c
@@ -84,3 +84,67 @@ __offtime (const time_t *t, long int offset, struct tm *tp)
   tp->tm_mday = days + 1;
   return 1;
 }
+
+/* Compute the `struct tm' representation of 64-bit-time *T,
+   offset OFFSET seconds east of UTC,
+   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
+   Return nonzero if successful.  */
+int
+__offtime64 (const __time64_t *t, long int offset, struct tm *tp)
+{
+  __time64_t days, rem, y;
+  const unsigned short int *ip;
+
+  days = *t / SECS_PER_DAY;
+  rem = *t % SECS_PER_DAY;
+  rem += offset;
+  while (rem < 0)
+    {
+      rem += SECS_PER_DAY;
+      --days;
+    }
+  while (rem >= SECS_PER_DAY)
+    {
+      rem -= SECS_PER_DAY;
+      ++days;
+    }
+  tp->tm_hour = rem / SECS_PER_HOUR;
+  rem %= SECS_PER_HOUR;
+  tp->tm_min = rem / 60;
+  tp->tm_sec = rem % 60;
+  /* January 1, 1970 was a Thursday.  */
+  tp->tm_wday = (4 + days) % 7;
+  if (tp->tm_wday < 0)
+    tp->tm_wday += 7;
+  y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+
+  while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+    {
+      /* Guess a corrected year, assuming 365 days per year.  */
+      __time64_t yg = y + days / 365 - (days % 365 < 0);
+
+      /* Adjust DAYS and Y to match the guessed year.  */
+      days -= ((yg - y) * 365
+	       + LEAPS_THRU_END_OF (yg - 1)
+	       - LEAPS_THRU_END_OF (y - 1));
+      y = yg;
+    }
+  tp->tm_year = y - 1900;
+  if (tp->tm_year != y - 1900)
+    {
+      /* The year cannot be represented due to overflow.  */
+      __set_errno (EOVERFLOW);
+      return 0;
+    }
+  tp->tm_yday = days;
+  ip = __mon_yday[__isleap(y)];
+  for (y = 11; days < (long int) ip[y]; --y)
+    continue;
+  days -= ip[y];
+  tp->tm_mon = y;
+  tp->tm_mday = days + 1;
+  return 1;
+}
diff --git a/time/time.h b/time/time.h
index 0fb1416..cd637bc 100644
--- a/time/time.h
+++ b/time/time.h
@@ -125,34 +125,78 @@ extern char *strptime_l (const char *__restrict __s,
 
 
 __BEGIN_NAMESPACE_STD
+
 /* 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;
+
 __END_NAMESPACE_STD
 
 #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 */
 
 __BEGIN_NAMESPACE_STD
+
 /* Return a string of the form "Day Mon dd hh:mm:ss yyyy\n"
    that is the representation of TP in this format.  */
 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;
+
 __END_NAMESPACE_STD
 
 #ifdef __USE_POSIX
@@ -164,6 +208,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 */
diff --git a/time/tzfile.c b/time/tzfile.c
index 3fd4569..9d1a0f6 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -637,7 +637,7 @@ __tzfile_default (const char *std, const char *dst,
 }
 
 void
-__tzfile_compute (time_t timer, int use_localtime,
+__tzfile_compute (__time64_t timer, int use_localtime,
 		  long int *leap_correct, int *leap_hit,
 		  struct tm *tp)
 {
@@ -692,7 +692,7 @@ __tzfile_compute (time_t timer, int use_localtime,
 
 	  /* Convert to broken down structure.  If this fails do not
 	     use the string.  */
-	  if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
+	  if (__glibc_unlikely (! __offtime64 (&timer, 0, tp)))
 	    goto use_last;
 
 	  /* Use the rules from the TZ string to compute the change.  */
diff --git a/time/tzset.c b/time/tzset.c
index eb42069..cd9df8f 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -61,7 +61,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;
 
@@ -451,7 +451,7 @@ tzset_internal (int always, int explicit)
       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 = (__time64_t) -1;
       update_vars ();
       return;
     }
@@ -550,10 +550,11 @@ compute_change (tz_rule *rule, int year)
 
 
 /* Figure out the correct timezone for TM and set `__tzname',
-   `__timezone', and `__daylight' accordingly.  */
+   `__timezone', and `__daylight' accordingly.
+   NOTE: this takes a __time64_t value, so passing a __time_t value is OK. */
 void
 internal_function
-__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);
@@ -654,6 +655,61 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
 }
 
 
+/* Return the `struct tm' representation of *TIMER in the local timezone.
+   Use local time if USE_LOCALTIME is nonzero, UTC otherwise.  */
+struct tm *
+__tz_convert64 (const __time64_t *timer, int use_localtime, struct tm *tp)
+{
+  long int leap_correction;
+  int leap_extra_secs;
+
+  if (timer == NULL)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
+  __libc_lock_lock (tzset_lock);
+
+  /* Update internal database according to current TZ setting.
+     POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
+     This is a good idea since this allows at least a bit more parallelism.  */
+  tzset_internal (tp == &_tmbuf && use_localtime, 1);
+
+  if (__use_tzfile)
+    __tzfile_compute (*timer, use_localtime, &leap_correction,
+		      &leap_extra_secs, tp);
+  else
+    {
+      if (! __offtime64 (timer, 0, tp))
+	tp = NULL;
+      else
+	__tz_compute (*timer, tp, use_localtime);
+      leap_correction = 0L;
+      leap_extra_secs = 0;
+    }
+
+  __libc_lock_unlock (tzset_lock);
+
+  if (tp)
+    {
+      if (! use_localtime)
+	{
+	  tp->tm_isdst = 0;
+	  tp->tm_zone = "GMT";
+	  tp->tm_gmtoff = 0L;
+	}
+
+      if (__offtime64 (timer, tp->tm_gmtoff - leap_correction, tp))
+        tp->tm_sec += leap_extra_secs;
+      else
+	tp = NULL;
+    }
+
+  return tp;
+}
+
+
 libc_freeres_fn (free_mem)
 {
   while (tzstring_list != NULL)

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

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

    Y2038: implement Y2038-proof difftime
    
    With -D_TIME_BITS=64, the 'difftime' API is implemented by
    function '__difftime64'.
    
    The API expects __time64_t arguments but returns a double like its
    32-bit-time counterpart, in order to remain as source-code-compatible
    as possible, even though the precision of a a double is only about 55
    bits.
    
    The implementation is simpler than its 32-bit counterpart, as it
    assumes that all __time64_t implementations are just 64-bit integers.
    
    Also, the implementation does not require a Y2038-proof kernel.

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 7e5ba53..d365576 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -16,4 +16,11 @@ libc {
     # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
     __vdso_clock_gettime;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __difftime64;
+  }
 }
diff --git a/time/difftime.c b/time/difftime.c
index e5e3311..1b2494c 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -119,3 +119,12 @@ __difftime (time_t time1, time_t time0)
   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
 }
 strong_alias (__difftime, difftime)
+
+/* Return the difference between 64-bit TIME1 and TIME0.  */
+double
+__difftime64 (__time64_t time1, __time64_t time0)
+{
+  /* Subtract the smaller integer from the larger, convert the difference to
+     double, and then negate if needed.  */
+  return time1 < time0 ? - (time0 - time1) : (time1 - time0);
+}
diff --git a/time/time.h b/time/time.h
index 7f98338..0fb1416 100644
--- a/time/time.h
+++ b/time/time.h
@@ -76,6 +76,14 @@ extern clock_t clock (void) __THROW;
 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__));
 

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

commit 419246d155840ce465210febf0a5109667fe55e8
Author: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Date:   Wed Feb 15 19:25:27 2017 +0100

    Y2038: make time_t Y2038-proof
    
    API type __time64_t is introduced as a 64-bit signed integer.
    
    Then, if _USE_TIME_BITS64 is defined, time_t is defined as __time64_t;
    otherwise, time_t is defined as __time_t.
    
    This allows the same user source code to use the same 'time_t' type
    and thus work with 32-bit time (default case) or with 64-bit time
    (-D_TIME_BITS=64) without any source-level change.
    
    ** NOTE **
    
    1.
    
    __USE_TIME_BITS64 is defined when _TIME_BITS is defined equal to 64.
    
    2.
    
    Defining _TIME_BITS=64 affects *all* API types derived from time_t,
    e.g. struct timeval, struct timespec etc: all time_t fields are now
    64-bit. This, in turn, means that most APIs are now inconsistent with
    their respective implementations. The rest of this series is about
    providing adequate 64-bit-time implementations.

diff --git a/bits/types.h b/bits/types.h
index 7638bd0..f5b2d42 100644
--- a/bits/types.h
+++ b/bits/types.h
@@ -145,7 +145,8 @@ __STD_TYPE __CLOCK_T_TYPE __clock_t;	/* Type of CPU usage counts.  */
 __STD_TYPE __RLIM_T_TYPE __rlim_t;	/* Type for resource measurement.  */
 __STD_TYPE __RLIM64_T_TYPE __rlim64_t;	/* Type for resource measurement (LFS).  */
 __STD_TYPE __ID_T_TYPE __id_t;		/* General type for IDs.  */
-__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch.  */
+__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch, Y2038-unsafe.  */
+__STD_TYPE __TIME64_T_TYPE __time64_t;	/* Seconds since the Epoch, Y2038-safe.  */
 __STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds.  */
 __STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds.  */
 
diff --git a/bits/typesizes.h b/bits/typesizes.h
index d407bf4..a916cc1 100644
--- a/bits/typesizes.h
+++ b/bits/typesizes.h
@@ -48,6 +48,7 @@
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/include/features.h b/include/features.h
index dc8ae79..cef60ac 100644
--- a/include/features.h
+++ b/include/features.h
@@ -356,6 +356,10 @@
 # define __USE_FILE_OFFSET64	1
 #endif
 
+#if defined _TIME_BITS && _TIME_BITS == 64
+# define __USE_TIME_BITS64	1
+#endif
+
 #if defined _DEFAULT_SOURCE
 # define __USE_MISC	1
 #endif
diff --git a/time/bits/types/time_t.h b/time/bits/types/time_t.h
index 16e5269..47ad649 100644
--- a/time/bits/types/time_t.h
+++ b/time/bits/types/time_t.h
@@ -5,7 +5,11 @@
 
 __BEGIN_NAMESPACE_STD
 /* Returned by `time'.  */
+#ifdef __USE_TIME_BITS64
+typedef __time64_t time_t;
+#else
 typedef __time_t time_t;
+#endif
 __END_NAMESPACE_STD
 #ifdef __USE_POSIX
 __USING_NAMESPACE_STD(time_t)

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


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]