[RFCv3] Add pthread_cond_timedwaitonclock_np
diff mbox

Message ID 1438884947-16358-1-git-send-email-mac@mcrowe.com
State New
Headers show

Commit Message

Mike Crowe Aug. 6, 2015, 6:15 p.m. UTC
C++11's std::condition_variable::wait_until specifies the clock to be
used at the time of the wait and permits separate waits on the same
instance using different clocks.

Unfortunately pthread_cond_timedwait always uses the clock that was
specified (or defaulted) when pthread_cond_init was called. libstdc++'s
current implementation converts all waits to
std::chrono::system_clock (i.e. CLOCK_REALTIME) which can race against
the system clock changing.

Inventing a brand-new function pthread_cond_timedwaitonclock_np which
accepts both the clock and the time point as parameters is
straightforward and means that the C++11 standard behaviour can be
implemented in libstdc++ on Linux at least.

(This patch is only to the C implementation of pthread_cond_timedwait so
it is necessary to remove pthread_cond_timedwait.S and
pthread_cond_wait.S to use it on x86 and x86_64 at the
moment. Apparently Torvald will be removing these soon anyway.)

Signed-off-by: Mike Crowe <mac@mcrowe.com>
---
 ChangeLog                                          |  79 ++++++++
 manual/threads.texi                                |  20 ++
 nptl/Makefile                                      |   4 +-
 nptl/Versions                                      |   7 +
 nptl/forward.c                                     |   5 +
 nptl/nptl-init.c                                   |   1 +
 nptl/pthreadP.h                                    |   4 +
 nptl/pthread_cond_timedwait.c                      |  26 ++-
 nptl/tst-cond11-onclock.c                          | 207 +++++++++++++++++++++
 nptl/tst-cond5-onclock.c                           | 114 ++++++++++++
 sysdeps/nacl/libpthread.abilist                    |   3 +
 sysdeps/nptl/pthread-functions.h                   |   4 +
 sysdeps/nptl/pthread.h                             |  15 ++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   3 +
 sysdeps/unix/sysv/linux/aarch64/libpthread.abilist |   3 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   3 +
 sysdeps/unix/sysv/linux/alpha/libpthread.abilist   |   3 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   3 +
 sysdeps/unix/sysv/linux/arm/libpthread.abilist     |   3 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   3 +
 sysdeps/unix/sysv/linux/hppa/libpthread.abilist    |   3 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   3 +
 sysdeps/unix/sysv/linux/i386/libpthread.abilist    |   3 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   3 +
 sysdeps/unix/sysv/linux/ia64/libpthread.abilist    |   3 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   3 +
 .../sysv/linux/m68k/coldfire/libpthread.abilist    |   3 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   3 +
 .../unix/sysv/linux/m68k/m680x0/libpthread.abilist |   3 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   3 +
 .../unix/sysv/linux/microblaze/libpthread.abilist  |   3 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   3 +
 .../unix/sysv/linux/mips/mips32/libpthread.abilist |   3 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   3 +
 .../unix/sysv/linux/mips/mips64/libpthread.abilist |   3 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   3 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   3 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   3 +
 sysdeps/unix/sysv/linux/nios2/libpthread.abilist   |   3 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   3 +
 .../linux/powerpc/powerpc32/libpthread.abilist     |   3 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   3 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   3 +
 .../linux/powerpc/powerpc64/libpthread.abilist     |   3 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   3 +
 .../sysv/linux/s390/s390-32/libpthread.abilist     |   3 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   3 +
 .../sysv/linux/s390/s390-64/libpthread.abilist     |   3 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   3 +
 sysdeps/unix/sysv/linux/sh/libpthread.abilist      |   3 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   3 +
 .../sysv/linux/sparc/sparc32/libpthread.abilist    |   3 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   3 +
 .../sysv/linux/sparc/sparc64/libpthread.abilist    |   3 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   3 +
 .../linux/tile/tilegx/tilegx32/libpthread.abilist  |   3 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   3 +
 .../linux/tile/tilegx/tilegx64/libpthread.abilist  |   3 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   3 +
 .../sysv/linux/tile/tilepro/libpthread.abilist     |   3 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   3 +
 .../unix/sysv/linux/x86_64/64/libpthread.abilist   |   3 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   3 +
 .../unix/sysv/linux/x86_64/x32/libpthread.abilist  |   3 +
 64 files changed, 632 insertions(+), 10 deletions(-)
 create mode 100644 nptl/tst-cond11-onclock.c
 create mode 100644 nptl/tst-cond5-onclock.c

