unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [RFCv4] Add pthread_cond_timedwaitonclock_np
@ 2017-06-22 17:05 Mike Crowe
  2017-06-28 14:39 ` Adhemerval Zanella
  0 siblings, 1 reply; 9+ messages in thread
From: Mike Crowe @ 2017-06-22 17:05 UTC (permalink / raw)
  To: libc-alpha; +Cc: Mike Crowe

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 condition
variable 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.

Let's invent 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.

Earlier versions of this patch were proposed in 2015 but further progress
stalled waiting for the assembly implementation of pthread_cond_timedwait.S
to be removed by Torvald Riegel. This happened in
ed19993b5b0d05d62cc883571519a67dae481a14.

See the following threads for previous versions and discussion:

* https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
* https://sourceware.org/ml/libc-alpha/2015-08/msg00186.html
* https://sourceware.org/ml/libc-alpha/2015-08/msg00230.html

Some of the abilist updates for other architectures appear to have gone
missing during the rebase. If this change is reviewed favourably then I
shall try to include them.

Signed-off-by: Mike Crowe <mac@mcrowe.com>
---
 ChangeLog                                          |  48 +++++
 manual/threads.texi                                |  21 +++
 nptl/Makefile                                      |   4 +-
 nptl/Versions                                      |   7 +
 nptl/forward.c                                     |   5 +
 nptl/nptl-init.c                                   |   1 +
 nptl/pthreadP.h                                    |   4 +
 nptl/pthread_cond_wait.c                           |  28 ++-
 nptl/tst-cond11-onclock.c                          | 209 +++++++++++++++++++++
 nptl/tst-cond5-onclock.c                           | 114 +++++++++++
 sysdeps/nptl/pthread-functions.h                   |   4 +
 sysdeps/nptl/pthread.h                             |  15 ++
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   1 +
 sysdeps/unix/sysv/linux/arm/libpthread.abilist     |   1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   1 +
 sysdeps/unix/sysv/linux/i386/libpthread.abilist    |   1 +
 .../sysv/linux/m68k/coldfire/libpthread.abilist    |   1 +
 .../unix/sysv/linux/m68k/m680x0/libpthread.abilist |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   1 +
 .../unix/sysv/linux/x86_64/64/libpthread.abilist   |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   1 +
 .../unix/sysv/linux/x86_64/x32/libpthread.abilist  |   1 +
 22 files changed, 466 insertions(+), 5 deletions(-)
 create mode 100644 nptl/tst-cond11-onclock.c
 create mode 100644 nptl/tst-cond5-onclock.c

diff --git a/ChangeLog b/ChangeLog
index 46a70ff7ce..385deb472f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+2017-06-22  Mike Crowe  <mac@mcrowe.com>
+
+	* sysdeps/nptl/pthread.h: Add pthread_cond_timedwaitonclock_np
+	declaration
+	* nptl/pthread_cond.c:
+	(__pthread_cond_wait_common): Add clockid parameter to determine
+	which clock to use.
+	(__pthread_cond_wait): Add dummy clockid parameter when calling
+	__pthread_cond_wait_common.
+	(__pthread_cond_timedwait): Read default clock set during
+	pthread_cond_init to supply as clockid parameter in call to
+	__pthread_cond_wait_common.
+	(__pthread_cond_timedwaitonclock_np): New function that supports
+	specifying clock to use at call time rather than initialisation
+	time.
+	(pthread_cond_timdwaitonclock_np): Weak alias for
+	__pthread_cond_timedwaitonclock_np
+	* 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.26): 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/unix/sysv/linux/aarch64/libc.abilist: Add
+	pthread_cond_timedwaitonclock_np
+	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/arm/libpthread.abilist: Likewise
+	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise
+	* sysdeps/unix/sysv/linux/i386/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/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
+
 2017-06-21  Florian Weimer  <fweimer@redhat.com>
 
 	* intl/loadmsgcat.c: Remove alloca support.
diff --git a/manual/threads.texi b/manual/threads.texi
index 769d974d50..8b3652c859 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -124,6 +124,27 @@ 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. Currently, @code{clockid} must be either @code{CLOCK_MONOTONIC}
+or @code{CLOCK_REALTIME}. 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 853da72e74..8cf661dc64 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -235,8 +235,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
 	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 0ae5def464..1cf8c2fbad 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.26 {
+    pthread_cond_timedwaitonclock_np;
+  }
   GLIBC_PRIVATE {
     __libc_alloca_cutoff;
     # Internal libc interface to libpthread
@@ -265,6 +268,10 @@ libpthread {
   GLIBC_2.22 {
   }
 
+  GLIBC_2.26 {
+    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 ac96765f29..c5fcb2f066 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 29216077a2..b913515fe9 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -106,6 +106,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 7fc1e50f78..c7e7587479 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -488,6 +488,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_wait.c b/nptl/pthread_cond_wait.c
index 7812b94a3a..d0166b86d5 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -378,6 +378,7 @@ __condvar_cleanup_waiting (void *arg)
 */
 static __always_inline int
 __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    clockid_t clockid,
     const struct timespec *abstime)
 {
   const int maxspin = 0;
@@ -510,7 +511,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	      if (__glibc_unlikely (abstime->tv_sec < 0))
 	        err = ETIMEDOUT;
 
-	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
+	      else if (clockid == CLOCK_MONOTONIC)
 		{
 		  /* CLOCK_MONOTONIC is requested.  */
 		  struct timespec rt;
@@ -652,7 +653,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 int
 __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
-  return __pthread_cond_wait_common (cond, mutex, NULL);
+  return __pthread_cond_wait_common (cond, mutex, CLOCK_REALTIME, NULL);
 }
 
 /* See __pthread_cond_wait_common.  */
@@ -664,10 +665,31 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
      it can assume that abstime is not NULL.  */
   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
     return EINVAL;
-  return __pthread_cond_wait_common (cond, mutex, abstime);
+
+  clockid_t clockid = ((cond->__data.__wrefs & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
+  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
+}
+
+/* See __pthread_cond_wait_common.  */
+int
+__pthread_cond_timedwaitonclock_np (pthread_cond_t *cond, pthread_mutex_t *mutex,
+				    clockid_t clockid,
+				    const struct timespec *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;
+
+  /* We only support CLOCK_REALTIME and CLOCK_MONOTONIC */
+  if (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC)
+    return EINVAL;
+
+  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
 }
 
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 		  GLIBC_2_3_2);
 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
 		  GLIBC_2_3_2);
+weak_alias (__pthread_cond_timedwaitonclock_np, pthread_cond_timedwaitonclock_np);
diff --git a/nptl/tst-cond11-onclock.c b/nptl/tst-cond11-onclock.c
new file mode 100644
index 0000000000..439cd404de
--- /dev/null
+++ b/nptl/tst-cond11-onclock.c
@@ -0,0 +1,209 @@
+/* Test pthread_cond_timedwaitonclock_np, based on tst-cond11.c
+   Copyright (C) 2003-2017 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 0000000000..adb3342781
--- /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-2017 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/nptl/pthread-functions.h b/sysdeps/nptl/pthread-functions.h
index 4006fc6c25..8225fdbfca 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 632ea7bc36..e95df8f592 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1003,6 +1003,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/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index d2a206a8df..b0ecb71d3b 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -101,6 +101,7 @@ GLIBC_2.25 strfroml F
 GLIBC_2.26 GLIBC_2.26 A
 GLIBC_2.26 preadv2 F
 GLIBC_2.26 preadv64v2 F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.26 pwritev2 F
 GLIBC_2.26 pwritev64v2 F
 GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index 91545c1542..32b3331c19 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -9,6 +9,7 @@ GLIBC_2.12 pthread_setname_np F
 GLIBC_2.18 GLIBC_2.18 A
 GLIBC_2.18 pthread_getattr_default_np F
 GLIBC_2.18 pthread_setattr_default_np F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 2ff1998ac9..1bcf512fa1 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2023,6 +2023,7 @@ GLIBC_2.25 strfroml F
 GLIBC_2.26 GLIBC_2.26 A
 GLIBC_2.26 preadv2 F
 GLIBC_2.26 preadv64v2 F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.26 pwritev2 F
 GLIBC_2.26 pwritev64v2 F
 GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index 8f9c3254be..3ae0e37475 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -216,6 +216,7 @@ GLIBC_2.2.3 GLIBC_2.2.3 A
 GLIBC_2.2.3 pthread_getattr_np F
 GLIBC_2.2.6 GLIBC_2.2.6 A
 GLIBC_2.2.6 __nanosleep F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2 GLIBC_2.3.2 A
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index 91545c1542..32b3331c19 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -9,6 +9,7 @@ GLIBC_2.12 pthread_setname_np F
 GLIBC_2.18 GLIBC_2.18 A
 GLIBC_2.18 pthread_getattr_default_np F
 GLIBC_2.18 pthread_setattr_default_np F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
index 8f9c3254be..3ae0e37475 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -216,6 +216,7 @@ GLIBC_2.2.3 GLIBC_2.2.3 A
 GLIBC_2.2.3 pthread_getattr_np F
 GLIBC_2.2.6 GLIBC_2.2.6 A
 GLIBC_2.2.6 __nanosleep F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2 GLIBC_2.3.2 A
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 513524d932..13f13e04db 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1864,6 +1864,7 @@ GLIBC_2.25 strfroml F
 GLIBC_2.26 GLIBC_2.26 A
 GLIBC_2.26 preadv2 F
 GLIBC_2.26 preadv64v2 F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.26 pwritev2 F
 GLIBC_2.26 pwritev64v2 F
 GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 85365c057c..accb1d8d6f 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -203,6 +203,8 @@ GLIBC_2.2.5 waitpid F
 GLIBC_2.2.5 write F
 GLIBC_2.2.6 GLIBC_2.2.6 A
 GLIBC_2.2.6 __nanosleep F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.3.2 GLIBC_2.3.2 A
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 0c557e9f43..db930f6307 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2107,6 +2107,7 @@ GLIBC_2.25 strfroml F
 GLIBC_2.26 GLIBC_2.26 A
 GLIBC_2.26 preadv2 F
 GLIBC_2.26 preadv64v2 F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
 GLIBC_2.26 pwritev2 F
 GLIBC_2.26 pwritev64v2 F
 GLIBC_2.26 reallocarray F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index 6cd0fc3487..d89762bd33 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -224,3 +224,4 @@ GLIBC_2.16 write F
 GLIBC_2.18 GLIBC_2.18 A
 GLIBC_2.18 pthread_getattr_default_np F
 GLIBC_2.18 pthread_setattr_default_np F
+GLIBC_2.26 pthread_cond_timedwaitonclock_np F
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [RFCv4] Add pthread_cond_timedwaitonclock_np
  2017-06-22 17:05 [RFCv4] Add pthread_cond_timedwaitonclock_np Mike Crowe
@ 2017-06-28 14:39 ` Adhemerval Zanella
  2017-09-21 20:43   ` Mike Crowe
  2017-09-30 16:01   ` Mike Crowe
  0 siblings, 2 replies; 9+ messages in thread