Patch
diff mbox

diff --git a/ChangeLog b/ChangeLog
index 4f985f1..d52f0e4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,82 @@ 
+2015-08-05  Mike Crowe  <mac@mcrowe.com>
+
+	* sysdeps/nptl/pthread.h: Add pthread_cond_timedwaitonclock_np
+	declaration
+	* nptl/pthread_cond_timedwait.c:
+	(__pthread_cond_timedwaitonclock_np): Rename __pthread_cond_timedwait
+	to __pthread_cond_timedwaitonclock_np, add clockid_t parameter and
+	use it to determine which clock to use.
+	(__pthread_cond_timedwait): Call __pthread_cond_timedwaitonclock_np
+	using clock specified or defaulted during pthread_cond_init.
+	(pthread_cond_timdwaitonclock_np): Weak alias for
+	__pthread_cond_timedwaitonclock
+	* nptl/tst-cond5-onclock.c: New file to test
+	pthread_cond_timedwaitonclock_np
+	* nptl/tst-cond11-onclock.c: New file to test
+	pthread_cond_timedwaitonclock_np
+	* nptl/Makefile: Add tst-cond5-onclock and tst-cond11-onclock
+	* nptl/Versions (GLIBC_2.23): Add pthread_cond_timedwaitonclock_np
+	to both libc and libpthread
+	* nptl/pthread_functions.h: Add
+	ptr___pthread_cond_timedwaitonclock_np
+	* nptl/forward.c (pthread_functions): Forward
+	pthread_cond_timedwaitonclock_np from libc to libpthread3
+	* nptl/nptl-init.c: Forwarding function initialisation for
+	pthread_cond_timedwaitonclock_np
+	* nptl/pthreadP.h (__pthread_cond_timedwait_np): Add
+	* manual/threads.texi: Add documentation for
+	pthread_cond_timedwaitonclock_np
+	* sysdeps/nacl/libpthread.abilist(GLIBC_2.23): Add
+	pthread_cond_timedwaitonclock_np
+	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/arm/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/i386/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/mips/mips32/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/mips/mips64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/sh/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/tile/tilepro/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist: Likewise
+
 2015-08-05  H.J. Lu  <hongjiu.lu@intel.com>
 
 	[BZ #18661]
diff --git a/manual/threads.texi b/manual/threads.texi
index 4d080d4..58b302b 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -132,6 +132,26 @@  The system does not have sufficient memory.
 @end table
 @end deftypefun
 
+@comment pthread.h
+@comment GNU
+@deftypefun int pthread_cond_timedwaitonclock_np (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex},
+                                                  clockid_t @var{clockid}, const struct timespec *@var{abstime})
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock}}
+@c If exactly the same function with arguments is called from a signal
+@c handler that interrupts between the mutex unlock and sleep then it
+@c will unlock the mutex twice resulting in undefined behaviour. Keep
+@c in mind that the unlock and sleep are only atomic with respect to other
+@c threads (really a happens-after relationship for pthread_cond_broadcast
+@c and pthread_cond_signal).
+@c In the AC case we would cancel the thread and the mutex would remain
+@c locked and we can't recover from that.
+Behaves like POSIX @code{pthread_cond_timedwait} except the time
+@var{abstime} is measured against the clock specified by @var{clockid}
+rather than the clock specified or defaulted when @code{pthread_cond_init}
+was called. This variant is necessary in order to implement C++11's
+@code{std::condition_variable::wait_until} method correctly.
+@end deftypefun
+
 @c FIXME these are undocumented:
 @c pthread_atfork
 @c pthread_attr_destroy
diff --git a/nptl/Makefile b/nptl/Makefile
index aaca0a4..2bbda28 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -221,8 +221,8 @@  tests = tst-typesizes \
 	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
 	tst-mutexpi9 \
 	tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
-	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
-	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
+	tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond5-onclock tst-cond6 tst-cond7 \
+	tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond11-onclock tst-cond12 tst-cond13 \
 	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
 	tst-cond20 tst-cond21 tst-cond22 tst-cond23 tst-cond24 tst-cond25 \
 	tst-cond-except \
diff --git a/nptl/Versions b/nptl/Versions
index 34e4b46..d0e63e5 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -28,6 +28,9 @@  libc {
     pthread_cond_wait; pthread_cond_signal;
     pthread_cond_broadcast; pthread_cond_timedwait;
   }