From: Adhemerval Zanella @ 2017-06-28 14:39 UTC (permalink / raw)
  To: libc-alpha; +Cc: Torvald Riegel, Rich Felker



On 22/06/2017 14:05, Mike Crowe wrote:
> 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 condition
> variable 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.
> 
> Let's invent 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.
> 
> Earlier versions of this patch were proposed in 2015 but further progress
> stalled waiting for the assembly implementation of pthread_cond_timedwait.S
> to be removed by Torvald Riegel. This happened in
> ed19993b5b0d05d62cc883571519a67dae481a14.
> 
> See the following threads for previous versions and discussion:
> 
> * https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
> * https://sourceware.org/ml/libc-alpha/2015-08/msg00186.html
> * https://sourceware.org/ml/libc-alpha/2015-08/msg00230.html
> 
> Some of the abilist updates for other architectures appear to have gone
> missing during the rebase. If this change is reviewed favourably then I
> shall try to include them.

I think it is a reasonable addition, however I have some concerns if this
would just another bad discussed ABI to fix and specific issues that will
be replaced by another better or simple solution (as your last comment in
BZ#41861 [1]).  It also concerns that it was not brought to Austin Group
attention as suggested by Szabolcs [2].

Torvald, do you think a new API to specific a clock is a reasonable addition
for GLIBC? Rich, any thought about this new API (any possible musl inclusion
in nearby future in case of glibc acceptance)? Do you think we should
approach Austin Group first? The issue with C++ seems to a QoI one that is
currently defined afaik as implementation-defined, so it would be an
enhancement

The patch itself has some minor issues about formatting that I outlined
below.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861
[2] https://sourceware.org/ml/libc-alpha/2015-07/msg00194.html

> 
> Signed-off-by: Mike Crowe <mac@mcrowe.com>
> ---
>  ChangeLog                                          |  48 +++++
>  manual/threads.texi                                |  21 +++
>  nptl/Makefile                                      |   4 +-
>  nptl/Versions                                      |   7 +
>  nptl/forward.c                                     |   5 +
>  nptl/nptl-init.c                                   |   1 +
>  nptl/pthreadP.h                                    |   4 +
>  nptl/pthread_cond_wait.c                           |  28 ++-
>  nptl/tst-cond11-onclock.c                          | 209 +++++++++++++++++++++
>  nptl/tst-cond5-onclock.c                           | 114 +++++++++++
>  sysdeps/nptl/pthread-functions.h                   |   4 +
>  sysdeps/nptl/pthread.h                             |  15 ++
>  sysdeps/unix/sysv/linux/arm/libc.abilist           |   1 +
>  sysdeps/unix/sysv/linux/arm/libpthread.abilist     |   1 +
>  sysdeps/unix/sysv/linux/i386/libc.abilist          |   1 +
>  sysdeps/unix/sysv/linux/i386/libpthread.abilist    |   1 +
>  .../sysv/linux/m68k/coldfire/libpthread.abilist    |   1 +
>  .../unix/sysv/linux/m68k/m680x0/libpthread.abilist |   1 +
>  sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   1 +
>  .../unix/sysv/linux/x86_64/64/libpthread.abilist   |   2 +
>  sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   1 +
>  .../unix/sysv/linux/x86_64/x32/libpthread.abilist  |   1 +
>  22 files changed, 466 insertions(+), 5 deletions(-)
>  create mode 100644 nptl/tst-cond11-onclock.c
>  create mode 100644 nptl/tst-cond5-onclock.c
> 
> diff --git a/ChangeLog b/ChangeLog
> index 46a70ff7ce..385deb472f 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,51 @@
> +2017-06-22  Mike Crowe  <mac@mcrowe.com>
> +
> +	* sysdeps/nptl/pthread.h: Add pthread_cond_timedwaitonclock_np
> +	declaration
> +	* nptl/pthread_cond.c:
> +	(__pthread_cond_wait_common): Add clockid parameter to determine
> +	which clock to use.
> +	(__pthread_cond_wait): Add dummy clockid parameter when calling
> +	__pthread_cond_wait_common.
> +	(__pthread_cond_timedwait): Read default clock set during
> +	pthread_cond_init to supply as clockid parameter in call to
> +	__pthread_cond_wait_common.
> +	(__pthread_cond_timedwaitonclock_np): New function that supports
> +	specifying clock to use at call time rather than initialisation
> +	time.
> +	(pthread_cond_timdwaitonclock_np): Weak alias for
> +	__pthread_cond_timedwaitonclock_np
> +	* 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.26): 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/unix/sysv/linux/aarch64/libc.abilist: Add
> +	pthread_cond_timedwaitonclock_np
> +	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise
> +	* sysdeps/unix/sysv/linux/arm/libpthread.abilist: Likewise
> +	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise
> +	* sysdeps/unix/sysv/linux/i386/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/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
> +
>  2017-06-21  Florian Weimer  <fweimer@redhat.com>
>  
>  	* intl/loadmsgcat.c: Remove alloca support.
> diff --git a/manual/threads.texi b/manual/threads.texi
> index 769d974d50..8b3652c859 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -124,6 +124,27 @@ 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. Currently, @code{clockid} must be either @code{CLOCK_MONOTONIC}
> +or @code{CLOCK_REALTIME}. This variant is necessary in order to implement
> +C++11's @code{std::condition_variable::wait_until} method correctly.
> +@end deftypefun