+  GLIBC_2.23 {
+    pthread_cond_timedwaitonclock_np;
+  }
   GLIBC_PRIVATE {
     __libc_alloca_cutoff;
     # Internal libc interface to libpthread
@@ -269,6 +272,10 @@  libpthread {
   GLIBC_2.22 {
   }
 
+  GLIBC_2.23 {
+    pthread_cond_timedwaitonclock_np;
+  }
+
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
     __pthread_clock_gettime; __pthread_clock_settime;
diff --git a/nptl/forward.c b/nptl/forward.c
index db74f8d..e88ee56 100644
--- a/nptl/forward.c
+++ b/nptl/forward.c
@@ -164,6 +164,11 @@  FORWARD (__pthread_cond_timedwait,
 	  const struct timespec *abstime), (cond, mutex, abstime), 0)
 versioned_symbol (libc, __pthread_cond_timedwait, pthread_cond_timedwait,
 		  GLIBC_2_3_2);
+FORWARD (__pthread_cond_timedwaitonclock_np,
+	 (pthread_cond_t *cond, pthread_mutex_t *mutex, clockid_t clockid,
+	  const struct timespec *abstime), (cond, mutex, clockid, abstime),
+	 0)
+weak_alias (__pthread_cond_timedwaitonclock_np, pthread_cond_timedwaitonclock_np);
 
 
 FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index c043fb5..04ec178 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -110,6 +110,7 @@  static const struct pthread_functions pthread_functions =
     .ptr___pthread_cond_signal = __pthread_cond_signal,
     .ptr___pthread_cond_wait = __pthread_cond_wait,
     .ptr___pthread_cond_timedwait = __pthread_cond_timedwait,
+    .ptr___pthread_cond_timedwaitonclock_np = __pthread_cond_timedwaitonclock_np,
 # if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
     .ptr___pthread_cond_broadcast_2_0 = __pthread_cond_broadcast_2_0,
     .ptr___pthread_cond_destroy_2_0 = __pthread_cond_destroy_2_0,
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 8cd51c6..fbb0cb0 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -474,6 +474,10 @@  extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
 extern int __pthread_cond_timedwait (pthread_cond_t *cond,
 				     pthread_mutex_t *mutex,
 				     const struct timespec *abstime);
+extern int __pthread_cond_timedwaitonclock_np (pthread_cond_t *cond,
+					       pthread_mutex_t *mutex,
+					       clockid_t clockid,
+					       const struct timespec *abstime);
 extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
 extern int __pthread_condattr_init (pthread_condattr_t *attr);
 extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *));
diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c
index 10b0a61..df12673 100644
--- a/nptl/pthread_cond_timedwait.c
+++ b/nptl/pthread_cond_timedwait.c
@@ -49,8 +49,9 @@  struct _condvar_cleanup_buffer
 };
 
 int
-__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
-			  const struct timespec *abstime)
+__pthread_cond_timedwaitonclock_np (pthread_cond_t *cond, pthread_mutex_t *mutex,
+				    clockid_t clockid,
+				    const struct timespec *abstime)
 {
   struct _pthread_cleanup_buffer buffer;
   struct _condvar_cleanup_buffer cbuffer;
@@ -120,8 +121,7 @@  __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
 # ifdef __NR_clock_gettime
 	INTERNAL_SYSCALL_DECL (err);
 	(void) INTERNAL_VSYSCALL (clock_gettime, err, 2,
-				  (cond->__data.__nwaiters
-				   & ((1 << COND_NWAITERS_SHIFT) - 1)),
+				  clockid,
 				  &rt);
 	/* Convert the absolute timeout value to a relative timeout.  */
 	rt.tv_sec = abstime->tv_sec - rt.tv_sec;
@@ -175,8 +175,7 @@  __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
 
       if (pi_flag)
 	{
-	  unsigned int clockbit = (cond->__data.__nwaiters & 1
-				   ? 0 : FUTEX_CLOCK_REALTIME);
+	  unsigned int clockbit = clockid ? 0 : FUTEX_CLOCK_REALTIME;
 	  err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex,
 						 futex_val, abstime, clockbit,
 						 &mutex->__data.__lock,
@@ -193,8 +192,7 @@  __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	  err = lll_futex_timed_wait (&cond->__data.__futex,
 				      futex_val, &rt, pshared);
 #else
-	  unsigned int clockbit = (cond->__data.__nwaiters & 1
-				   ? 0 : FUTEX_CLOCK_REALTIME);
+	  unsigned int clockbit = clockid ? 0 : FUTEX_CLOCK_REALTIME;
 	  err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val,
 					     abstime, clockbit, pshared);
 #endif
@@ -264,5 +262,17 @@  __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
   return err ?: result;
 }
 
+weak_alias (__pthread_cond_timedwaitonclock_np, pthread_cond_timedwaitonclock_np);
+
+int
+__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
+			  const struct timespec *abstime)
+{
+    return __pthread_cond_timedwaitonclock_np (cond, mutex,
+					       (cond->__data.__nwaiters
+						& ((1 << COND_NWAITERS_SHIFT) - 1)),
+					       abstime);
+}
+
 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 		  GLIBC_2_3_2);
diff --git a/nptl/tst-cond11-onclock.c b/nptl/tst-cond11-onclock.c
new file mode 100644
index 0000000..a7a15d7
--- /dev/null
+++ b/nptl/tst-cond11-onclock.c
@@ -0,0 +1,207 @@ 
+/* Test pthread_cond_timedwaitonclock_np, based on tst-cond11.c
+   Copyright (C) 2003-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Mike Crowe <mac@mcrowe.com>, 2015.
+
+   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 <pthread.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
+static int
+run_test (clockid_t attr_clock, clockid_t wait_clock)
+{
+  pthread_condattr_t condattr;
+  pthread_cond_t cond;
+  pthread_mutexattr_t mutattr;
+  pthread_mutex_t mut;
+
+  printf ("attr_clock = %d, wait_clock = %d\n", (int) attr_clock, (int) wait_clock);
+
+  if (pthread_condattr_init (&condattr) != 0)
+    {
+      puts ("condattr_init failed");
+      return 1;
+    }
+
+  if (pthread_condattr_setclock (&condattr, attr_clock) != 0)
+    {
+      puts ("condattr_setclock failed");
+      return 1;
+    }
+
+  clockid_t cl2;
+  if (pthread_condattr_getclock (&condattr, &cl2) != 0)
+    {
+      puts ("condattr_getclock failed");
+      return 1;
+    }
+  if (attr_clock != cl2)
+    {
+      printf ("condattr_getclock returned wrong value: %d, expected %d\n",
+	      (int) cl2, (int) attr_clock);
+      return 1;
+    }
+
+  if (pthread_cond_init (&cond, &condattr) != 0)
+    {
+      puts ("cond_init failed");
+      return 1;
+    }
+
+  if (pthread_condattr_destroy (&condattr) != 0)
+    {
+      puts ("condattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_init (&mutattr) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (&mut, &mutattr) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&mutattr) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&mut) != EDEADLK)
+    {
+      puts ("2nd mutex_lock did not return EDEADLK");
+      return 1;
+    }
+
+  struct timespec ts;
+  if (clock_gettime (wait_clock, &ts) != 0)
+    {
+      puts ("clock_gettime failed");
+      return 1;
+    }
+
+  /* Wait one second.  */
+  ++ts.tv_sec;
+
+  int e = pthread_cond_timedwaitonclock_np (&cond, &mut, wait_clock, &ts);
+  if (e == 0)
+    {
+      puts ("cond_timedwait succeeded");
+      return 1;
+    }
+  else if (e != ETIMEDOUT)
+    {
+      puts ("cond_timedwait did not return ETIMEDOUT");
+      return 1;
+    }
+
+  struct timespec ts2;
+  if (clock_gettime (wait_clock, &ts2) != 0)
+    {
+      puts ("second clock_gettime failed");
+      return 1;
+    }
+
+  if (ts2.tv_sec < ts.tv_sec
+      || (ts2.tv_sec == ts.tv_sec && ts2.tv_nsec < ts.tv_nsec))
+    {
+      puts ("timeout too short");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&mut) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  if (pthread_cond_destroy (&cond) != 0)
+    {
+      puts ("cond_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+#endif
+
+
+static int
+do_test (void)
+{
+#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
+
+  puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
+  return 0;
+
+#else
+
+  int res = run_test (CLOCK_REALTIME, CLOCK_REALTIME);
+
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+#  if _POSIX_MONOTONIC_CLOCK == 0
+  int e = sysconf (_SC_MONOTONIC_CLOCK);
+  if (e < 0)
+    puts ("CLOCK_MONOTONIC not supported");
+  else if (e == 0)
+    {
+      puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
+      res = 1;
+    }
+  else
+#  endif
+    res |= run_test (CLOCK_REALTIME, CLOCK_MONOTONIC);
+    res |= run_test (CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+    res |= run_test (CLOCK_MONOTONIC, CLOCK_REALTIME);
+# else
+  puts ("_POSIX_MONOTONIC_CLOCK not defined");
+# endif
+
+  return res;
+#endif
+}
+
+#define TIMEOUT 12
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/nptl/tst-cond5-onclock.c b/nptl/tst-cond5-onclock.c
new file mode 100644
index 0000000..6ca8562
--- /dev/null
+++ b/nptl/tst-cond5-onclock.c
@@ -0,0 +1,114 @@ 
+/* Test pthread_cond_timedwaitonclock_np, based on tst-cond5.c
+   Copyright (C) 2002-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Mike Crowe <mac@mcrowe.com>, 2015.
+
+   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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+static pthread_mutex_t mut;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+
+static int
+do_test_onclock(clockid_t clockid)
+{
+  pthread_mutexattr_t ma;
+  int err;
+  struct timespec ts;
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_init (&mut, &ma) != 0)
+    {
+      puts ("mutex_init failed");
+      exit (1);
+    }
+
+  /* Get the mutex.  */
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  /* Waiting for the condition will fail.  But we want the timeout here.  */
+  if (clock_gettime (clockid, &ts) != 0)
+    {
+      puts ("clock_gettime failed");
+      exit (1);
+    }
+
+  ts.tv_nsec += 500000000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ts.tv_nsec -= 1000000000;
+      ++ts.tv_sec;
+    }
+  err = pthread_cond_timedwaitonclock_np (&cond, &mut, clockid, &ts);
+  if (err == 0)
+    {
+      /* This could in theory happen but here without any signal and
+	 additional waiter it should not.  */
+      puts ("cond_timedwait succeeded");
+      exit (1);
+    }
+  else if (err != ETIMEDOUT)
+    {
+      printf ("cond_timedwait returned with %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    {
+      printf ("mutex_unlock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  int rc;
+  rc = do_test_onclock(CLOCK_MONOTONIC);
+  if (rc == 0)
+    rc = do_test_onclock(CLOCK_REALTIME);
+
+  return rc;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/nacl/libpthread.abilist b/sysdeps/nacl/libpthread.abilist
index 6c5e70d..5fa66c0 100644
--- a/sysdeps/nacl/libpthread.abilist
+++ b/sysdeps/nacl/libpthread.abilist
@@ -174,3 +174,6 @@  GLIBC_2.22
  sem_trywait F
  sem_unlink F
  sem_wait F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/nptl/pthread-functions.h b/sysdeps/nptl/pthread-functions.h
index 0784c59..71f8287 100644
--- a/sysdeps/nptl/pthread-functions.h
+++ b/sysdeps/nptl/pthread-functions.h
@@ -55,6 +55,10 @@  struct pthread_functions
   int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
   int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *,
 				       const struct timespec *);
+  int (*ptr___pthread_cond_timedwaitonclock_np) (pthread_cond_t *,
+						 pthread_mutex_t *,
+						 clockid_t,
+						 const struct timespec *);
   int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *);
   int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *);
   int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *,
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index 89d0882..a59bf0c 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1002,6 +1002,21 @@  extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
 				   const struct timespec *__restrict __abstime)
      __nonnull ((1, 2, 3));
 
+#ifdef __USE_GNU
+/* Wait for condition variable COND to be signaled or broadcast until
+   ABSTIME measured by the specified clock. MUTEX is assumed to be
+   locked before. CLOCK is the clock to use. ABSTIME is an absolute
+   time specification against CLOCK's epoch.
+
+   This function is a cancellation point and therefore not marked with
+   __THROW. */
+extern int pthread_cond_timedwaitonclock_np (pthread_cond_t *__restrict __cond,
+					     pthread_mutex_t *__restrict __mutex,
+					     __clockid_t __clock_id,
+					     const struct timespec *__restrict __abstime)
+     __nonnull ((1, 2, 4));
+#endif
+
 /* Functions for handling condition variable attributes.  */
 
 /* Initialize condition variable attribute ATTR.  */
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 3e0f329..169c5c3 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2084,3 +2084,6 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
index 5520312..998a164 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
@@ -226,3 +226,6 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 58c8b32..0b05dfb 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -1825,6 +1825,9 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
index 4c75b17..eaf6cc0 100644
--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
@@ -226,6 +226,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index f2b20ad..dc04a7a 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -92,6 +92,9 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index ac46302..6ff44ac 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -12,6 +12,9 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.4
  GLIBC_2.4 A
  _IO_flockfile F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index cf0ad90..00b0712 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -98,6 +98,9 @@  GLIBC_2.19
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
index 6613c09..ad6d5fd 100644
--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
@@ -210,6 +210,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index fcf1b72..6587b12 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2026,6 +2026,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index 865364e..ea90f3f 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -226,6 +226,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 16c2e3d..fce8f36 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
index a84c113..e92fc78 100644
--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
@@ -210,6 +210,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 902b0c3..17b19ee 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -93,6 +93,9 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index ac46302..6ff44ac 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -12,6 +12,9 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.4
  GLIBC_2.4 A
  _IO_flockfile F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 4db00b0..cc010ed 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1982,6 +1982,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
index 865364e..ea90f3f 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -226,6 +226,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index f1f76a1..003dc76 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2083,3 +2083,6 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
index f25407d..2625fe9 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
@@ -224,3 +224,6 @@  GLIBC_2.18
  wait F
  waitpid F
  write F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 2d51989..555bf5a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1954,6 +1954,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
index 00ad3ab..105811a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
@@ -220,6 +220,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index b012bdf..2d83e83 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1952,6 +1952,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
index fdcd0cc..4af1a92 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
@@ -220,6 +220,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 9db0e8b..397c788 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1950,6 +1950,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index eecfcfe..46886ae 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1944,6 +1944,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index b10bf62..988c21e 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2124,3 +2124,6 @@  GLIBC_2.21
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
index ca203c7..6625d24 100644
--- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
@@ -222,3 +222,6 @@  GLIBC_2.21
  wait F
  waitpid F
  write F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 0f15463..8f5543d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1986,6 +1986,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index c8a2a04..5686d12 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -226,6 +226,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 7bcaa07..74b6717 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1992,6 +1992,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index e58a00d..51f94cd 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -93,6 +93,9 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist
index 0faa1b8..d31efcb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist
@@ -12,6 +12,9 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  _IO_flockfile F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 0ce7824..5079565 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1987,6 +1987,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
index 699de01..23c2c2a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
@@ -230,6 +230,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index dc79912..4bb7114 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1883,6 +1883,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
index 51a8a7f..8923a89 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
@@ -214,6 +214,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 9ed1b45..35ef7ac 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1867,6 +1867,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
index 6613c09..ad6d5fd 100644
--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
@@ -210,6 +210,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5a40ff3..96c0ba5 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1978,6 +1978,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
index 4c75b17..eaf6cc0 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
@@ -226,6 +226,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index fa70645..b4284dd 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1911,6 +1911,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
index a84c113..e92fc78 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
@@ -210,6 +210,9 @@  GLIBC_2.2.3
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index dd215d7..c26835a 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2094,3 +2094,6 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libpthread.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libpthread.abilist
index f3c2600..0ca63d9 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libpthread.abilist
@@ -226,3 +226,6 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index ef4747a..ce7167e 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2094,3 +2094,6 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libpthread.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libpthread.abilist
index f3c2600..0ca63d9 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libpthread.abilist
@@ -226,3 +226,6 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index dd215d7..c26835a 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2094,3 +2094,6 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libpthread.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libpthread.abilist
index f3c2600..0ca63d9 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libpthread.abilist
@@ -226,3 +226,6 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index b377b04..3095585 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1857,6 +1857,9 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 1b5192b..67f9ffa 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -208,6 +208,9 @@  GLIBC_2.2.5
 GLIBC_2.2.6
  GLIBC_2.2.6 A
  __nanosleep F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2
  GLIBC_2.3.2 A
  pthread_cond_broadcast F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 5f70329..ba1cf8f 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2092,3 +2092,6 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index 328f69a..46c4219 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -226,3 +226,6 @@  GLIBC_2.18
  GLIBC_2.18 A
  pthread_getattr_default_np F
  pthread_setattr_default_np F
+GLIBC_2.23
+ GLIBC_2.23 A
+ pthread_cond_timedwaitonclock_np F