I think we can't omit the C++11 requirement on manual.


> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy
> diff --git a/nptl/Makefile b/nptl/Makefile
> index 853da72e74..8cf661dc64 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -235,8 +235,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
>  	tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
>  	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 \

Line too long, split in multiple ones.

>  	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 0ae5def464..1cf8c2fbad 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.26 {
> +    pthread_cond_timedwaitonclock_np;
> +  }

The libc addition seems wrong, whhy this is required?

>    GLIBC_PRIVATE {
>      __libc_alloca_cutoff;
>      # Internal libc interface to libpthread
> @@ -265,6 +268,10 @@ libpthread {
>    GLIBC_2.22 {
>    }
>  
> +  GLIBC_2.26 {
> +    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 ac96765f29..c5fcb2f066 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 29216077a2..b913515fe9 100644
> --- a/nptl/nptl-init.c
> +++ b/nptl/nptl-init.c
> @@ -106,6 +106,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 7fc1e50f78..c7e7587479 100644
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> @@ -488,6 +488,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_wait.c b/nptl/pthread_cond_wait.c
> index 7812b94a3a..d0166b86d5 100644
> --- a/nptl/pthread_cond_wait.c
> +++ b/nptl/pthread_cond_wait.c
> @@ -378,6 +378,7 @@ __condvar_cleanup_waiting (void *arg)
>  */
>  static __always_inline int
>  __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
> +    clockid_t clockid,
>      const struct timespec *abstime)
>  {
>    const int maxspin = 0;
> @@ -510,7 +511,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>  	      if (__glibc_unlikely (abstime->tv_sec < 0))
>  	        err = ETIMEDOUT;
>  
> -	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
> +	      else if (clockid == CLOCK_MONOTONIC)
>  		{
>  		  /* CLOCK_MONOTONIC is requested.  */
>  		  struct timespec rt;
> @@ -652,7 +653,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>  int__PTHREAD_COND_CLOCK_MONOTONIC_MASK
>  __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
>  {
> -  return __pthread_cond_wait_common (cond, mutex, NULL);
> +  return __pthread_cond_wait_common (cond, mutex, CLOCK_REALTIME, NULL);
>  }
>  

I would prefer to just use '0' and states clockid_t is unused due 'abstime' being NULL.

>  /* See __pthread_cond_wait_common.  */
> @@ -664,10 +665,31 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
>       it can assume that abstime is not NULL.  */
>    if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
>      return EINVAL;
> -  return __pthread_cond_wait_common (cond, mutex, abstime);
> +
> +  clockid_t clockid = ((cond->__data.__wrefs & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
> +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
> +}

Line to long and I think it is required to state why a plain load to
__wrefs in this specific case is suffice for synchronization.  In fact
I think it would be better to just use a relaxed MO:

    /* Relaxed MO is suffice because clock ID bit is only modified
       in condition creation.  */
    unsigned int flags = atomic_load_relaxed (&cond->__data.__wrefs);
    clockid_t clock = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
                      ? CLOCK_MONOTONIC : CLOCK_REALTIME;
    return __pthread_cond_wait_common (cond, mutex, clock, abstime);

> +
> +/* See __pthread_cond_wait_common.  */
> +int
> +__pthread_cond_timedwaitonclock_np (pthread_cond_t *cond, pthread_mutex_t *mutex,
> +				    clockid_t clockid,
> +				    const struct timespec *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;
> +
> +  /* We only support CLOCK_REALTIME and CLOCK_MONOTONIC */
> +  if (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC)
> +    return EINVAL;

I think we shold also add the test present on pthread_condattr_setclock
(Which will in fact turn to always 'true' due 'futex_supports_exact_relative_timeouts'
being always true in Linux) for consistency.

  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
  if (clock_id == CLOCK_MONOTONIC
      && !futex_supports_exact_relative_timeouts())
    return ENOTSUP;

> +
> +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
>  }
>  
>  versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
>  		  GLIBC_2_3_2);
>  versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
>  		  GLIBC_2_3_2);
> +weak_alias (__pthread_cond_timedwaitonclock_np, pthread_cond_timedwaitonclock_np);
> diff --git a/nptl/tst-cond11-onclock.c b/nptl/tst-cond11-onclock.c
> new file mode 100644
> index 0000000000..439cd404de
> --- /dev/null
> +++ b/nptl/tst-cond11-onclock.c
> @@ -0,0 +1,209 @@
> +/* Test pthread_cond_timedwaitonclock_np, based on tst-cond11.c
> +   Copyright (C) 2003-2017 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"

We create tests using libsupport now, support/README, support/README-testing.c
have some examples.  It is simplifies a lot the error reporting and code
on tests.

> diff --git a/nptl/tst-cond5-onclock.c b/nptl/tst-cond5-onclock.c
> new file mode 100644
> index 0000000000..adb3342781
> --- /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-2017 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/nptl/pthread-functions.h b/sysdeps/nptl/pthread-functions.h
> index 4006fc6c25..8225fdbfca 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 632ea7bc36..e95df8f592 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -1003,6 +1003,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/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index d2a206a8df..b0ecb71d3b 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -101,6 +101,7 @@ GLIBC_2.25 strfroml F
>  GLIBC_2.26 GLIBC_2.26 A
>  GLIBC_2.26 preadv2 F
>  GLIBC_2.26 preadv64v2 F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.26 pwritev2 F
>  GLIBC_2.26 pwritev64v2 F
>  GLIBC_2.26 reallocarray F
> diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> index 91545c1542..32b3331c19 100644
> --- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> @@ -9,6 +9,7 @@ GLIBC_2.12 pthread_setname_np F
>  GLIBC_2.18 GLIBC_2.18 A
>  GLIBC_2.18 pthread_getattr_default_np F
>  GLIBC_2.18 pthread_setattr_default_np F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.4 GLIBC_2.4 A
>  GLIBC_2.4 _IO_flockfile F
>  GLIBC_2.4 _IO_ftrylockfile F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index 2ff1998ac9..1bcf512fa1 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2023,6 +2023,7 @@ GLIBC_2.25 strfroml F
>  GLIBC_2.26 GLIBC_2.26 A
>  GLIBC_2.26 preadv2 F
>  GLIBC_2.26 preadv64v2 F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.26 pwritev2 F
>  GLIBC_2.26 pwritev64v2 F
>  GLIBC_2.26 reallocarray F
> diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> index 8f9c3254be..3ae0e37475 100644
> --- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> @@ -216,6 +216,7 @@ GLIBC_2.2.3 GLIBC_2.2.3 A
>  GLIBC_2.2.3 pthread_getattr_np F
>  GLIBC_2.2.6 GLIBC_2.2.6 A
>  GLIBC_2.2.6 __nanosleep F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.3.2 GLIBC_2.3.2 A
>  GLIBC_2.3.2 pthread_cond_broadcast F
>  GLIBC_2.3.2 pthread_cond_destroy F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> index 91545c1542..32b3331c19 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> @@ -9,6 +9,7 @@ GLIBC_2.12 pthread_setname_np F
>  GLIBC_2.18 GLIBC_2.18 A
>  GLIBC_2.18 pthread_getattr_default_np F
>  GLIBC_2.18 pthread_setattr_default_np F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.4 GLIBC_2.4 A
>  GLIBC_2.4 _IO_flockfile F
>  GLIBC_2.4 _IO_ftrylockfile F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> index 8f9c3254be..3ae0e37475 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> @@ -216,6 +216,7 @@ GLIBC_2.2.3 GLIBC_2.2.3 A
>  GLIBC_2.2.3 pthread_getattr_np F
>  GLIBC_2.2.6 GLIBC_2.2.6 A
>  GLIBC_2.2.6 __nanosleep F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.3.2 GLIBC_2.3.2 A
>  GLIBC_2.3.2 pthread_cond_broadcast F
>  GLIBC_2.3.2 pthread_cond_destroy F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index 513524d932..13f13e04db 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -1864,6 +1864,7 @@ GLIBC_2.25 strfroml F
>  GLIBC_2.26 GLIBC_2.26 A
>  GLIBC_2.26 preadv2 F
>  GLIBC_2.26 preadv64v2 F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.26 pwritev2 F
>  GLIBC_2.26 pwritev64v2 F
>  GLIBC_2.26 reallocarray F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> index 85365c057c..accb1d8d6f 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> @@ -203,6 +203,8 @@ GLIBC_2.2.5 waitpid F
>  GLIBC_2.2.5 write F
>  GLIBC_2.2.6 GLIBC_2.2.6 A
>  GLIBC_2.2.6 __nanosleep F
> +GLIBC_2.26 GLIBC_2.26 A
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.3.2 GLIBC_2.3.2 A
>  GLIBC_2.3.2 pthread_cond_broadcast F
>  GLIBC_2.3.2 pthread_cond_destroy F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index 0c557e9f43..db930f6307 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2107,6 +2107,7 @@ GLIBC_2.25 strfroml F
>  GLIBC_2.26 GLIBC_2.26 A
>  GLIBC_2.26 preadv2 F
>  GLIBC_2.26 preadv64v2 F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
>  GLIBC_2.26 pwritev2 F
>  GLIBC_2.26 pwritev64v2 F
>  GLIBC_2.26 reallocarray F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> index 6cd0fc3487..d89762bd33 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> @@ -224,3 +224,4 @@ GLIBC_2.16 write F
>  GLIBC_2.18 GLIBC_2.18 A
>  GLIBC_2.18 pthread_getattr_default_np F
>  GLIBC_2.18 pthread_setattr_default_np F
> +GLIBC_2.26 pthread_cond_timedwaitonclock_np F
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFCv4] Add pthread_cond_timedwaitonclock_np
  2017-06-28 14:39 ` Adhemerval Zanella
@ 2017-09-21 20:43   ` Mike Crowe
  2017-09-30 16:01   ` Mike Crowe
  1 sibling, 0 replies; 9+ messages in thread
From: Mike Crowe @ 2017-09-21 20:43 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, Torvald Riegel, Rich Felker

Apologies for the slow reply. I seem to have somehow missed your response
on libc-alpha. :(

On 22/06/2017 14:05, Mike Crowe wrote:
>> 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 condition
>> variable 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.
>>
>> Let's invent 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.
>>
>> Earlier versions of this patch were proposed in 2015 but further progress
>> stalled waiting for the assembly implementation of pthread_cond_timedwait.S
>> to be removed by Torvald Riegel. This happened in
>> ed19993b5b0d05d62cc883571519a67dae481a14.
>>
>> See the following threads for previous versions and discussion:
>>
>> * https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
>> * https://sourceware.org/ml/libc-alpha/2015-08/msg00186.html
>> * https://sourceware.org/ml/libc-alpha/2015-08/msg00230.html
>>
>> Some of the abilist updates for other architectures appear to have gone
>> missing during the rebase. If this change is reviewed favourably then I
>> shall try to include them.

On Wednesday 28 June 2017 at 11:39:40 -0300, Adhemerval Zanella wrote:
> I think it is a reasonable addition, however I have some concerns if this
> would just another bad discussed ABI to fix and specific issues that will
> be replaced by another better or simple solution (as your last comment in
> BZ#41861 [1]).

Comment 14 of BZ#41861 proposed two solutions, but I believe that they both
have downsides:

1. Write a new condition variable implementation in libstdc++ on top of
futex(2). Since I wrote that comment I've become aware that libstdc++ has
gained an atomic_futex implementation that could be used. It currently
falls back to using std::condition_variable when futex isn't available so
that would need to be changed before it could be used as the basis for
std::condition_variable itself.

2. Make std::condition_variable use CLOCK_MONOTONIC by default and convert
to that from CLOCK_REALTIME when passed std::chrono::system_clock. I'm
surprised this wasn't done several years ago, since I think it is
preferable to the current situation. However, it's not perfect since a wait
on std::chrono::system_clock will not react to changes made to the clock
during the wait. The current implementation results in FUTEX_CLOCK_REALTIME
being used which does react to changes to the system clock during the wait,
so this solution would change the behaviour of such code.

> It also concerns that it was not brought to Austin Group
> attention as suggested by Szabolcs [2].

I shall try to work out how I should go about doing that.

> Torvald, do you think a new API to specific a clock is a reasonable addition
> for GLIBC? Rich, any thought about this new API (any possible musl inclusion
> in nearby future in case of glibc acceptance)? Do you think we should
> approach Austin Group first? The issue with C++ seems to a QoI one that is
> currently defined afaik as implementation-defined, so it would be an
> enhancement

The lack of reliable waits using a steady clock is a problem for embedded
systems in particular because the system clock may be set at any time. In
the past we used to not even attempt to set the system clock to the real
time because so many libraries would misbehave when it changed. But,
gradually, most code has been fixed to use CLOCK_MONOTONIC so we now do so.
But we're left using our own std::condition_variable variant now (that
basically implements solution 2 above) in order to avoid the problem in C++
code.

> The patch itself has some minor issues about formatting that I outlined
> below.

Thanks for the review. I shall try to incorporate your suggestions and post
a new version.

Mike.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFCv4] Add pthread_cond_timedwaitonclock_np
  2017-06-28 14:39 ` Adhemerval Zanella
  2017-09-21 20:43   ` Mike Crowe
@ 2017-09-30 16:01   ` Mike Crowe
  2017-10-02 22:26     ` Adhemerval Zanella
  1 sibling, 1 reply; 9+ messages in thread
From: Mike Crowe @ 2017-09-30 16:01 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, Torvald Riegel, Rich Felker

> On 22/06/2017 14:05, Mike Crowe wrote:
> > 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 condition
> > variable 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.
> > 
> > Let's invent 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.
> > 
> > Earlier versions of this patch were proposed in 2015 but further progress
> > stalled waiting for the assembly implementation of pthread_cond_timedwait.S
> > to be removed by Torvald Riegel. This happened in
> > ed19993b5b0d05d62cc883571519a67dae481a14.
> > 
> > See the following threads for previous versions and discussion:
> > 
> > * https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
> > * https://sourceware.org/ml/libc-alpha/2015-08/msg00186.html
> > * https://sourceware.org/ml/libc-alpha/2015-08/msg00230.html
> > 
> > Some of the abilist updates for other architectures appear to have gone
> > missing during the rebase. If this change is reviewed favourably then I
> > shall try to include them.

On Wednesday 28 June 2017 at 11:39:40 -0300, Adhemerval Zanella wrote:
> I think it is a reasonable addition, however I have some concerns if this
> would just another bad discussed ABI to fix and specific issues that will
> be replaced by another better or simple solution (as your last comment in
> BZ#41861 [1]).  It also concerns that it was not brought to Austin Group
> attention as suggested by Szabolcs [2].

I've now submitted the suggestion. It can be viewed at
http://austingroupbugs.net/view.php?id=1164

[Snipped uncontentious parts of patch and suggestions for brevity.]

> > diff --git a/nptl/Versions b/nptl/Versions
> > index 0ae5def464..1cf8c2fbad 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.26 {
> > +    pthread_cond_timedwaitonclock_np;
> > +  }
> 
> The libc addition seems wrong, whhy this is required?

pthread_cond_timedwait is in libc, so I followed suite and added
pthread_cond_timedwaitonclock_np too. I must admit that I can't quite see
how the dummy empty implementations of the pthread functions end up in
libc, but they apparently do according to:

https://stackoverflow.com/questions/11161462/why-glibc-and-pthread-library-both-defined-same-apis

Maybe this means that I've missed something.

> >  /* See __pthread_cond_wait_common.  */
> > @@ -664,10 +665,31 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
> >       it can assume that abstime is not NULL.  */
> >    if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
> >      return EINVAL;
> > -  return __pthread_cond_wait_common (cond, mutex, abstime);
> > +
> > +  clockid_t clockid = ((cond->__data.__wrefs & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
> > +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
> > +}
> 
> Line to long and I think it is required to state why a plain load to
> __wrefs in this specific case is suffice for synchronization.  In fact
> I think it would be better to just use a relaxed MO:
> 
>     /* Relaxed MO is suffice because clock ID bit is only modified
>        in condition creation.  */
>     unsigned int flags = atomic_load_relaxed (&cond->__data.__wrefs);
>     clockid_t clock = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
>                       ? CLOCK_MONOTONIC : CLOCK_REALTIME;
>     return __pthread_cond_wait_common (cond, mutex, clock, abstime);

OK. I too was worried about that load, but persuaded myself that it was
safe for the same reasons. I think you're correct that it should be made
explicit and explained.

Thanks again for your review.

Mike.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [RFCv4] Add pthread_cond_timedwaitonclock_np
  2017-09-30 16:01   ` Mike Crowe
@ 2017-10-02 22:26     ` Adhemerval Zanella
  2019-07-16 10:05       ` pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np) Mike Crowe
  0 siblings, 1 reply; 9+ messages in thread
From: Adhemerval Zanella @ 2017-10-02 22:26 UTC (permalink / raw)
  To: Mike Crowe; +Cc: libc-alpha, Torvald Riegel, Rich Felker



On 30/09/2017 13:01, Mike Crowe wrote:
>> On 22/06/2017 14:05, Mike Crowe wrote:
>>> 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 condition
>>> variable 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.
>>>
>>> Let's invent 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.
>>>
>>> Earlier versions of this patch were proposed in 2015 but further progress
>>> stalled waiting for the assembly implementation of pthread_cond_timedwait.S
>>> to be removed by Torvald Riegel. This happened in
>>> ed19993b5b0d05d62cc883571519a67dae481a14.
>>>
>>> See the following threads for previous versions and discussion:
>>>
>>> * https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
>>> * https://sourceware.org/ml/libc-alpha/2015-08/msg00186.html
>>> * https://sourceware.org/ml/libc-alpha/2015-08/msg00230.html
>>>
>>> Some of the abilist updates for other architectures appear to have gone
>>> missing during the rebase. If this change is reviewed favourably then I
>>> shall try to include them.
> 
> On Wednesday 28 June 2017 at 11:39:40 -0300, Adhemerval Zanella wrote:
>> I think it is a reasonable addition, however I have some concerns if this
>> would just another bad discussed ABI to fix and specific issues that will
>> be replaced by another better or simple solution (as your last comment in
>> BZ#41861 [1]).  It also concerns that it was not brought to Austin Group
>> attention as suggested by Szabolcs [2].
> 
> I've now submitted the suggestion. It can be viewed at
> http://austingroupbugs.net/view.php?id=1164
> 
> [Snipped uncontentious parts of patch and suggestions for brevity.]

Thanks, I think this is the best way forward, although it might require
some time to get Austin group any reply.  If and once we get a positive
indication for API inclusion, we speed up by adding as a GNU extension
for upcoming releases and later adding in the default API.

> 
>>> diff --git a/nptl/Versions b/nptl/Versions
>>> index 0ae5def464..1cf8c2fbad 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.26 {
>>> +    pthread_cond_timedwaitonclock_np;
>>> +  }
>>
>> The libc addition seems wrong, whhy this is required?
> 
> pthread_cond_timedwait is in libc, so I followed suite and added
> pthread_cond_timedwaitonclock_np too. I must admit that I can't quite see
> how the dummy empty implementations of the pthread functions end up in
> libc, but they apparently do according to:
> 
> https://stackoverflow.com/questions/11161462/why-glibc-and-pthread-library-both-defined-same-apis
> 
> Maybe this means that I've missed something.

This is an GLIB implementation detail, where some libraries which
are expected to be usable without explicit linking to libpthread use
some pthread functions (for instance aio from librt). 

In the single thread case libc.so uses wrappers that may or not call the
libpthread.so implementation (nptl/forward.c) if libpthread.so.0 is
loaded (by dlopen for instance).

So since there is no current use of pthread_cond_timedwaitonclock_np,
there is no requirement to add it on libc.so. 

> 
>>>  /* See __pthread_cond_wait_common.  */
>>> @@ -664,10 +665,31 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
>>>       it can assume that abstime is not NULL.  */
>>>    if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
>>>      return EINVAL;
>>> -  return __pthread_cond_wait_common (cond, mutex, abstime);
>>> +
>>> +  clockid_t clockid = ((cond->__data.__wrefs & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
>>> +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
>>> +}
>>
>> Line to long and I think it is required to state why a plain load to
>> __wrefs in this specific case is suffice for synchronization.  In fact
>> I think it would be better to just use a relaxed MO:
>>
>>     /* Relaxed MO is suffice because clock ID bit is only modified
>>        in condition creation.  */
>>     unsigned int flags = atomic_load_relaxed (&cond->__data.__wrefs);
>>     clockid_t clock = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
>>                       ? CLOCK_MONOTONIC : CLOCK_REALTIME;
>>     return __pthread_cond_wait_common (cond, mutex, clock, abstime);
> 
> OK. I too was worried about that load, but persuaded myself that it was
> safe for the same reasons. I think you're correct that it should be made
> explicit and explained.
> 
> Thanks again for your review.
> 
> Mike.
> 

I think you can add a comment stating that since it is undefined behaviour
to call pthread_mutex_timedwait with a cond or mutex argument which has not
been initialized, the __wrefs bits used for clockid is not expected to be
set concurrently and so it should be safe to use a relaxed load in this
case.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np)
  2017-10-02 22:26     ` Adhemerval Zanella
@ 2019-07-16 10:05       ` Mike Crowe
  2019-07-16 11:00         ` Florian Weimer
  0 siblings, 1 reply; 9+ messages in thread
From: Mike Crowe @ 2019-07-16 10:05 UTC (permalink / raw)
  To: Adhemerval Zanella, libc-alpha, Carlos O'Donell

[pthread_cond_clockwait was previously known as
pthread_cond_timedwaitonclock_np.]

On Monday 02 October 2017 at 19:26:35 -0300, Adhemerval Zanella wrote:
> >>> diff --git a/nptl/Versions b/nptl/Versions
> >>> index 0ae5def464..1cf8c2fbad 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.26 {
> >>> +    pthread_cond_timedwaitonclock_np;
> >>> +  }
> >>
> >> The libc addition seems wrong, whhy this is required?
> > 
> > pthread_cond_timedwait is in libc, so I followed suit and added
> > pthread_cond_timedwaitonclock_np too. I must admit that I can't quite see
> > how the dummy empty implementations of the pthread functions end up in
> > libc, but they apparently do according to:
> > 
> > https://stackoverflow.com/questions/11161462/why-glibc-and-pthread-library-both-defined-same-apis
> > 
> > Maybe this means that I've missed something.
> 
> This is an GLIB implementation detail, where some libraries which
> are expected to be usable without explicit linking to libpthread use
> some pthread functions (for instance aio from librt). 
> 
> In the single thread case libc.so uses wrappers that may or not call the
> libpthread.so implementation (nptl/forward.c) if libpthread.so.0 is
> loaded (by dlopen for instance).
> 
> So since there is no current use of pthread_cond_timedwaitonclock_np,
> there is no requirement to add it on libc.so.

I was digging through some old review comments, and came across this. It
looks like I didn't address it. :( afe4de7d283ebd88157126c5494ce1796194c16e
added forwarders for __pthread_cond_clockwait and pthread_clock_clockwait
to glibc:

$ nm /lib64/libc.so.6 |grep _clockwait
000000000007f410 t __pthread_cond_clockwait
000000000007f410 t pthread_cond_clockwait

Should we remove them now, before they are included in a release and it's
too late? (I tried removing them from forward.c, pthread-functions.h and
nptl-init.c and all tests passed on x86_64.)

Alternatively, if they should stay, do they need adding to the libc part of
nptl/Versions?

Thanks, and sorry for not discovering this earlier.

Mike.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np)
  2019-07-16 10:05       ` pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np) Mike Crowe
@ 2019-07-16 11:00         ` Florian Weimer
  2019-07-16 14:31           ` Mike Crowe
  2019-07-16 16:11           ` Carlos O'Donell
  0 siblings, 2 replies; 9+ messages in thread
From: Florian Weimer @ 2019-07-16 11:00 UTC (permalink / raw)
  To: Mike Crowe; +Cc: Adhemerval Zanella, libc-alpha, Carlos O'Donell

* Mike Crowe:

> I was digging through some old review comments, and came across this. It
> looks like I didn't address it. :( afe4de7d283ebd88157126c5494ce1796194c16e
> added forwarders for __pthread_cond_clockwait and pthread_clock_clockwait
> to glibc:
>
> $ nm /lib64/libc.so.6 |grep _clockwait
> 000000000007f410 t __pthread_cond_clockwait
> 000000000007f410 t pthread_cond_clockwait
>
> Should we remove them now, before they are included in a release and it's
> too late? (I tried removing them from forward.c, pthread-functions.h and
> nptl-init.c and all tests passed on x86_64.)

There's no rush because they aren't part of the ABI due to the missing
nptl/Versions entry.  Therefore, they cannot be used today.  Removing
them is just an optimization.

It's up to Carlos to say whether he wants it in the release.  Posting a
patch should help with that decision (and since there's no ABI list
change involved, the patch can easily be applied after the release if
necessary).

Thanks,
Florian

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np)
  2019-07-16 11:00         ` Florian Weimer
@ 2019-07-16 14:31           ` Mike Crowe
  2019-07-16 16:11           ` Carlos O'Donell
  1 sibling, 0 replies; 9+ messages in thread
From: Mike Crowe @ 2019-07-16 14:31 UTC (permalink / raw)
  To: Florian Weimer, Carlos O'Donell; +Cc: Adhemerval Zanella, libc-alpha

On Tuesday 16 July 2019 at 13:00:40 +0200, Florian Weimer wrote:
> * Mike Crowe:
> 
> > I was digging through some old review comments, and came across this. It
> > looks like I didn't address it. :( afe4de7d283ebd88157126c5494ce1796194c16e
> > added forwarders for __pthread_cond_clockwait and pthread_clock_clockwait
> > to glibc:
> >
> > $ nm /lib64/libc.so.6 |grep _clockwait
> > 000000000007f410 t __pthread_cond_clockwait
> > 000000000007f410 t pthread_cond_clockwait
> >
> > Should we remove them now, before they are included in a release and it's
> > too late? (I tried removing them from forward.c, pthread-functions.h and
> > nptl-init.c and all tests passed on x86_64.)
> 
> There's no rush because they aren't part of the ABI due to the missing
> nptl/Versions entry.  Therefore, they cannot be used today.  Removing
> them is just an optimization.
> 
> It's up to Carlos to say whether he wants it in the release.  Posting a
> patch should help with that decision (and since there's no ABI list
> change involved, the patch can easily be applied after the release if
> necessary).

Done. https://sourceware.org/ml/libc-alpha/2019-07/msg00298.html

Thanks.

Mike.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np)
  2019-07-16 11:00         ` Florian Weimer
  2019-07-16 14:31           ` Mike Crowe
@ 2019-07-16 16:11           ` Carlos O'Donell
  1 sibling, 0 replies; 9+ messages in thread
From: Carlos O'Donell @ 2019-07-16 16:11 UTC (permalink / raw)
  To: Florian Weimer, Mike Crowe; +Cc: Adhemerval Zanella, libc-alpha

On 7/16/19 7:00 AM, Florian Weimer wrote:
> * Mike Crowe:
> 
>> I was digging through some old review comments, and came across this. It
>> looks like I didn't address it. :( afe4de7d283ebd88157126c5494ce1796194c16e
>> added forwarders for __pthread_cond_clockwait and pthread_clock_clockwait
>> to glibc:
>>
>> $ nm /lib64/libc.so.6 |grep _clockwait
>> 000000000007f410 t __pthread_cond_clockwait
>> 000000000007f410 t pthread_cond_clockwait
>>
>> Should we remove them now, before they are included in a release and it's
>> too late? (I tried removing them from forward.c, pthread-functions.h and
>> nptl-init.c and all tests passed on x86_64.)
> 
> There's no rush because they aren't part of the ABI due to the missing
> nptl/Versions entry.  Therefore, they cannot be used today.  Removing
> them is just an optimization.
> 
> It's up to Carlos to say whether he wants it in the release.  Posting a
> patch should help with that decision (and since there's no ABI list
> change involved, the patch can easily be applied after the release if
> necessary).

Yes, please post the patch and I'll review. TO: me.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-07-16 16:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-22 17:05 [RFCv4] Add pthread_cond_timedwaitonclock_np Mike Crowe
2017-06-28 14:39 ` Adhemerval Zanella
2017-09-21 20:43   ` Mike Crowe
2017-09-30 16:01   ` Mike Crowe
2017-10-02 22:26     ` Adhemerval Zanella
2019-07-16 10:05       ` pthread_cond_clockwait glibc forwarder (was Re: [RFCv4] Add pthread_cond_timedwaitonclock_np) Mike Crowe
2019-07-16 11:00         ` Florian Weimer
2019-07-16 14:31           ` Mike Crowe
2019-07-16 16:11           ` Carlos O'Donell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).