unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions
@ 2019-05-27 20:03 Mike Crowe
  2019-05-27 20:03 ` [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls Mike Crowe
                   ` (5 more replies)
  0 siblings, 6 replies; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

My attempts[1] to add a variant of pthread_cond_timedwait that would accept
a clockid_t parameter led me to propose[2] to The Austin Group the addition
of an entire family of functions that accept a clockid_t parameter to
indicate the clock that the timespec absolute timeout parameter should be
measured against. They responded positively to the request but an
implementation is required before the proposal can proceed.

This patch series is the second version of the first part of that
implementation in glibc, it contains implementations and tests for
four new functions:

int pthread_cond_clockwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
                           clockid_t clock, const struct timespec *abstime)

int pthread_rwlock_clockrdlock(pthread_rwlock_t *rwlock, clockid_t clock,
                               const struct timespec *abstime)

int pthread_rwlock_clockwrlock(pthread_rwlock_t *rwlock, clockid_t clock,
                               const struct timespec *abstime)

int sem_clockwait(sem_t *restrict, clockid_t clock_id, const struct
                  timespec *restrict)

These are implemented by replacing the underlying equivalent _timed
functions with ones that accept a clockid_t parameter, and then
implementing the existing _timed functions by passing CLOCK_REALTIME to the
new implementation. This requires clockid_t parameters to be added to the
underlying futex-internal and lowlevellock-futex functions.

I have an implementation of pthread_mutex_clocklock too, but it's not
quite ready for posting yet.

glibc-specific functions, such as pthread_timedjoin_np are next on the
list after that.

The mq_clockreceive and mq_clocksend functions corresponding to
mq_timedreceive and mq_timedsend require kernel changes before they can be
implemented in glibc.

As implemented, passing an unsupported or invalid clock to these functions
yields EINVAL. I considered returning ENOTSUP for valid-but-unsupported
clocks, but I was worried that there was a risk that the list of valid
clocks would not be updated when a new clock was added to glibc.

Rather than duplicating tests, I've parameterised them so that the same
tests can be run on the existing timedwait functions and the new clockwait
functions.

The changes have been tested with "make check" and "make check-abi" on
x86, x86_64, arm and arm64. I've attempted to update the abilists for
all architectures, but cannot test all of them.

Thanks to everyone that commented on previous versions of this patch
series. They have been a great help, and I hope that I have
incorporated their feedback correctly.

Adhemerval Zanella suggested that timespec validity checks could be
consolidated. I think that's a good idea, but it would need to be a
different change. This series doesn't really make that change any
harder to do, and I can try to tackle that separately.

Adhemerval Zanella also suggested that
futex_supports_exact_relative_timeouts could be removed. I agree, but
that would also need to be a separate change.

Changes since v2[5]:
* Don't update hurd abilist since the new functions aren't (yet) in
  htl.

Changes since v1[4]:
* Many whitespace/formatting cleanups
* Rebase on top of tests that use libsupport
* Use futex_abstimed_supported_clockid in __pthread_cond_clockwait.
* Update all abilists.
* Add to NEWS.

[1] https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
[2] http://austingroupbugs.net/view.php?id=1216
[3] https://sourceware.org/ml/libc-alpha/2019-05/msg00031.html
[4] https://sourceware.org/ml/libc-alpha/2019-02/msg00637.html
[5] https://sourceware.org/ml/libc-alpha/2019-05/msg00131.html

Mike Crowe (6):
  nptl: Add clockid parameter to futex timed wait calls
  nptl: Add POSIX-proposed sem_clockwait
  nptl: Add POSIX-proposed pthread_cond_clockwait
  nptl: pthread_rwlock: Move timeout validation into _full functions
  nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock
  Update NEWS for new _clockwait functions

 ChangeLog                                                       | 329 +++++++-
 NEWS                                                            |   6 +-
 manual/threads.texi                                             |  58 +-
 nptl/Makefile                                                   |   8 +-
 nptl/Versions                                                   |   5 +-
 nptl/forward.c                                                  |   5 +-
 nptl/nptl-init.c                                                |   1 +-
 nptl/pthreadP.h                                                 |   4 +-
 nptl/pthread_cond_wait.c                                        |  68 +-
 nptl/pthread_mutex_timedlock.c                                  |   4 +-
 nptl/pthread_rwlock_clockrdlock.c                               |  29 +-
 nptl/pthread_rwlock_clockwrlock.c                               |  29 +-
 nptl/pthread_rwlock_common.c                                    |  32 +-
 nptl/pthread_rwlock_rdlock.c                                    |   2 +-
 nptl/pthread_rwlock_timedrdlock.c                               |  12 +-
 nptl/pthread_rwlock_timedwrlock.c                               |  12 +-
 nptl/pthread_rwlock_wrlock.c                                    |   2 +-
 nptl/sem_clockwait.c                                            |  45 +-
 nptl/sem_timedwait.c                                            |   3 +-
 nptl/sem_wait.c                                                 |   3 +-
 nptl/sem_waitcommon.c                                           |  15 +-
 nptl/tst-abstime.c                                              |   8 +-
 nptl/tst-cond11.c                                               |  37 +-
 nptl/tst-cond26.c                                               |  77 ++-
 nptl/tst-cond27.c                                               |  68 +-
 nptl/tst-rwlock14.c                                             |  12 +-
 nptl/tst-rwlock6.c                                              |  94 +-
 nptl/tst-rwlock7.c                                              |  83 +-
 nptl/tst-rwlock9.c                                              | 102 +-
 nptl/tst-sem13.c                                                |  39 +-
 nptl/tst-sem17.c                                                |  76 ++-
 nptl/tst-sem5.c                                                 |  23 +-
 sysdeps/nptl/futex-internal.h                                   |   7 +-
 sysdeps/nptl/lowlevellock-futex.h                               |  13 +-
 sysdeps/nptl/pthread-functions.h                                |   4 +-
 sysdeps/nptl/pthread.h                                          |  29 +-
 sysdeps/pthread/semaphore.h                                     |   7 +-
 sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |   4 +-
 sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |   4 +-
 sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |   4 +-
 sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |   4 +-
 sysdeps/unix/sysv/linux/futex-internal.h                        |  26 +-
 sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |   4 +-
 sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |   4 +-
 sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |   4 +-
 sysdeps/unix/sysv/linux/lowlevellock-futex.h                    |  33 +-
 sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |   4 +-
 sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |   4 +-
 sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |   4 +-
 sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |   4 +-
 sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |   4 +-
 sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |   4 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |   4 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |   4 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |   4 +-
 sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |   4 +-
 sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |   4 +-
 sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |   4 +-
 sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |   4 +-
 sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |   4 +-
 sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |   4 +-
 sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |   4 +-
 sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |   4 +-
 63 files changed, 1323 insertions(+), 183 deletions(-)
 create mode 100644 nptl/pthread_rwlock_clockrdlock.c
 create mode 100644 nptl/pthread_rwlock_clockwrlock.c
 create mode 100644 nptl/sem_clockwait.c
 create mode 100644 nptl/tst-cond26.c
 create mode 100644 nptl/tst-cond27.c
 create mode 100644 nptl/tst-sem17.c

base-commit: 85188d8211698d1a255f0aec6529546db5c56de3
-- 
git-series 0.9.1

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

* [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls
  2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
@ 2019-05-27 20:03 ` Mike Crowe
  2019-06-05 17:52   ` Adhemerval Zanella
  2019-05-27 20:03 ` [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait Mike Crowe
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

In preparation for adding POSIX clockwait variants of timedwait functions,
add a clockid_t parameter to futex_abstimed_wait functions and pass
CLOCK_REALTIME from all callers for the time being.

Replace lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset which
takes a clockid_t parameter rather than the magic clockbit.

* sysdeps/nptl/lowlevellock-futex.h,
  sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
  lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset that takes a
  clockid rather than a special clockbit.

* sysdeps/nptl/lowlevellock-futex.h: Add lll_futex_supported_clockid so
  that client functions can check whether their clockid parameter is valid
  even if they don't ultimately end up calling lll_futex_clock_wait_bitset.

* sysdeps/nptl/futex-internal.h, sysdeps/unix/sysv/linux/futex-internal.h
  (futex_abstimed_wait, futex_abstimed_wait_cancelable): Add clockid_t
  parameter to indicate which clock the absolute time passed should be
  measured against. Pass that clockid onto lll_futex_clock_wait_bitset.
  Add invalid clock as reason for returning -EINVAL.

* sysdeps/nptl/futex-internal.h, sysdeps/unix/sysv/linux/futex-internal.h:
  Introduce futex_abstimed_supported_clockid so that client functions can
  check whether their clockid parameter is valid even if they don't
  ultimately end up calling futex_abstimed_wait.

* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Remove code to
  calculate relative timeout for __PTHREAD_COND_CLOCK_MONOTONIC_MASK and
  just pass CLOCK_MONOTONIC or CLOCK_REALTIME as required to
  futex_abstimed_wait_cancelable.

* nptl/pthread_rwlock_common (__pthread_rwlock_rdlock_full,
  __pthread_wrlock_full), nptl/sem_waitcommon (do_futex_wait): Pass
  additional CLOCK_REALTIME to futex_abstimed_wait_cancelable.

* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Switch to
  lll_futex_clock_wait_bitset and pass CLOCK_REALTIME
---
 ChangeLog                                    | 40 +++++++++++++++++++++-
 nptl/pthread_cond_wait.c                     | 32 +++--------------
 nptl/pthread_mutex_timedlock.c               |  4 +-
 nptl/pthread_rwlock_common.c                 |  8 ++--
 nptl/sem_waitcommon.c                        |  6 ++-
 sysdeps/nptl/futex-internal.h                |  7 ++++-
 sysdeps/nptl/lowlevellock-futex.h            | 13 ++++---
 sysdeps/unix/sysv/linux/futex-internal.h     | 26 ++++++++++----
 sysdeps/unix/sysv/linux/lowlevellock-futex.h | 33 +++++++++++++----
 9 files changed, 118 insertions(+), 51 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 53a3ae4..ff85b12 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2019-05-27  Mike Crowe  <mac@mcrowe.com>
+
+	nptl: Add clockid parameter to futex timed wait calls
+
+	* sysdeps/nptl/lowlevellock-futex.h,
+	sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
+	lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset that
+	takes a clockid rather than a special clockbit.
+
+	* sysdeps/nptl/lowlevellock-futex.h: Add
+	lll_futex_supported_clockid so that client functions can check
+	whether their clockid parameter is valid even if they don't
+	ultimately end up calling lll_futex_clock_wait_bitset.
+
+	* sysdeps/nptl/futex-internal.h,
+	sysdeps/unix/sysv/linux/futex-internal.h
+	(futex_abstimed_wait, futex_abstimed_wait_cancelable): Add
+	clockid_t parameter to indicate which clock the absolute time
+	passed should be measured against. Pass that clockid onto
+	lll_futex_clock_wait_bitset. Add invalid clock as reason for
+	returning -EINVAL.
+
+	* sysdeps/nptl/futex-internal.h,
+	sysdeps/unix/sysv/linux/futex-internal.h: Introduce
+	futex_abstimed_supported_clockid so that client functions can check
+	whether their clockid parameter is valid even if they don't
+	ultimately end up calling futex_abstimed_wait.
+
+	* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Remove
+	code to calculate relative timeout for
+	__PTHREAD_COND_CLOCK_MONOTONIC_MASK and just pass CLOCK_MONOTONIC
+	or CLOCK_REALTIME as required to futex_abstimed_wait_cancelable.
+
+	* nptl/pthread_rwlock_common (__pthread_rwlock_rdlock_full)
+	(__pthread_wrlock_full), nptl/sem_waitcommon (do_futex_wait): Pass
+	additional CLOCK_REALTIME to futex_abstimed_wait_cancelable.
+
+	* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock):
+	Switch to lll_futex_clock_wait_bitset and pass CLOCK_REALTIME
+
 2019-05-27  Florian Weimer  <fweimer@redhat.com>
 
 	* nptl/nptl-init.c: Add comment.
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 9a0f29e..7385562 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -509,35 +509,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 		 values despite them being valid.  */
 	      if (__glibc_unlikely (abstime->tv_sec < 0))
 	        err = ETIMEDOUT;
-
-	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
-		{
-		  /* CLOCK_MONOTONIC is requested.  */
-		  struct timespec rt;
-		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
-		    __libc_fatal ("clock_gettime does not support "
-				  "CLOCK_MONOTONIC\n");
-		  /* Convert the absolute timeout value to a relative
-		     timeout.  */
-		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
-		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
-		  if (rt.tv_nsec < 0)
-		    {
-		      rt.tv_nsec += 1000000000;
-		      --rt.tv_sec;
-		    }
-		  /* Did we already time out?  */
-		  if (__glibc_unlikely (rt.tv_sec < 0))
-		    err = ETIMEDOUT;
-		  else
-		    err = futex_reltimed_wait_cancelable
-			(cond->__data.__g_signals + g, 0, &rt, private);
-		}
 	      else
 		{
-		  /* Use CLOCK_REALTIME.  */
+		  const clockid_t clockid =
+		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
+		    CLOCK_MONOTONIC : CLOCK_REALTIME;
+
 		  err = futex_abstimed_wait_cancelable
-		      (cond->__data.__g_signals + g, 0, abstime, private);
+                    (cond->__data.__g_signals + g, 0, clockid, abstime,
+                     private);
 		}
 	    }
 
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index 270b072..d4d11cc 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -266,8 +266,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
 	  assume_other_futex_waiters |= FUTEX_WAITERS;
 
 	  /* Block using the futex.  */
-	  int err = lll_futex_timed_wait_bitset (&mutex->__data.__lock,
-	      oldval, abstime, FUTEX_CLOCK_REALTIME,
+	  int err = lll_futex_clock_wait_bitset (&mutex->__data.__lock,
+	      oldval, CLOCK_REALTIME, abstime,
 	      PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
 	  /* The futex call timed out.  */
 	  if (err == -ETIMEDOUT)
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index 2560734..89ba21a 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -319,7 +319,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 		{
 		  int private = __pthread_rwlock_get_private (rwlock);
 		  int err = futex_abstimed_wait (&rwlock->__data.__readers,
-						 r, abstime, private);
+						 r, CLOCK_REALTIME, abstime, private);
 		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
 		     return because we don't need to clean up anything.  */
 		  if (err == ETIMEDOUT)
@@ -447,7 +447,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 	    continue;
 	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
 					 1 | PTHREAD_RWLOCK_FUTEX_USED,
-					 abstime, private);
+					 CLOCK_REALTIME, abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      /* If we timed out, we need to unregister.  If no read phase
@@ -707,7 +707,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	  may_share_futex_used_flag = true;
 	  int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
 					 1 | PTHREAD_RWLOCK_FUTEX_USED,
-					 abstime, private);
+					 CLOCK_REALTIME, abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      if (prefer_writer)
@@ -806,7 +806,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	    continue;
 	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
 					 PTHREAD_RWLOCK_FUTEX_USED,
-					 abstime, private);
+					 CLOCK_REALTIME, abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
index 5646bea..425d040 100644
--- a/nptl/sem_waitcommon.c
+++ b/nptl/sem_waitcommon.c
@@ -109,11 +109,13 @@ do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
 
 #if __HAVE_64B_ATOMICS
   err = futex_abstimed_wait_cancelable (
-      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
+      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0,
+      CLOCK_REALTIME, abstime,
       sem->private);
 #else
   err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
-					abstime, sem->private);
+					CLOCK_REALTIME, abstime,
+					sem->private);
 #endif
 
   return err;
diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h
index 86a0818..54b7319 100644
--- a/sysdeps/nptl/futex-internal.h
+++ b/sysdeps/nptl/futex-internal.h
@@ -159,16 +159,23 @@ futex_reltimed_wait_cancelable (unsigned int* futex_word,
 				unsigned int expected,
 			        const struct timespec* reltime, int private);
 
+/* Check whether the specified clockid is supported by
+   futex_abstimed_wait and futex_abstimed_wait_cancelable. */
+static __always_inline int
+futex_abstimed_supported_clockid (clockid_t clockid);
+
 /* Like futex_reltimed_wait, but the provided timeout (ABSTIME) is an
    absolute point in time; a call will time out after this point in time.  */
 static __always_inline int
 futex_abstimed_wait (unsigned int* futex_word, unsigned int expected,
+		     clockid_t clockid,
 		     const struct timespec* abstime, int private);
 
 /* Like futex_reltimed_wait but is a POSIX cancellation point.  */
 static __always_inline int
 futex_abstimed_wait_cancelable (unsigned int* futex_word,
 				unsigned int expected,
+				clockid_t clockid,
 			        const struct timespec* abstime, int private);
 
 /* Atomically wrt other futex operations on the same futex, this unblocks the
diff --git a/sysdeps/nptl/lowlevellock-futex.h b/sysdeps/nptl/lowlevellock-futex.h
index 63d917d..35fcfbb 100644
--- a/sysdeps/nptl/lowlevellock-futex.h
+++ b/sysdeps/nptl/lowlevellock-futex.h
@@ -43,10 +43,15 @@
 #define lll_futex_timed_wait(futexp, val, timeout, private)             \
   -ENOSYS
 
-/* If CLOCKBIT is zero, this is identical to lll_futex_timed_wait.
-   If CLOCKBIT has FUTEX_CLOCK_REALTIME set, then it's the same but
-   TIMEOUT is counted by CLOCK_REALTIME rather than CLOCK_MONOTONIC.  */
-#define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
+/* Verify whether the supplied clockid is supported by
+   lll_futex_clock_wait_bitset */
+#define lll_futex_supported_clockid(clockid)				\
+  (0)
+
+/* Wait until a lll_futex_wake call on FUTEXP, or the absolute TIMEOUT
+   measured against CLOCKID elapses. CLOCKID may be CLOCK_REALTIME or
+   CLOCK_MONOTONIC. */
+#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
   -ENOSYS
 
 /* Wake up up to NR waiters on FUTEXP.  */
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
index 501f993..03312d6 100644
--- a/sysdeps/unix/sysv/linux/futex-internal.h
+++ b/sysdeps/unix/sysv/linux/futex-internal.h
@@ -162,15 +162,24 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
 
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
+futex_abstimed_supported_clockid (clockid_t clockid)
+{
+  return lll_futex_supported_clockid (clockid);
+}
+
+/* See sysdeps/nptl/futex-internal.h for details.  */
+static __always_inline int
 futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
+		     clockid_t clockid,
 		     const struct timespec *abstime, int private)
 {
   /* Work around the fact that the kernel rejects negative timeout values
      despite them being valid.  */
   if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
     return ETIMEDOUT;
-  int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
-					 FUTEX_CLOCK_REALTIME, private);
+  int err = lll_futex_clock_wait_bitset (futex_word, expected,
+					 clockid, abstime,
+					 private);
   switch (err)
     {
     case 0:
@@ -180,9 +189,10 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
       return -err;
 
     case -EFAULT: /* Must have been caused by a glibc or application bug.  */
-    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
-		     being normalized.  Must have been caused by a glibc or
-		     application bug.  */
+    case -EINVAL: /* Either due to wrong alignment, unsupported
+		     clockid or due to the timeout not being
+		     normalized. Must have been caused by a glibc or
+		     application bug. */
     case -ENOSYS: /* Must have been caused by a glibc bug.  */
     /* No other errors are documented at this time.  */
     default:
@@ -194,6 +204,7 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
 static __always_inline int
 futex_abstimed_wait_cancelable (unsigned int *futex_word,
 				unsigned int expected,
+				clockid_t clockid,
 			        const struct timespec *abstime, int private)
 {
   /* Work around the fact that the kernel rejects negative timeout values
@@ -202,8 +213,9 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
     return ETIMEDOUT;
   int oldtype;
   oldtype = __pthread_enable_asynccancel ();
-  int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
-					 FUTEX_CLOCK_REALTIME, private);
+  int err = lll_futex_clock_wait_bitset (futex_word, expected,
+					clockid, abstime,
+					private);
   __pthread_disable_asynccancel (oldtype);
   switch (err)
     {
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index 030a14b..ba01197 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -82,12 +82,33 @@
 		     __lll_private_flag (FUTEX_WAIT, private),  \
 		     val, timeout)
 
-#define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
-  lll_futex_syscall (6, futexp,                                         \
-		     __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
-					 private),                      \
-		     val, timeout, NULL /* Unused.  */,                 \
-		     FUTEX_BITSET_MATCH_ANY)
+/* Verify whether the supplied clockid is supported by
+   lll_futex_clock_wait_bitset */
+#define lll_futex_supported_clockid(clockid)			\
+  ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC)
+
+/* The kernel currently only supports CLOCK_MONOTONIC or
+ * CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to
+ * convert others here but currently do not.
+ */
+#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
+  ({									\
+    long int __ret;							\
+    if (lll_futex_supported_clockid (clockid))                          \
+      {                                                                 \
+        const unsigned int clockbit =                                   \
+          (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0;       \
+        const int op =                                                  \
+          __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private);   \
+                                                                        \
+        __ret = lll_futex_syscall (6, futexp, op, val,                  \
+                                   timeout, NULL /* Unused.  */,	\
+                                   FUTEX_BITSET_MATCH_ANY);		\
+      }                                                                 \
+    else                                                                \
+      __ret = -EINVAL;							\
+    __ret;								\
+  })
 
 #define lll_futex_wake(futexp, nr, private)                             \
   lll_futex_syscall (4, futexp,                                         \
-- 
git-series 0.9.1

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

* [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
  2019-05-27 20:03 ` [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls Mike Crowe
@ 2019-05-27 20:03 ` Mike Crowe
  2019-06-05 21:07   ` Adhemerval Zanella
  2019-05-27 20:03 ` [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait Mike Crowe
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

Add:

 int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)

which behaves just like sem_timedwait, but measures abstime against the
specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
sets errno == EINVAL if any other clock is specified.

* nptl/sem_waitcommon.c (do_futex_wait, __new_sem_wait_slow): Add clockid
  parameters to indicate the clock which abstime should be measured
  against.

* nptl/sem_timedwait.c (sem_timedwait), nptl/sem_wait.c (__new_sem_wait):
  Pass CLOCK_REALTIME as clockid to __new_sem_wait_slow.

* nptl/sem_clockwait.c: New file to implement sem_clockwait based on
  sem_timedwait.c.

* nptl/Makefile: Add sem_clockwait.c source file. Add CFLAGS for
  sem_clockwait.c to match those used for sem_timedwait.c.

* sysdeps/pthread/semaphore.h: Add sem_clockwait.

* nptl/Versions (GLIBC_2.30): Likewise.

* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
  (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
  (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
  (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist	(GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist (GLIBC_2.30):
  Likewise.
* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist (GLIBC_2.30):
  Likewise.

* nptl/tst-sem17.c: Add new test for passing invalid clock to
  sem_clockwait.

* nptl/tst-sem13.c, nptl/tst-sem5.c: Modify existing sem_timedwait tests to
  also test sem_clockwait.

* manual/threads.texi: Document sem_clockwait.
---
 ChangeLog                                                       | 71 +++++++-
 manual/threads.texi                                             | 10 +-
 nptl/Makefile                                                   |  5 +-
 nptl/Versions                                                   |  4 +-
 nptl/sem_clockwait.c                                            | 45 ++++-
 nptl/sem_timedwait.c                                            |  3 +-
 nptl/sem_wait.c                                                 |  3 +-
 nptl/sem_waitcommon.c                                           | 15 +-
 nptl/tst-sem13.c                                                | 39 +++-
 nptl/tst-sem17.c                                                | 76 +++++++-
 nptl/tst-sem5.c                                                 | 23 +-
 sysdeps/pthread/semaphore.h                                     |  7 +-
 sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |  1 +-
 sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |  1 +-
 sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |  1 +-
 sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |  1 +-
 sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |  1 +-
 sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |  1 +-
 sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |  1 +-
 sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |  1 +-
 sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |  1 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |  1 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |  1 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |  1 +-
 sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |  1 +-
 sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |  1 +-
 sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |  1 +-
 sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |  1 +-
 sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |  1 +-
 sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |  1 +-
 sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |  1 +-
 sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |  1 +-
 36 files changed, 305 insertions(+), 20 deletions(-)
 create mode 100644 nptl/sem_clockwait.c
 create mode 100644 nptl/tst-sem17.c

diff --git a/ChangeLog b/ChangeLog
index ff85b12..814e331 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,76 @@
 2019-05-27  Mike Crowe  <mac@mcrowe.com>
 
+	nptl: Add POSIX-proposed sem_clockwait which behaves just like
+	sem_timedwait, but measures abstime against the specified clock.
+
+	* nptl/sem_waitcommon.c (do_futex_wait, __new_sem_wait_slow): Add
+	clockid parameters to indicate the clock which abstime should be
+	measured against.
+
+	* nptl/sem_timedwait.c (sem_timedwait), nptl/sem_wait.c
+	(__new_sem_wait): Pass CLOCK_REALTIME as clockid to
+	__new_sem_wait_slow.
+
+	* nptl/sem_clockwait.c: New file to implement sem_clockwait based
+	on sem_timedwait.c.
+
+	* nptl/Makefile: Add sem_clockwait.c source file. Add CFLAGS for
+	sem_clockwait.c to match those used for sem_timedwait.c.
+
+	* sysdeps/pthread/semaphore.h: Add sem_clockwait.
+
+	* nptl/Versions (GLIBC_2.30): Likewise.
+
+	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+
+	* nptl/tst-sem17.c: Add new test for passing invalid clock to
+	sem_clockwait.
+
+	* nptl/tst-sem13.c, nptl/tst-sem5.c: Modify existing sem_timedwait
+	tests to also test sem_clockwait.
+
+	* manual/threads.texi: Document sem_clockwait.
+
+2019-05-27  Mike Crowe  <mac@mcrowe.com>
+
 	nptl: Add clockid parameter to futex timed wait calls
 
 	* sysdeps/nptl/lowlevellock-futex.h,
diff --git a/manual/threads.texi b/manual/threads.texi
index 87fda7d..674267c 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -669,6 +669,16 @@ The system does not have sufficient memory.
 @end table
 @end deftypefun
 
+@comment semaphore.h
+@comment POSIX-proposed
+@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clockid},
+                               const struct timespec *@var{abstime})
+Behaves like @code{sem_timedwait} except the time @var{abstime} is measured
+against the clock specified by @var{clockid} rather than
+@code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
+@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
+@end deftypefun
+
 @c FIXME these are undocumented:
 @c pthread_atfork
 @c pthread_attr_destroy
diff --git a/nptl/Makefile b/nptl/Makefile
index de312b3..43a99dc 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -113,7 +113,7 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
 		      sem_init sem_destroy \
 		      sem_open sem_close sem_unlink \
 		      sem_getvalue \
-		      sem_wait sem_timedwait sem_post \
+		      sem_wait sem_timedwait sem_clockwait sem_post \
 		      cleanup cleanup_defer cleanup_compat \
 		      cleanup_defer_compat unwind \
 		      pt-longjmp pt-cleanup\
@@ -193,6 +193,7 @@ CFLAGS-pthread_once.c += $(uses-callbacks) -fexceptions \
 CFLAGS-pthread_cond_wait.c += -fexceptions -fasynchronous-unwind-tables
 CFLAGS-sem_wait.c += -fexceptions -fasynchronous-unwind-tables
 CFLAGS-sem_timedwait.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-sem_clockwait.c = -fexceptions -fasynchronous-unwind-tables
 
 # These are the function wrappers we have to duplicate here.
 CFLAGS-fcntl.c += -fexceptions -fasynchronous-unwind-tables
@@ -262,7 +263,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-key1 tst-key2 tst-key3 tst-key4 \
 	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
 	tst-sem8 tst-sem9 tst-sem10 tst-sem14 \
-	tst-sem15 tst-sem16 \
+	tst-sem15 tst-sem16 tst-sem17 \
 	tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
 	tst-align tst-align3 \
 	tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
diff --git a/nptl/Versions b/nptl/Versions
index e7f691d..cd1806c 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -277,6 +277,10 @@ libpthread {
     cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
   }
 
+  GLIBC_2.30 {
+    sem_clockwait;
+  }
+
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
     __pthread_clock_gettime; __pthread_clock_settime;
diff --git a/nptl/sem_clockwait.c b/nptl/sem_clockwait.c
new file mode 100644
index 0000000..c0cd667
--- /dev/null
+++ b/nptl/sem_clockwait.c
@@ -0,0 +1,45 @@
+/* sem_clockwait -- wait on a semaphore with timeout using
+   the specified clock.
+
+   Copyright (C) 2003-2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "sem_waitcommon.c"
+
+int
+sem_clockwait (sem_t *sem, clockid_t clockid,
+	       const struct timespec *abstime)
+{
+  /* Check that supplied clockid is one we support, even if we don't
+     end up waiting. */
+  if (!futex_abstimed_supported_clockid (clockid))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow ((struct new_sem *) sem, clockid, abstime);
+}
diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
index 3dd71ab..0918d8b 100644
--- a/nptl/sem_timedwait.c
+++ b/nptl/sem_timedwait.c
@@ -36,5 +36,6 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
   if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
     return 0;
   else
-    return __new_sem_wait_slow((struct new_sem *) sem, abstime);
+    return __new_sem_wait_slow ((struct new_sem *) sem,
+				CLOCK_REALTIME, abstime);
 }
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index 6a2d26b..20a8b9d 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -39,7 +39,8 @@ __new_sem_wait (sem_t *sem)
   if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
     return 0;
   else
-    return __new_sem_wait_slow((struct new_sem *) sem, NULL);
+    return __new_sem_wait_slow ((struct new_sem *) sem,
+				CLOCK_REALTIME, NULL);
 }
 versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
 
diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
index 425d040..cad56e9 100644
--- a/nptl/sem_waitcommon.c
+++ b/nptl/sem_waitcommon.c
@@ -103,19 +103,19 @@ __sem_wait_cleanup (void *arg)
    users don't seem to need it.  */
 static int
 __attribute__ ((noinline))
-do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
+do_futex_wait (struct new_sem *sem, clockid_t clockid,
+	       const struct timespec *abstime)
 {
   int err;
 
 #if __HAVE_64B_ATOMICS
   err = futex_abstimed_wait_cancelable (
       (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0,
-      CLOCK_REALTIME, abstime,
+      clockid, abstime,
       sem->private);
 #else
   err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
-					CLOCK_REALTIME, abstime,
-					sem->private);
+					clockid, abstime, sem->private);
 #endif
 
   return err;
@@ -162,7 +162,8 @@ __new_sem_wait_fast (struct new_sem *sem, int definitive_result)
 /* Slow path that blocks.  */
 static int
 __attribute__ ((noinline))
-__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
+__new_sem_wait_slow (struct new_sem *sem, clockid_t clockid,
+		     const struct timespec *abstime)
 {
   int err = 0;
 
@@ -180,7 +181,7 @@ __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
       /* If there is no token available, sleep until there is.  */
       if ((d & SEM_VALUE_MASK) == 0)
 	{
-	  err = do_futex_wait (sem, abstime);
+	  err = do_futex_wait (sem, clockid, abstime);
 	  /* A futex return value of 0 or EAGAIN is due to a real or spurious
 	     wake-up, or due to a change in the number of tokens.  We retry in
 	     these cases.
@@ -281,7 +282,7 @@ __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
 	  if ((v >> SEM_VALUE_SHIFT) == 0)
 	    {
 	      /* See __HAVE_64B_ATOMICS variant.  */
-	      err = do_futex_wait(sem, abstime);
+	      err = do_futex_wait (sem, clockid, abstime);
 	      if (err == ETIMEDOUT || err == EINTR)
 		{
 		  __set_errno (err);
diff --git a/nptl/tst-sem13.c b/nptl/tst-sem13.c
index 28d37ed..21c3b7e 100644
--- a/nptl/tst-sem13.c
+++ b/nptl/tst-sem13.c
@@ -6,9 +6,14 @@
 #include <internaltypes.h>
 #include <support/check.h>
 
+/* A bogus clock value that tells run_test to use
+   sem_timedwait rather than sem_clockwait */
+#define CLOCK_USE_TIMEDWAIT (-1)
 
-static int
-do_test (void)
+typedef int (*waitfn_t)(sem_t *, struct timespec *);
+
+static void
+do_test_wait (waitfn_t waitfn, const char *fnname)
 {
   union
   {
@@ -16,11 +21,13 @@ do_test (void)
     struct new_sem ns;
   } u;
 
+  printf ("do_test_wait: %s\n", fnname);
+
   TEST_COMPARE (sem_init (&u.s, 0, 0), 0);
 
   struct timespec ts = { 0, 1000000001 };	/* Invalid.  */
   errno = 0;
-  TEST_VERIFY_EXIT (sem_timedwait (&u.s, &ts) < 0);
+  TEST_VERIFY_EXIT (waitfn (&u.s, &ts) < 0);
   TEST_COMPARE (errno, EINVAL);
 
 #if __HAVE_64B_ATOMICS
@@ -33,7 +40,7 @@ do_test (void)
   ts.tv_sec = /* Invalid.  */ -2;
   ts.tv_nsec = 0;
   errno = 0;
-  TEST_VERIFY_EXIT (sem_timedwait (&u.s, &ts) < 0);
+  TEST_VERIFY_EXIT (waitfn (&u.s, &ts) < 0);
   TEST_COMPARE (errno, ETIMEDOUT);
 #if __HAVE_64B_ATOMICS
   nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT);
@@ -41,7 +48,31 @@ do_test (void)
   nwaiters = u.ns.nwaiters;
 #endif
   TEST_COMPARE (nwaiters, 0);
+}
 
+int test_sem_timedwait (sem_t *sem, struct timespec *ts)
+{
+  return sem_timedwait (sem, ts);
+}
+
+int test_sem_clockwait_monotonic (sem_t *sem, struct timespec *ts)
+{
+  return sem_clockwait (sem, CLOCK_MONOTONIC, ts);
+}
+
+int test_sem_clockwait_realtime (sem_t *sem, struct timespec *ts)
+{
+  return sem_clockwait (sem, CLOCK_REALTIME, ts);
+}
+
+static int do_test (void)
+{
+  do_test_wait (&test_sem_timedwait,
+                "sem_timedwait");
+  do_test_wait (&test_sem_clockwait_monotonic,
+                "sem_clockwait(monotonic)");
+  do_test_wait (&test_sem_clockwait_realtime,
+                "sem_clockwait(realtime)");
   return 0;
 }
 
diff --git a/nptl/tst-sem17.c b/nptl/tst-sem17.c
new file mode 100644
index 0000000..78c52c8
--- /dev/null
+++ b/nptl/tst-sem17.c
@@ -0,0 +1,76 @@
+/* Test unsupported/bad clocks passed to sem_clockwait.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <support/check.h>
+#include <support/timespec.h>
+
+
+#define NOT_A_VALID_CLOCK 123456
+
+static int
+do_test (void)
+{
+  sem_t s;
+  TEST_COMPARE (sem_init (&s, 0, 1), 0);
+
+  const struct timespec ts = make_timespec (0, 0);
+
+  /* These clocks are meaningless to sem_clockwait. */
+#if defined(CLOCK_PROCESS_CPUTIME_ID)
+  TEST_COMPARE (sem_clockwait (&s, CLOCK_PROCESS_CPUTIME_ID, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+#endif
+#if defined(CLOCK_THREAD_CPUTIME_ID)
+  TEST_COMPARE (sem_clockwait (&s, CLOCK_THREAD_CPUTIME_ID, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+#endif
+
+  /* These clocks might be meaningful, but are currently unsupported
+     by pthread_cond_clockwait. */
+#if defined(CLOCK_REALTIME_COARSE)
+  TEST_COMPARE (sem_clockwait (&s, CLOCK_REALTIME_COARSE, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+#endif
+#if defined(CLOCK_MONOTONIC_RAW)
+  TEST_COMPARE (sem_clockwait (&s, CLOCK_MONOTONIC_RAW, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+#endif
+#if defined(CLOCK_MONOTONIC_COARSE)
+  TEST_COMPARE (sem_clockwait (&s, CLOCK_MONOTONIC_COARSE, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+#endif
+#if defined(CLOCK_BOOTTIME)
+  TEST_COMPARE (sem_clockwait (&s, CLOCK_BOOTTIME, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+#endif
+
+  /* This is a completely invalid clock */
+  TEST_COMPARE (sem_clockwait (&s, NOT_A_VALID_CLOCK, &ts), -1);
+  TEST_COMPARE (errno, EINVAL);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-sem5.c b/nptl/tst-sem5.c
index 396222b..843839b 100644
--- a/nptl/tst-sem5.c
+++ b/nptl/tst-sem5.c
@@ -25,10 +25,15 @@
 #include <support/timespec.h>
 #include <support/xtime.h>
 
+/* A bogus clock value that tells run_test to use
+   sem_timedwait rather than sem_clockwait */
+#define CLOCK_USE_TIMEDWAIT (-1)
 
-static int
-do_test (void)
+static void
+do_test_clock (clockid_t clockid)
 {
+  const clockid_t clockid_for_get =
+    clockid == CLOCK_USE_TIMEDWAIT ? CLOCK_REALTIME : clockid;
   sem_t s;
   struct timespec ts;
 
@@ -36,14 +41,22 @@ do_test (void)
   TEST_COMPARE (TEMP_FAILURE_RETRY (sem_wait (&s)), 0);
 
   /* We wait for half a second.  */
-  xclock_gettime (CLOCK_REALTIME, &ts);
+  xclock_gettime (clockid_for_get, &ts);
   ts = timespec_add (ts, make_timespec (0, TIMESPEC_HZ/2));
 
   errno = 0;
-  TEST_COMPARE (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)), -1);
+  TEST_COMPARE (TEMP_FAILURE_RETRY ((clockid == CLOCK_USE_TIMEDWAIT)
+                                    ? sem_timedwait (&s, &ts)
+                                    : sem_clockwait (&s, clockid, &ts)), -1);
   TEST_COMPARE (errno, ETIMEDOUT);
-  TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts);
+  TEST_TIMESPEC_NOW_OR_AFTER (clockid_for_get, ts);
+}
 
+static int do_test (void)
+{
+  do_test_clock (CLOCK_USE_TIMEDWAIT);
+  do_test_clock (CLOCK_REALTIME);
+  do_test_clock (CLOCK_MONOTONIC);
   return 0;
 }
 
diff --git a/sysdeps/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
index 87c0543..6e74aa3 100644
--- a/sysdeps/pthread/semaphore.h
+++ b/sysdeps/pthread/semaphore.h
@@ -64,6 +64,13 @@ extern int sem_timedwait (sem_t *__restrict __sem,
   __nonnull ((1, 2));
 #endif
 
+#ifdef __USE_GNU
+extern int sem_clockwait (sem_t *__restrict __sem,
+			  clockid_t clock,
+			  const struct timespec *__restrict __abstime)
+  __nonnull ((1, 3));
+#endif
+
 /* Test whether SEM is posted.  */
 extern int sem_trywait (sem_t *__sem) __THROWNL __nonnull ((1));
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
index 9a9e4ce..0294cb3 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
index b413007..1f63759 100644
--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
 GLIBC_2.3.2 pthread_cond_init F
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index af82a4c..905392e 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
 GLIBC_2.4 _IO_funlockfile F
diff --git a/sysdeps/unix/sysv/linux/csky/libpthread.abilist b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
index ea4b79a..fdf577c 100644
--- a/sysdeps/unix/sysv/linux/csky/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
@@ -233,3 +233,4 @@ GLIBC_2.29 tss_set F
 GLIBC_2.29 wait F
 GLIBC_2.29 waitpid F
 GLIBC_2.29 write F
+GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
index bcba07f..fa02154 100644
--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
@@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index bece86d..86eb656 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
index ccc9449..406da6f 100644
--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
@@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index af82a4c..905392e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
 GLIBC_2.4 _IO_funlockfile F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
index bece86d..86eb656 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
index 5067375..bd9455d 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
index 0214496..c1792c5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
index 0214496..c1792c5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
index 78cac2a..8eca3c2 100644
--- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
@@ -241,3 +241,4 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index 09e8447..ca68bd7 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.3.4 siglongjmp F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
index 8300958..9e0500d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
@@ -246,6 +246,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.3.4 siglongjmp F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
index 9a9e4ce..0294cb3 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
index c370fda..c6bddf9 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
@@ -235,3 +235,4 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
index d05468f..581e3be 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
index e8161aa..ed422c3 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
@@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
index bcba07f..fa02154 100644
--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
@@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
index b413007..e31e905 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
index ccc9449..406da6f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
@@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 931c827..454d340 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
 GLIBC_2.4 pthread_mutex_setprioceiling F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index c09c9b0..db565a1 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 sem_clockwait F
-- 
git-series 0.9.1

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

* [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait
  2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
  2019-05-27 20:03 ` [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls Mike Crowe
  2019-05-27 20:03 ` [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait Mike Crowe
@ 2019-05-27 20:03 ` Mike Crowe
  2019-06-06 12:53   ` Adhemerval Zanella
  2019-05-27 20:03 ` [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions Mike Crowe
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

Add:

 int pthread_cond_clockwait (pthread_cond_t *cond,
                             pthread_mutex_t *mutex,
                             clockid_t clockid,
                             const struct timespec *abstime)

which behaves just like pthread_cond_timedwait except it always measures
abstime against the supplied clockid. Currently supports CLOCK_REALTIME and
CLOCK_MONOTONIC and returns EINVAL if any other clock is specified.

Includes feedback from many others. This function was originally
proposed[1] as pthread_cond_timedwaitonclock_np, but The Austin Group
preferred the new name.

	* nptl/Makefile: Add tst-cond26 and tst-cond27

	* nptl/Versions (GLIBC_2.30): Add pthread_cond_clockwait

	* sysdeps/nptl/pthread.h: Likewise

	* nptl/forward.c: Add __pthread_cond_clockwait

	* nptl/forward.c: Likewise

	* nptl/pthreadP.h: Likewise

	* sysdeps/nptl/pthread-functions.h: Likewise

	* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Add
	clockid parameter and comment describing why we don't need to check
	its value. Use that value when calling
	futex_abstimed_wait_cancelable rather than reading the clock from
	the flags. (__pthread_cond_wait): Pass unused clockid parameter.
	(__pthread_cond_timedwait): Read clock from flags and pass it to
	__pthread_cond_wait_common. (__pthread_cond_clockwait): Add new
	function with weak alias from pthread_cond_clockwait.

	* sysdeps/mach/hurd/i386/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
	(GLIBC_2.30): Likewise.

	* nptl/tst-cond11.c (run_test): Support testing
	pthread_cond_clockwait too by using a special magic
	CLOCK_USE_ATTR_CLOCK value to determine whether to call
	pthread_cond_timedwait or pthread_cond_clockwait. (do_test): Pass
	CLOCK_USE_ATTR_CLOCK for existing tests, and add new tests using
	all combinations of CLOCK_MONOTONIC and CLOCK_REALTIME.

	* ntpl/tst-cond26.c: New test for passing unsupported and invalid
	clocks to pthread_cond_clockwait.

	* nptl/tst-cond27.c: Add test similar to tst-cond5.c, but using
	struct timespec and pthread_cond_clockwait.

	* manual/threads.texi: Document pthread_cond_clockwait. The comment
	was provided by Carlos O'Donell.

[1] https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
---
 ChangeLog                                                       | 85 +++++++-
 manual/threads.texi                                             | 20 ++-
 nptl/Makefile                                                   |  1 +-
 nptl/Versions                                                   |  2 +-
 nptl/forward.c                                                  |  5 +-
 nptl/nptl-init.c                                                |  1 +-
 nptl/pthreadP.h                                                 |  4 +-
 nptl/pthread_cond_wait.c                                        | 44 +++-
 nptl/tst-cond11.c                                               | 37 ++-
 nptl/tst-cond26.c                                               | 77 ++++++-
 nptl/tst-cond27.c                                               | 68 ++++++-
 sysdeps/nptl/pthread-functions.h                                |  4 +-
 sysdeps/nptl/pthread.h                                          | 15 +-
 sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |  1 +-
 sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |  1 +-
 sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |  1 +-
 sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |  1 +-
 sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |  1 +-
 sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |  1 +-
 sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |  1 +-
 sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |  1 +-
 sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |  1 +-
 sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |  1 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |  1 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |  1 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |  1 +-
 sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |  1 +-
 sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |  1 +-
 sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |  1 +-
 sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |  1 +-
 sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |  1 +-
 sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |  1 +-
 sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |  1 +-
 sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |  1 +-
 37 files changed, 369 insertions(+), 18 deletions(-)
 create mode 100644 nptl/tst-cond26.c
 create mode 100644 nptl/tst-cond27.c

diff --git a/ChangeLog b/ChangeLog
index 814e331..1f95dd4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,90 @@
 2019-05-27  Mike Crowe  <mac@mcrowe.com>
 
+	nptl: Add POSIX-proposed pthread_cond_clockwait which behaves just
+	like pthread_cond_timedwait except it always measures abstime
+	against the supplied clockid.
+
+	* nptl/Makefile: Add tst-cond26 and tst-cond27
+
+	* nptl/Versions (GLIBC_2.30): Add pthread_cond_clockwait
+
+	* sysdeps/nptl/pthread.h: Likewise
+
+	* nptl/forward.c: Add __pthread_cond_clockwait
+
+	* nptl/forward.c: Likewise
+
+	* nptl/pthreadP.h: Likewise
+
+	* sysdeps/nptl/pthread-functions.h: Likewise
+
+	* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Add
+	clockid parameter and comment describing why we don't need to check
+	its value. Use that value when calling
+	futex_abstimed_wait_cancelable rather than reading the clock from
+	the flags. (__pthread_cond_wait): Pass unused clockid parameter.
+	(__pthread_cond_timedwait): Read clock from flags and pass it to
+	__pthread_cond_wait_common. (__pthread_cond_clockwait): Add new
+	function with weak alias from pthread_cond_clockwait.
+
+	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+
+	* nptl/tst-cond11.c (run_test): Support testing
+	pthread_cond_clockwait too by using a special magic
+	CLOCK_USE_ATTR_CLOCK value to determine whether to call
+	pthread_cond_timedwait or pthread_cond_clockwait. (do_test): Pass
+	CLOCK_USE_ATTR_CLOCK for existing tests, and add new tests using
+	all combinations of CLOCK_MONOTONIC and CLOCK_REALTIME.
+
+	* ntpl/tst-cond26.c: New test for passing unsupported and invalid
+	clocks to pthread_cond_clockwait.
+
+	* nptl/tst-cond27.c: Add test similar to tst-cond5.c, but using
+	struct timespec and pthread_cond_clockwait.
+
+	* manual/threads.texi: Document pthread_cond_clockwait. The comment
+	was provided by Carlos O'Donell.
+
+2019-05-27  Mike Crowe  <mac@mcrowe.com>
+
 	nptl: Add POSIX-proposed sem_clockwait which behaves just like
 	sem_timedwait, but measures abstime against the specified clock.
 
diff --git a/manual/threads.texi b/manual/threads.texi
index 674267c..91462f5 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -679,6 +679,26 @@ against the clock specified by @var{clockid} rather than
 @code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
 @end deftypefun
 
+@comment pthread.h
+@comment POSIX-proposed
+@deftypefun int pthread_cond_clockwait (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 @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,
+@var{clockid} must be either @code{CLOCK_MONOTONIC} or
+@code{CLOCK_REALTIME}.
+@end deftypefun
+
 @c FIXME these are undocumented:
 @c pthread_atfork
 @c pthread_attr_destroy
diff --git a/nptl/Makefile b/nptl/Makefile
index 43a99dc..70a2139 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -250,6 +250,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-cond8 tst-cond9 tst-cond10 tst-cond11 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-cond26 tst-cond27 \
 	tst-cond-except \
 	tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
 	tst-robust6 tst-robust7 tst-robust8 tst-robust9 \
diff --git a/nptl/Versions b/nptl/Versions
index cd1806c..8c094d0 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -278,7 +278,7 @@ libpthread {
   }
 
   GLIBC_2.30 {
-    sem_clockwait;
+    sem_clockwait; pthread_cond_clockwait;
   }
 
   GLIBC_PRIVATE {
diff --git a/nptl/forward.c b/nptl/forward.c
index ed1e7d0..50f358f 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_clockwait,
+	 (pthread_cond_t *cond, pthread_mutex_t *mutex, clockid_t clockid,
+	  const struct timespec *abstime), (cond, mutex, clockid, abstime),
+	 0)
+weak_alias (__pthread_cond_clockwait, pthread_cond_clockwait);
 
 
 FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 73935f8..9c2a3d7 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -95,6 +95,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_clockwait = __pthread_cond_clockwait,
 # 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 66527d8..9caa2b4 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -449,6 +449,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_clockwait (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 7385562..558f930 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;
@@ -386,6 +387,11 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 
   LIBC_PROBE (cond_wait, 2, cond, mutex);
 
+  /* clockid will already have been checked by
+     __pthread_cond_clockwait or pthread_condattr_setclock, or we
+     don't use it if abstime is NULL, so we don't need to check it
+     here. */
+
   /* Acquire a position (SEQ) in the waiter sequence (WSEQ).  We use an
      atomic operation because signals and broadcasts may update the group
      switch without acquiring the mutex.  We do not need release MO here
@@ -511,10 +517,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
 	        err = ETIMEDOUT;
 	      else
 		{
-		  const clockid_t clockid =
-		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
-		    CLOCK_MONOTONIC : CLOCK_REALTIME;
-
 		  err = futex_abstimed_wait_cancelable
                     (cond->__data.__g_signals + g, 0, clockid, abstime,
                      private);
@@ -632,7 +634,8 @@ __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);
+  /* clockid is unused when abstime is NULL. */
+  return __pthread_cond_wait_common (cond, mutex, 0, NULL);
 }
 
 /* See __pthread_cond_wait_common.  */
@@ -644,10 +647,39 @@ __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);
+
+  /* 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 clockid = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
+                    ? CLOCK_MONOTONIC : CLOCK_REALTIME;
+  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
+}
+
+/* See __pthread_cond_wait_common.  */
+int
+__pthread_cond_clockwait (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;
+
+  if (!futex_abstimed_supported_clockid (clockid))
+    return EINVAL;
+
+  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
+  if (clockid == CLOCK_MONOTONIC
+      && !futex_supports_exact_relative_timeouts ())
+    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_clockwait, pthread_cond_clockwait);
diff --git a/nptl/tst-cond11.c b/nptl/tst-cond11.c
index 3bc4ff4..e42e71d 100644
--- a/nptl/tst-cond11.c
+++ b/nptl/tst-cond11.c
@@ -26,24 +26,27 @@
 #include <support/xthread.h>
 #include <support/xtime.h>
 
+/* A bogus clock value that tells run_test to use
+   pthread_cond_timedwait rather than pthread_condclockwait. */
+#define CLOCK_USE_ATTR_CLOCK (-1)
 
 #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
 static int
-run_test (clockid_t cl)
+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 ("clock = %d\n", (int) cl);
+  printf ("attr_clock = %d\n", (int) attr_clock);
 
   TEST_COMPARE (pthread_condattr_init (&condattr), 0);
-  TEST_COMPARE (pthread_condattr_setclock (&condattr, cl), 0);
+  TEST_COMPARE (pthread_condattr_setclock (&condattr, attr_clock), 0);
 
-  clockid_t cl2;
-  TEST_COMPARE (pthread_condattr_getclock (&condattr, &cl2), 0);
-  TEST_COMPARE (cl, cl2);
+  clockid_t attr_clock_read;
+  TEST_COMPARE (pthread_condattr_getclock (&condattr, &attr_clock_read), 0);
+  TEST_COMPARE (attr_clock, attr_clock_read);
 
   TEST_COMPARE (pthread_cond_init (&cond, &condattr), 0);
   TEST_COMPARE (pthread_condattr_destroy (&condattr), 0);
@@ -57,13 +60,20 @@ run_test (clockid_t cl)
   TEST_COMPARE (pthread_mutex_lock (&mut), EDEADLK);
 
   struct timespec ts_timeout;
-  xclock_gettime (cl, &ts_timeout);
+  xclock_gettime (wait_clock == CLOCK_USE_ATTR_CLOCK ? attr_clock : wait_clock,
+                  &ts_timeout);
 
   /* Wait one second.  */
   ++ts_timeout.tv_sec;
 
-  TEST_COMPARE (pthread_cond_timedwait (&cond, &mut, &ts_timeout), ETIMEDOUT);
-  TEST_TIMESPEC_BEFORE_NOW (ts_timeout, cl);
+  if (wait_clock == CLOCK_USE_ATTR_CLOCK) {
+    TEST_COMPARE (pthread_cond_timedwait (&cond, &mut, &ts_timeout), ETIMEDOUT);
+    TEST_TIMESPEC_BEFORE_NOW (ts_timeout, attr_clock);
+  } else {
+    TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, wait_clock, &ts_timeout),
+                  ETIMEDOUT);
+    TEST_TIMESPEC_BEFORE_NOW (ts_timeout, wait_clock);
+  }
 
   xpthread_mutex_unlock (&mut);
   xpthread_mutex_destroy (&mut);
@@ -83,7 +93,7 @@ do_test (void)
 
 #else
 
-  run_test (CLOCK_REALTIME);
+  run_test (CLOCK_REALTIME, CLOCK_USE_ATTR_CLOCK);
 
 # if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
 #  if _POSIX_MONOTONIC_CLOCK == 0
@@ -93,8 +103,13 @@ do_test (void)
   else if (e == 0)
       FAIL_RET ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
   else
+    {
 #  endif
-    run_test (CLOCK_MONOTONIC);
+      run_test (CLOCK_MONOTONIC, CLOCK_USE_ATTR_CLOCK);
+      run_test (CLOCK_REALTIME, CLOCK_MONOTONIC);
+      run_test (CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+      run_test (CLOCK_MONOTONIC, CLOCK_REALTIME);
+    }
 # else
   puts ("_POSIX_MONOTONIC_CLOCK not defined");
 # endif
diff --git a/nptl/tst-cond26.c b/nptl/tst-cond26.c
new file mode 100644
index 0000000..2db7d2e
--- /dev/null
+++ b/nptl/tst-cond26.c
@@ -0,0 +1,77 @@
+/* Test unsupported/bad clocks passed to pthread_cond_clockwait.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <support/check.h>
+#include <support/timespec.h>
+#include <support/xthread.h>
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+#define NOT_A_VALID_CLOCK 123456
+
+static int
+do_test (void)
+{
+  xpthread_mutex_lock (&mut);
+
+  const struct timespec ts = make_timespec (0, 0);
+
+  /* These clocks are meaningless to sem_clockwait. */
+#if defined(CLOCK_PROCESS_CPUTIME_ID)
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        CLOCK_PROCESS_CPUTIME_ID, &ts), EINVAL);
+#endif
+#if defined(CLOCK_THREAD_CPUTIME_ID)
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        CLOCK_THREAD_CPUTIME_ID, &ts), EINVAL);
+#endif
+
+  /* These clocks might be meaningful, but are currently unsupported
+     by pthread_cond_clockwait. */
+#if defined(CLOCK_REALTIME_COARSE)
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        CLOCK_REALTIME_COARSE, &ts), EINVAL);
+#endif
+#if defined(CLOCK_MONOTONIC_RAW)
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        CLOCK_MONOTONIC_RAW, &ts), EINVAL);
+#endif
+#if defined(CLOCK_MONOTONIC_COARSE)
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        CLOCK_MONOTONIC_COARSE, &ts), EINVAL);
+#endif
+#if defined(CLOCK_BOOTTIME)
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        CLOCK_BOOTTIME, &ts), EINVAL);
+#endif
+
+  /* This is a completely invalid clock */
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
+                                        NOT_A_VALID_CLOCK, &ts), EINVAL);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-cond27.c b/nptl/tst-cond27.c
new file mode 100644
index 0000000..8d20663
--- /dev/null
+++ b/nptl/tst-cond27.c
@@ -0,0 +1,68 @@
+/* Test pthread_cond_clockwait timeout.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <support/check.h>
+#include <support/timespec.h>
+#include <support/xthread.h>
+
+
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+
+static int
+do_test_clock (clockid_t clockid)
+{
+  /* Get the mutex.  */
+  xpthread_mutex_lock (&mut);
+
+  /* Waiting for the condition will fail.  But we want the timeout here.  */
+  struct timespec ts_now;
+  xclock_gettime (clockid, &ts_now);
+
+  const struct timespec ts_timeout =
+    timespec_add (ts_now, make_timespec (0, 500000000));
+
+  /* In theory pthread_cond_clockwait could return zero here due to
+     spurious wakeup. However that can't happen without a signal or an
+     additional waiter. */
+  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, clockid, &ts_timeout),
+                ETIMEDOUT);
+
+  xpthread_mutex_unlock (&mut);
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  do_test_clock (CLOCK_MONOTONIC);
+  do_test_clock (CLOCK_REALTIME);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/nptl/pthread-functions.h b/sysdeps/nptl/pthread-functions.h
index cd5e94d..cfa9660 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_clockwait) (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 704a3c4..f000b1e 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_clockwait (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/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
index 0294cb3..5af4b8a 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
@@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
index 1f63759..a00adfb 100644
--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
@@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index 905392e..4aeee7b 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
diff --git a/sysdeps/unix/sysv/linux/csky/libpthread.abilist b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
index fdf577c..2c08b76 100644
--- a/sysdeps/unix/sysv/linux/csky/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
@@ -233,4 +233,5 @@ GLIBC_2.29 tss_set F
 GLIBC_2.29 wait F
 GLIBC_2.29 waitpid F
 GLIBC_2.29 write F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
index fa02154..dc0d4ad 100644
--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
@@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index 86eb656..1830e40 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
index 406da6f..0811d73 100644
--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
@@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index 905392e..4aeee7b 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 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 86eb656..1830e40 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
index bd9455d..f2be6b4 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
@@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
index c1792c5..41527fe 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
index c1792c5..41527fe 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
index 8eca3c2..04fc3a6 100644
--- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
@@ -241,4 +241,5 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index ca68bd7..ebdab1a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.3.4 siglongjmp F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
index 9e0500d..8a1fb34 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
@@ -246,6 +246,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.3.4 siglongjmp F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
index 0294cb3..5af4b8a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
@@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
index c6bddf9..a1c8c2e 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
@@ -235,4 +235,5 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
index 581e3be..0feb3cf 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
index ed422c3..cc4f160 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
@@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
index fa02154..dc0d4ad 100644
--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
@@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
index e31e905..ed0574a 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
@@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
index 406da6f..0811d73 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
@@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 454d340..aaa1c3b 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
 GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index db565a1..5d02b03 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
 GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
+GLIBC_2.30 pthread_cond_clockwait F
 GLIBC_2.30 sem_clockwait F
-- 
git-series 0.9.1

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

* [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions
  2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
                   ` (2 preceding siblings ...)
  2019-05-27 20:03 ` [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait Mike Crowe
@ 2019-05-27 20:03 ` Mike Crowe
  2019-06-06 19:18   ` Adhemerval Zanella
  2019-05-27 20:03 ` [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock Mike Crowe
  2019-05-27 20:03 ` [PATCH v3 6/6] Update NEWS for new _clockwait functions Mike Crowe
  5 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

As recommended by the comments in the implementations of
pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock, let's move the
timeout validity checks into the corresponding pthread_rwlock_rdlock_full
and pthread_rwlock_wrlock_full functions. Since these functions may be
called with abstime == NULL, an extra check for that is necessary too.

	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full):
	Check validity of abstime parameter.
	(__pthread_rwlock_rwlock_full): Likewise.

	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
	Remove check for validity of abstime parameter.

	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
	Likewise.
---
 ChangeLog                         | 14 ++++++++++++++
 nptl/pthread_rwlock_common.c      | 20 ++++++++++++++++++++
 nptl/pthread_rwlock_timedrdlock.c | 10 ----------
 nptl/pthread_rwlock_timedwrlock.c | 10 ----------
 4 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1f95dd4..22a8bdc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2019-05-27  Mike Crowe  <mac@mcrowe.com>
 
+	nptl: pthread_rwlock: Move timeout validation into _full functions
+
+	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full):
+	Check validity of abstime parameter.
+	(__pthread_rwlock_rwlock_full): Likewise.
+
+	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
+	Remove check for validity of abstime parameter.
+
+	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
+	Likewise.
+
+2019-05-27  Mike Crowe  <mac@mcrowe.com>
+
 	nptl: Add POSIX-proposed pthread_cond_clockwait which behaves just
 	like pthread_cond_timedwait except it always measures abstime
 	against the supplied clockid.
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index 89ba21a..120b880 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -282,6 +282,16 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 {
   unsigned int r;
 
+  /* Make sure any passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  if (abstime
+      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
   /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
      situation we recognize and report.  */
   if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
@@ -576,6 +586,16 @@ static __always_inline int
 __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
     const struct timespec *abstime)
 {
+  /* Make sure any passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  if (abstime
+      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
   /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
      situation we recognize and report.  */
   if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c
index aa00530..84c1983 100644
--- a/nptl/pthread_rwlock_timedrdlock.c
+++ b/nptl/pthread_rwlock_timedrdlock.c
@@ -23,15 +23,5 @@ int
 pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
     const struct timespec *abstime)
 {
-  /* Make sure the passed in timeout value is valid.  Note that the previous
-     implementation assumed that this check *must* not be performed if there
-     would in fact be no blocking; however, POSIX only requires that "the
-     validity of the abstime parameter need not be checked if the lock can be
-     immediately acquired" (i.e., we need not but may check it).  */
-  /* ??? Just move this to __pthread_rwlock_rdlock_full?  */
-  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
-      || abstime->tv_nsec < 0))
-    return EINVAL;
-
   return __pthread_rwlock_rdlock_full (rwlock, abstime);
 }
diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
index 3c92e44..f0b745d 100644
--- a/nptl/pthread_rwlock_timedwrlock.c
+++ b/nptl/pthread_rwlock_timedwrlock.c
@@ -23,15 +23,5 @@ int
 pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
     const struct timespec *abstime)
 {
-  /* Make sure the passed in timeout value is valid.  Note that the previous
-     implementation assumed that this check *must* not be performed if there
-     would in fact be no blocking; however, POSIX only requires that "the
-     validity of the abstime parameter need not be checked if the lock can be
-     immediately acquired" (i.e., we need not but may check it).  */
-  /* ??? Just move this to __pthread_rwlock_wrlock_full?  */
-  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
-      || abstime->tv_nsec < 0))
-    return EINVAL;
-
   return __pthread_rwlock_wrlock_full (rwlock, abstime);
 }
-- 
git-series 0.9.1

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

* [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock
  2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
                   ` (3 preceding siblings ...)
  2019-05-27 20:03 ` [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions Mike Crowe
@ 2019-05-27 20:03 ` Mike Crowe
  2019-06-07 14:05   ` Adhemerval Zanella
  2019-05-27 20:03 ` [PATCH v3 6/6] Update NEWS for new _clockwait functions Mike Crowe
  5 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

Add:
 int pthread_rwlock_clockrdlock (pthread_rwlock_t *rwlock,
                                 clockid_t clockid,
                                 const struct timespec *abstime)
and:
 int pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
                                 clockid_t clockid,
                                 const struct timespec *abstime)

which behave like pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock
respectively, except they always measure abstime against the supplied
clockid. The functions currently support CLOCK_REALTIME and CLOCK_MONOTONIC
and return EINVAL if any other clock is specified.

	* sysdeps/nptl/pthread.h: Add pthread_rwlock_clockrdlock and
	pthread_wrlock_clockwrlock.

	* nptl/Makefile: Build pthread_rwlock_clockrdlock.c and
	pthread_rwlock_clockwrlock.c.

	* nptl/pthread_rwlock_clockrdlock.c: Implement
	pthread_rwlock_clockrdlock.

	* nptl/pthread_rwlock_clockwrlock.c: Implement
	pthread_rwlock_clockwrlock.

	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full): Add
	clockid parameter and verify that it indicates a supported clock on
	entry so that we fail even if it doesn't end up being used. Pass
	that clock on to futex_abstimed_wait when necessary.
	(__pthread_rwlock_wrlock_full): Likewise.

	* nptl/pthread_rwlock_rdlock.c: (__pthread_rwlock_rdlock): Pass
	CLOCK_REALTIME to __pthread_rwlock_rdlock_full even though it won't
	be used because there's no timeout.

	* nptl/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Pass
	CLOCK_REALTIME to __pthread_rwlock_wrlock_full even though it won't
	be used because there is no timeout.

	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
	Pass CLOCK_REALTIME to __pthread_rwlock_rdlock_full since abstime
	uses that clock.

	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
	Pass CLOCK_REALTIME to __pthread_rwlock_wrlock_full since abstime
	uses that clock.

	* sysdeps/mach/hurd/i386/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
	(GLIBC_2.30): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
	(GLIBC_2.30): Likewise.

	* nptl/tst-abstime.c (th): Add pthread_rwlock_clockrdlock and
	pthread_rwlock_clockwrlock timeout tests to match the existing
	pthread_rwlock_timedrdloock and pthread_rwlock_timedwrlock tests.

	* nptl/tst-rwlock14.c (do_test): Likewise.

	* nptl/tst-rwlock6.c (tf): Accept thread_args structure so that
	rwlock, a clockid and function name can be passed to the thread.
	(do_test_clock): Rename from do_test. Accept clockid parameter to
	specify test clock. Use the magic clockid value of
	CLOCK_USE_TIMEDLOCK to indicate that pthread_rwlock_timedrdlock and
	pthread_rwlock_timedwrlock should be tested, otherwise pass the
	specified clockid to pthread_rwlock_clockrdlock and
	pthread_rwlock_clockwrlock. Use xpthread_create and xpthread_join.
	(do_test): Call do_test_clock to test each clockid in turn.

	* nptl/tst-rwlock7.c: Likewise.

	* nptl/tst-rwlock9.c (writer_thread, reader_thread): Accept
	thread_args structure so that the (now int) thread number, the
	clockid and the function name can be passed to the thread.
	(do_test_clock): Renamed from do_test. Pass the necessary
	thread_args when creating the reader and writer threads. Use
	xpthread_create and xpthread_join.
	(do_test): Call do_test_clock to test each clockid in turn.

	* manual/threads.texi: Add documentation for
	pthread_rwlock_clockrdlock and pthread_rwlock_clockwrclock.
---
 ChangeLog                                                       | 113 +++++++-
 manual/threads.texi                                             |  28 ++-
 nptl/Makefile                                                   |   2 +-
 nptl/Versions                                                   |   1 +-
 nptl/pthread_rwlock_clockrdlock.c                               |  29 ++-
 nptl/pthread_rwlock_clockwrlock.c                               |  29 ++-
 nptl/pthread_rwlock_common.c                                    |  40 +-
 nptl/pthread_rwlock_rdlock.c                                    |   2 +-
 nptl/pthread_rwlock_timedrdlock.c                               |   2 +-
 nptl/pthread_rwlock_timedwrlock.c                               |   2 +-
 nptl/pthread_rwlock_wrlock.c                                    |   2 +-
 nptl/tst-abstime.c                                              |   8 +-
 nptl/tst-rwlock14.c                                             |  12 +-
 nptl/tst-rwlock6.c                                              |  94 ++++--
 nptl/tst-rwlock7.c                                              |  83 +++--
 nptl/tst-rwlock9.c                                              | 102 ++++--
 sysdeps/nptl/pthread.h                                          |  14 +-
 sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |   2 +-
 sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |   2 +-
 sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |   2 +-
 sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |   2 +-
 sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |   2 +-
 sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |   2 +-
 sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |   2 +-
 sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |   2 +-
 sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |   2 +-
 sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |   2 +-
 sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |   2 +-
 sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |   2 +-
 sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |   2 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |   2 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |   2 +-
 sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |   2 +-
 sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |   2 +-
 sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |   2 +-
 sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |   2 +-
 sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |   2 +-
 sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |   2 +-
 sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |   2 +-
 sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |   2 +-
 sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |   2 +-
 41 files changed, 511 insertions(+), 100 deletions(-)
 create mode 100644 nptl/pthread_rwlock_clockrdlock.c
 create mode 100644 nptl/pthread_rwlock_clockwrlock.c

diff --git a/ChangeLog b/ChangeLog
index 22a8bdc..66589f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,118 @@
 2019-05-27  Mike Crowe  <mac@mcrowe.com>
 
+	nptl: Add POSIX-proposed pthread_rwlock_clockrdlock &
+	pthread_rwlock_clockwrlock which behave like
+	pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock
+	respectively, except they always measure abstime against the
+	supplied clockid. The functions currently support CLOCK_REALTIME
+	and CLOCK_MONOTONIC and return EINVAL if any other clock is
+	specified.
+
+	* sysdeps/nptl/pthread.h: Add pthread_rwlock_clockrdlock and
+	pthread_wrlock_clockwrlock.
+
+	* nptl/Makefile: Build pthread_rwlock_clockrdlock.c and
+	pthread_rwlock_clockwrlock.c.
+
+	* nptl/pthread_rwlock_clockrdlock.c: Implement
+	pthread_rwlock_clockrdlock.
+
+	* nptl/pthread_rwlock_clockwrlock.c: Implement
+	pthread_rwlock_clockwrlock.
+
+	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full): Add
+	clockid parameter and verify that it indicates a supported clock on
+	entry so that we fail even if it doesn't end up being used. Pass
+	that clock on to futex_abstimed_wait when necessary.
+	(__pthread_rwlock_wrlock_full): Likewise.
+
+	* nptl/pthread_rwlock_rdlock.c: (__pthread_rwlock_rdlock): Pass
+	CLOCK_REALTIME to __pthread_rwlock_rdlock_full even though it won't
+	be used because there's no timeout.
+
+	* nptl/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Pass
+	CLOCK_REALTIME to __pthread_rwlock_wrlock_full even though it won't
+	be used because there is no timeout.
+
+	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
+	Pass CLOCK_REALTIME to __pthread_rwlock_rdlock_full since abstime
+	uses that clock.
+
+	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
+	Pass CLOCK_REALTIME to __pthread_rwlock_wrlock_full since abstime
+	uses that clock.
+
+	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+	(GLIBC_2.30): Likewise.
+
+	* nptl/tst-abstime.c (th): Add pthread_rwlock_clockrdlock and
+	pthread_rwlock_clockwrlock timeout tests to match the existing
+	pthread_rwlock_timedrdloock and pthread_rwlock_timedwrlock tests.
+
+	* nptl/tst-rwlock14.c (do_test): Likewise.
+
+	* nptl/tst-rwlock6.c (tf): Accept thread_args structure so that
+	rwlock, a clockid and function name can be passed to the thread.
+	(do_test_clock): Rename from do_test. Accept clockid parameter to
+	specify test clock. Use the magic clockid value of
+	CLOCK_USE_TIMEDLOCK to indicate that pthread_rwlock_timedrdlock and
+	pthread_rwlock_timedwrlock should be tested, otherwise pass the
+	specified clockid to pthread_rwlock_clockrdlock and
+	pthread_rwlock_clockwrlock. Use xpthread_create and xpthread_join.
+	(do_test): Call do_test_clock to test each clockid in turn.
+
+	* nptl/tst-rwlock7.c: Likewise.
+
+	* nptl/tst-rwlock9.c (writer_thread, reader_thread): Accept
+	thread_args structure so that the (now int) thread number, the
+	clockid and the function name can be passed to the thread.
+	(do_test_clock): Renamed from do_test. Pass the necessary
+	thread_args when creating the reader and writer threads. Use
+	xpthread_create and xpthread_join.
+	(do_test): Call do_test_clock to test each clockid in turn.
+
+	* manual/threads.texi: Add documentation for
+	pthread_rwlock_clockrdlock and pthread_rwlock_clockwrclock.
+
+2019-05-27  Mike Crowe  <mac@mcrowe.com>
+
 	nptl: pthread_rwlock: Move timeout validation into _full functions
 
 	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full):
diff --git a/manual/threads.texi b/manual/threads.texi
index 91462f5..83b8bb6 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -699,6 +699,34 @@ specified or defaulted when @code{pthread_cond_init} was called. Currently,
 @code{CLOCK_REALTIME}.
 @end deftypefun
 
+@comment pthread.h
+@comment POSIX-proposed
+@deftypefun int pthread_rwlock_clockrdlock (pthread_rwlock_t *@var{rwlock},
+				       clockid_t @var{clockid},
+				       const struct timespec *@var{abstime})
+
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+Behaves like @code{pthread_rwlock_timedrdlock} except the time
+@var{abstime} is measured against the clock specified by @var{clockid}
+rather than @code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
+@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}, otherwise @code{EINVAL} is
+returned.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX-proposed
+@deftypefun int pthread_rwlock_clockwrlock (pthread_rwlock_t *@var{rwlock},
+				       clockid_t @var{clockid},
+				       const struct timespec *@var{abstime})
+
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
+Behaves like @code{pthread_rwlock_timedwrlock} except the time
+@var{abstime} is measured against the clock specified by @var{clockid}
+rather than @code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
+@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}, otherwise @code{EINVAL} is
+returned.
+@end deftypefun
+
 @c FIXME these are undocumented:
 @c pthread_atfork
 @c pthread_attr_destroy
diff --git a/nptl/Makefile b/nptl/Makefile
index 70a2139..d86513a 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -76,7 +76,9 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
 		      pthread_mutexattr_gettype pthread_mutexattr_settype \
 		      pthread_rwlock_init pthread_rwlock_destroy \
 		      pthread_rwlock_rdlock pthread_rwlock_timedrdlock \
+		      pthread_rwlock_clockrdlock \
 		      pthread_rwlock_wrlock pthread_rwlock_timedwrlock \
+		      pthread_rwlock_clockwrlock \
 		      pthread_rwlock_tryrdlock pthread_rwlock_trywrlock \
 		      pthread_rwlock_unlock \
 		      pthread_rwlockattr_init pthread_rwlockattr_destroy \
diff --git a/nptl/Versions b/nptl/Versions
index 8c094d0..ce79959 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -279,6 +279,7 @@ libpthread {
 
   GLIBC_2.30 {
     sem_clockwait; pthread_cond_clockwait;
+    pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
   }
 
   GLIBC_PRIVATE {
diff --git a/nptl/pthread_rwlock_clockrdlock.c b/nptl/pthread_rwlock_clockrdlock.c
new file mode 100644
index 0000000..3c252f5
--- /dev/null
+++ b/nptl/pthread_rwlock_clockrdlock.c
@@ -0,0 +1,29 @@
+/* Implement pthread_rwlock_clockrdlock.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "pthread_rwlock_common.c"
+
+/* See pthread_rwlock_common.c.  */
+int
+pthread_rwlock_clockrdlock (pthread_rwlock_t *rwlock,
+    clockid_t clockid,
+    const struct timespec *abstime)
+{
+  return __pthread_rwlock_rdlock_full (rwlock, clockid, abstime);
+}
diff --git a/nptl/pthread_rwlock_clockwrlock.c b/nptl/pthread_rwlock_clockwrlock.c
new file mode 100644
index 0000000..38ba693
--- /dev/null
+++ b/nptl/pthread_rwlock_clockwrlock.c
@@ -0,0 +1,29 @@
+/* Implement pthread_rwlock_clockwrlock.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "pthread_rwlock_common.c"
+
+/* See pthread_rwlock_common.c.  */
+int
+pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
+    clockid_t clockid,
+    const struct timespec *abstime)
+{
+  return __pthread_rwlock_wrlock_full (rwlock, clockid, abstime);
+}
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index 120b880..50a366e 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -278,17 +278,19 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock)
 
 static __always_inline int
 __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
+    clockid_t clockid,
     const struct timespec *abstime)
 {
   unsigned int r;
 
-  /* Make sure any passed in timeout value is valid.  Note that the previous
-     implementation assumed that this check *must* not be performed if there
-     would in fact be no blocking; however, POSIX only requires that "the
-     validity of the abstime parameter need not be checked if the lock can be
-     immediately acquired" (i.e., we need not but may check it).  */
-  if (abstime
-      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
+  /* Make sure any passed in clockid and timeout value are valid. Note
+     that the previous implementation assumed that this check *must*
+     not be performed if there would in fact be no blocking; however,
+     POSIX only requires that "the validity of the abstime parameter
+     need not be checked if the lock can be immediately acquired"
+     (i.e., we need not but may check it). */
+  if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
+      || abstime->tv_nsec >= 1000000000
       || abstime->tv_nsec < 0))
     return EINVAL;
 
@@ -329,7 +331,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 		{
 		  int private = __pthread_rwlock_get_private (rwlock);
 		  int err = futex_abstimed_wait (&rwlock->__data.__readers,
-						 r, CLOCK_REALTIME, abstime, private);
+						 r, clockid, abstime, private);
 		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
 		     return because we don't need to clean up anything.  */
 		  if (err == ETIMEDOUT)
@@ -457,7 +459,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
 	    continue;
 	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
 					 1 | PTHREAD_RWLOCK_FUTEX_USED,
-					 CLOCK_REALTIME, abstime, private);
+					 clockid, abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      /* If we timed out, we need to unregister.  If no read phase
@@ -584,15 +586,17 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
 
 static __always_inline int
 __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
+    clockid_t clockid,
     const struct timespec *abstime)
 {
-  /* Make sure any passed in timeout value is valid.  Note that the previous
-     implementation assumed that this check *must* not be performed if there
-     would in fact be no blocking; however, POSIX only requires that "the
-     validity of the abstime parameter need not be checked if the lock can be
-     immediately acquired" (i.e., we need not but may check it).  */
-  if (abstime
-      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
+  /* Make sure any passed in clockid and timeout value are valid. Note
+     that the previous implementation assumed that this check *must*
+     not be performed if there would in fact be no blocking; however,
+     POSIX only requires that "the validity of the abstime parameter
+     need not be checked if the lock can be immediately acquired"
+     (i.e., we need not but may check it). */
+  if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
+      || abstime->tv_nsec >= 1000000000
       || abstime->tv_nsec < 0))
     return EINVAL;
 
@@ -727,7 +731,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	  may_share_futex_used_flag = true;
 	  int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
 					 1 | PTHREAD_RWLOCK_FUTEX_USED,
-					 CLOCK_REALTIME, abstime, private);
+					 clockid, abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      if (prefer_writer)
@@ -826,7 +830,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
 	    continue;
 	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
 					 PTHREAD_RWLOCK_FUTEX_USED,
-					 CLOCK_REALTIME, abstime, private);
+					 clockid, abstime, private);
 	  if (err == ETIMEDOUT)
 	    {
 	      if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
diff --git a/nptl/pthread_rwlock_rdlock.c b/nptl/pthread_rwlock_rdlock.c
index 5fdc89e..387c824 100644
--- a/nptl/pthread_rwlock_rdlock.c
+++ b/nptl/pthread_rwlock_rdlock.c
@@ -24,7 +24,7 @@ __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
 {
   LIBC_PROBE (rdlock_entry, 1, rwlock);
 
-  int result = __pthread_rwlock_rdlock_full (rwlock, NULL);
+  int result = __pthread_rwlock_rdlock_full (rwlock, CLOCK_REALTIME, NULL);
   LIBC_PROBE (rdlock_acquire_read, 1, rwlock);
   return result;
 }
diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c
index 84c1983..8f8e680 100644
--- a/nptl/pthread_rwlock_timedrdlock.c
+++ b/nptl/pthread_rwlock_timedrdlock.c
@@ -23,5 +23,5 @@ int
 pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
     const struct timespec *abstime)
 {
-  return __pthread_rwlock_rdlock_full (rwlock, abstime);
+  return __pthread_rwlock_rdlock_full (rwlock, CLOCK_REALTIME, abstime);
 }
diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
index f0b745d..a5616de 100644
--- a/nptl/pthread_rwlock_timedwrlock.c
+++ b/nptl/pthread_rwlock_timedwrlock.c
@@ -23,5 +23,5 @@ int
 pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
     const struct timespec *abstime)
 {
-  return __pthread_rwlock_wrlock_full (rwlock, abstime);
+  return __pthread_rwlock_wrlock_full (rwlock, CLOCK_REALTIME, abstime);
 }
diff --git a/nptl/pthread_rwlock_wrlock.c b/nptl/pthread_rwlock_wrlock.c
index 194a14c..da246d8 100644
--- a/nptl/pthread_rwlock_wrlock.c
+++ b/nptl/pthread_rwlock_wrlock.c
@@ -24,7 +24,7 @@ __pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
 {
   LIBC_PROBE (wrlock_entry, 1, rwlock);
 
-  int result = __pthread_rwlock_wrlock_full (rwlock, NULL);
+  int result = __pthread_rwlock_wrlock_full (rwlock, CLOCK_REALTIME, NULL);
   LIBC_PROBE (wrlock_acquire_write, 1, rwlock);
   return result;
 }
diff --git a/nptl/tst-abstime.c b/nptl/tst-abstime.c
index 56fb8a5..c5040c5 100644
--- a/nptl/tst-abstime.c
+++ b/nptl/tst-abstime.c
@@ -38,6 +38,14 @@ th (void *arg)
   TEST_COMPARE (pthread_mutex_timedlock (&m1, &t), ETIMEDOUT);
   TEST_COMPARE (pthread_rwlock_timedrdlock (&rw1, &t), ETIMEDOUT);
   TEST_COMPARE (pthread_rwlock_timedwrlock (&rw2, &t), ETIMEDOUT);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&rw1, CLOCK_REALTIME, &t),
+                ETIMEDOUT);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&rw2, CLOCK_REALTIME, &t),
+                ETIMEDOUT);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&rw1, CLOCK_MONOTONIC, &t),
+                ETIMEDOUT);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&rw2, CLOCK_MONOTONIC, &t),
+                ETIMEDOUT);
   return NULL;
 }
 
diff --git a/nptl/tst-rwlock14.c b/nptl/tst-rwlock14.c
index af176b6..f4e1422 100644
--- a/nptl/tst-rwlock14.c
+++ b/nptl/tst-rwlock14.c
@@ -64,19 +64,31 @@ do_test (void)
   ts.tv_nsec = -1;
 
   TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
   TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
 
   ts.tv_nsec = 1000000000;
 
   TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
   TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
 
   ts.tv_nsec = (__typeof (ts.tv_nsec)) 0x100001000LL;
   if ((__typeof (ts.tv_nsec)) 0x100001000LL != 0x100001000LL)
     ts.tv_nsec = 2000000000;
 
   TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
   TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
+  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
 
   return 0;
 }
diff --git a/nptl/tst-rwlock6.c b/nptl/tst-rwlock6.c
index 5e73f50..d6020bf 100644
--- a/nptl/tst-rwlock6.c
+++ b/nptl/tst-rwlock6.c
@@ -28,6 +28,11 @@
 #include <support/xtime.h>
 
 
+/* A bogus clock value that tells run_test to use
+   pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock rather
+   than pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. */
+#define CLOCK_USE_TIMEDLOCK (-1)
+
 static int kind[] =
   {
     PTHREAD_RWLOCK_PREFER_READER_NP,
@@ -35,43 +40,63 @@ static int kind[] =
     PTHREAD_RWLOCK_PREFER_WRITER_NP,
   };
 
+struct thread_args
+{
+  pthread_rwlock_t *rwlock;
+  clockid_t clockid;
+  const char *fnname;
+};
 
 static void *
 tf (void *arg)
 {
-  pthread_rwlock_t *r = arg;
+  struct thread_args *args = arg;
+  pthread_rwlock_t *r = args->rwlock;
+  const clockid_t clockid = args->clockid;
+  const clockid_t clockid_for_get =
+    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
+  const char *fnname = args->fnname;
 
   /* Timeout: 0.3 secs.  */
   struct timespec ts_start;
-  xclock_gettime (CLOCK_REALTIME, &ts_start);
+  xclock_gettime (clockid_for_get, &ts_start);
 
   struct timespec ts_timeout = timespec_add (ts_start,
                                              make_timespec (0, 300000000));
 
-  puts ("child calling timedrdlock");
+  printf ("child calling %srdlock\n", fnname);
 
-  TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), ETIMEDOUT);
+  if (clockid == CLOCK_USE_TIMEDLOCK)
+    TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), ETIMEDOUT);
+  else
+    TEST_COMPARE (pthread_rwlock_clockrdlock (r, clockid, &ts_timeout),
+                  ETIMEDOUT);
 
-  puts ("1st child timedrdlock done");
+  printf ("1st child %srdlock done\n", fnname);
 
   TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts_timeout);
 
-  xclock_gettime (CLOCK_REALTIME, &ts_timeout);
+  xclock_gettime (clockid_for_get, &ts_timeout);
   ts_timeout.tv_sec += 10;
   /* Note that the following operation makes ts invalid.  */
   ts_timeout.tv_nsec += 1000000000;
 
-  TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), EINVAL);
+  if (clockid == CLOCK_USE_TIMEDLOCK)
+    TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), EINVAL);
+  else
+    TEST_COMPARE (pthread_rwlock_clockrdlock (r, clockid, &ts_timeout), EINVAL);
 
-  puts ("2nd child timedrdlock done");
+  printf ("2nd child %srdlock done\n", fnname);
 
   return NULL;
 }
 
 
 static int
-do_test (void)
+do_test_clock (clockid_t clockid, const char *fnname)
 {
+  const clockid_t clockid_for_get =
+    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
   size_t cnt;
   for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
     {
@@ -91,39 +116,46 @@ do_test (void)
         FAIL_EXIT1 ("round %Zu: rwlockattr_destroy failed\n", cnt);
 
       struct timespec ts;
-      xclock_gettime (CLOCK_REALTIME, &ts);
+      xclock_gettime (clockid_for_get, &ts);
       ++ts.tv_sec;
 
       /* Get a write lock.  */
-      int e = pthread_rwlock_timedwrlock (&r, &ts);
+      int e = (clockid == CLOCK_USE_TIMEDLOCK)
+	? pthread_rwlock_timedwrlock (&r, &ts)
+	: pthread_rwlock_clockwrlock (&r, clockid, &ts);
       if (e != 0)
-        FAIL_EXIT1 ("round %Zu: rwlock_timedwrlock failed (%d)\n", cnt, e);
+        FAIL_EXIT1 ("round %Zu: %swrlock failed (%d)\n",
+                    cnt, fnname, e);
 
-      puts ("1st timedwrlock done");
+      printf ("1st %swrlock done\n", fnname);
 
-      xclock_gettime (CLOCK_REALTIME, &ts);
+      xclock_gettime (clockid_for_get, &ts);
       ++ts.tv_sec;
-      TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EDEADLK);
+      if (clockid == CLOCK_USE_TIMEDLOCK)
+        TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EDEADLK);
+      else
+        TEST_COMPARE (pthread_rwlock_clockrdlock (&r, clockid, &ts), EDEADLK);
 
-      puts ("1st timedrdlock done");
+      printf ("1st %srdlock done\n", fnname);
 
-      xclock_gettime (CLOCK_REALTIME, &ts);
+      xclock_gettime (clockid_for_get, &ts);
       ++ts.tv_sec;
-      TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EDEADLK);
+      if (clockid == CLOCK_USE_TIMEDLOCK)
+        TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EDEADLK);
+      else
+        TEST_COMPARE (pthread_rwlock_clockwrlock (&r, clockid, &ts), EDEADLK);
 
-      puts ("2nd timedwrlock done");
+      printf ("2nd %swrlock done\n", fnname);
 
-      pthread_t th;
-      if (pthread_create (&th, NULL, tf, &r) != 0)
-        FAIL_EXIT1 ("round %Zu: create failed\n", cnt);
+      struct thread_args args;
+      args.rwlock = &r;
+      args.clockid = clockid;
+      args.fnname = fnname;
+      pthread_t th = xpthread_create (NULL, tf, &args);
 
       puts ("started thread");
 
-      void *status;
-      if (pthread_join (th, &status) != 0)
-        FAIL_EXIT1 ("round %Zu: join failed\n", cnt);
-      if (status != NULL)
-        FAIL_EXIT1 ("failure in round %Zu\n", cnt);
+      (void) xpthread_join (th);
 
       puts ("joined thread");
 
@@ -134,4 +166,12 @@ do_test (void)
   return 0;
 }
 
+static int do_test (void)
+{
+  do_test_clock (CLOCK_USE_TIMEDLOCK, "timed");
+  do_test_clock (CLOCK_REALTIME, "clock(realtime)");
+  do_test_clock (CLOCK_MONOTONIC, "clock(monotonic)");
+  return 0;
+}
+
 #include <support/test-driver.c>
diff --git a/nptl/tst-rwlock7.c b/nptl/tst-rwlock7.c
index df50f0a..1c31572 100644
--- a/nptl/tst-rwlock7.c
+++ b/nptl/tst-rwlock7.c
@@ -28,6 +28,11 @@
 #include <support/xtime.h>
 
 
+/* A bogus clock value that tells run_test to use
+   pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock rather
+   than pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. */
+#define CLOCK_USE_TIMEDLOCK (-1)
+
 static int kind[] =
   {
     PTHREAD_RWLOCK_PREFER_READER_NP,
@@ -35,40 +40,60 @@ static int kind[] =
     PTHREAD_RWLOCK_PREFER_WRITER_NP,
   };
 
+struct thread_args
+{
+  pthread_rwlock_t *rwlock;
+  clockid_t clockid;
+  const char *fnname;
+};
 
 static void *
 tf (void *arg)
 {
-  pthread_rwlock_t *r = arg;
+  struct thread_args *args = arg;
+  pthread_rwlock_t *r = args->rwlock;
+  const clockid_t clockid = args->clockid;
+  const clockid_t clockid_for_get =
+    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
+  const char *fnname = args->fnname;
 
   /* Timeout: 0.3 secs.  */
   struct timespec ts_start;
-  xclock_gettime (CLOCK_REALTIME, &ts_start);
+  xclock_gettime (clockid_for_get, &ts_start);
   const struct timespec ts_timeout = timespec_add (ts_start,
                                                    make_timespec (0, 300000000));
 
-  TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_timeout), ETIMEDOUT);
-  puts ("child: timedwrlock failed with ETIMEDOUT");
+  if (clockid == CLOCK_USE_TIMEDLOCK)
+    TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_timeout), ETIMEDOUT);
+  else
+    TEST_COMPARE (pthread_rwlock_clockwrlock (r, clockid, &ts_timeout),
+                  ETIMEDOUT);
+  printf ("child: %swrlock failed with ETIMEDOUT", fnname);
 
-  TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts_timeout);
+  TEST_TIMESPEC_NOW_OR_AFTER (clockid_for_get, ts_timeout);
 
   struct timespec ts_invalid;
-  xclock_gettime (CLOCK_REALTIME, &ts_invalid);
+  xclock_gettime (clockid_for_get, &ts_invalid);
   ts_invalid.tv_sec += 10;
   /* Note that the following operation makes ts invalid.  */
   ts_invalid.tv_nsec += 1000000000;
 
-  TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_invalid), EINVAL);
+  if (clockid == CLOCK_USE_TIMEDLOCK)
+    TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_invalid), EINVAL);
+  else
+    TEST_COMPARE (pthread_rwlock_clockwrlock (r, clockid, &ts_invalid), EINVAL);
 
-  puts ("child: timedwrlock failed with EINVAL");
+  printf ("child: %swrlock failed with EINVAL", fnname);
 
   return NULL;
 }
 
 
 static int
-do_test (void)
+do_test_clock (clockid_t clockid, const char *fnname)
 {
+  const clockid_t clockid_for_get =
+    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
   size_t cnt;
   for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
     {
@@ -88,23 +113,27 @@ do_test (void)
         FAIL_EXIT1 ("round %Zu: rwlockattr_destroy failed\n", cnt);
 
       struct timespec ts;
-      xclock_gettime (CLOCK_REALTIME, &ts);
+      xclock_gettime (clockid_for_get, &ts);
 
       ++ts.tv_sec;
 
       /* Get a read lock.  */
-      if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
-        FAIL_EXIT1 ("round %Zu: rwlock_timedrdlock failed\n", cnt);
-
-      printf ("%zu: got timedrdlock\n", cnt);
-
-      pthread_t th;
-      if (pthread_create (&th, NULL, tf, &r) != 0)
-        FAIL_EXIT1 ("round %Zu: create failed\n", cnt);
-
-      void *status;
-      if (pthread_join (th, &status) != 0)
-        FAIL_EXIT1 ("round %Zu: join failed\n", cnt);
+      if (clockid == CLOCK_USE_TIMEDLOCK) {
+        if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
+          FAIL_EXIT1 ("round %Zu: rwlock_timedrdlock failed\n", cnt);
+      } else {
+        if (pthread_rwlock_clockrdlock (&r, clockid, &ts) != 0)
+          FAIL_EXIT1 ("round %Zu: rwlock_%srdlock failed\n", cnt, fnname);
+      }
+
+      printf ("%zu: got %srdlock\n", cnt, fnname);
+
+      struct thread_args args;
+      args.rwlock = &r;
+      args.clockid = clockid;
+      args.fnname = fnname;
+      pthread_t th = xpthread_create(NULL, tf, &args);
+      void *status = xpthread_join (th);
       if (status != NULL)
         FAIL_EXIT1 ("failure in round %Zu\n", cnt);
 
@@ -115,4 +144,14 @@ do_test (void)
   return 0;
 }
 
+static int
+do_test (void)
+{
+  do_test_clock (CLOCK_USE_TIMEDLOCK, "timed");
+  do_test_clock (CLOCK_MONOTONIC, "clock(monotonic)");
+  do_test_clock (CLOCK_REALTIME, "clock(realtime)");
+
+  return 0;
+}
+
 #include <support/test-driver.c>
diff --git a/nptl/tst-rwlock9.c b/nptl/tst-rwlock9.c
index e772247..e975554 100644
--- a/nptl/tst-rwlock9.c
+++ b/nptl/tst-rwlock9.c
@@ -26,6 +26,7 @@
 #include <sys/time.h>
 #include <support/check.h>
 #include <support/timespec.h>
+#include <support/xthread.h>
 
 
 #define NWRITERS 15
@@ -40,12 +41,30 @@ static const struct timespec delay = { 0, 1000000 };
 # define KIND PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
 #endif
 
+/* A bogus clock value that tells the tests to use
+   pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock rather
+   than pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. */
+#define CLOCK_USE_TIMEDLOCK (-1)
+
 static pthread_rwlock_t lock;
 
+struct thread_args
+{
+  int nr;
+  clockid_t clockid;
+  const char *fnname;
+};
 
 static void *
-writer_thread (void *nr)
+writer_thread (void *arg)
 {
+  struct thread_args *args = arg;
+  const int nr = args->nr;
+  const clockid_t clockid = args->clockid;
+  const clockid_t clockid_for_get =
+    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
+  const char *fnname = args->fnname;
+
   struct timespec ts;
   int n;
 
@@ -54,27 +73,29 @@ writer_thread (void *nr)
       int e;
       do
 	{
-	  xclock_gettime (CLOCK_REALTIME, &ts);
+	  xclock_gettime (clockid_for_get, &ts);
 
           ts = timespec_add (ts, timeout);
           ts = timespec_add (ts, timeout);
 
-	  printf ("writer thread %ld tries again\n", (long int) nr);
+	  printf ("writer thread %d tries again\n", nr);
 
-	  e = pthread_rwlock_timedwrlock (&lock, &ts);
+	  e = (clockid == CLOCK_USE_TIMEDLOCK)
+	    ? pthread_rwlock_timedwrlock (&lock, &ts)
+	    : pthread_rwlock_clockwrlock (&lock, clockid, &ts);
 	  if (e != 0 && e != ETIMEDOUT)
-            FAIL_EXIT1 ("timedwrlock failed");
+            FAIL_EXIT1 ("%swrlock failed", fnname);
 	}
       while (e == ETIMEDOUT);
 
-      printf ("writer thread %ld succeeded\n", (long int) nr);
+      printf ("writer thread %d succeeded\n", nr);
 
       nanosleep (&delay, NULL);
 
       if (pthread_rwlock_unlock (&lock) != 0)
         FAIL_EXIT1 ("unlock for writer failed");
 
-      printf ("writer thread %ld released\n", (long int) nr);
+      printf ("writer thread %d released\n", nr);
     }
 
   return NULL;
@@ -82,8 +103,15 @@ writer_thread (void *nr)
 
 
 static void *
-reader_thread (void *nr)
+reader_thread (void *arg)
 {
+  struct thread_args *args = arg;
+  const int nr = args->nr;
+  const clockid_t clockid = args->clockid;
+  const clockid_t clockid_for_get =
+    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
+  const char *fnname = args->fnname;
+
   struct timespec ts;
   int n;
 
@@ -92,26 +120,29 @@ reader_thread (void *nr)
       int e;
       do
 	{
-	  xclock_gettime (CLOCK_REALTIME, &ts);
+	  xclock_gettime (clockid_for_get, &ts);
 
           ts = timespec_add (ts, timeout);
 
-	  printf ("reader thread %ld tries again\n", (long int) nr);
+	  printf ("reader thread %d tries again\n", nr);
 
-	  e = pthread_rwlock_timedrdlock (&lock, &ts);
+	  if (clockid == CLOCK_USE_TIMEDLOCK)
+	    e = pthread_rwlock_timedrdlock (&lock, &ts);
+          else
+	    e = pthread_rwlock_clockrdlock (&lock, clockid, &ts);
 	  if (e != 0 && e != ETIMEDOUT)
-            FAIL_EXIT1 ("timedrdlock failed");
+            FAIL_EXIT1 ("%srdlock failed", fnname);
 	}
       while (e == ETIMEDOUT);
 
-      printf ("reader thread %ld succeeded\n", (long int) nr);
+      printf ("reader thread %d succeeded\n", nr);
 
       nanosleep (&delay, NULL);
 
       if (pthread_rwlock_unlock (&lock) != 0)
         FAIL_EXIT1 ("unlock for reader failed");
 
-      printf ("reader thread %ld released\n", (long int) nr);
+      printf ("reader thread %d released\n", nr);
     }
 
   return NULL;
@@ -119,12 +150,11 @@ reader_thread (void *nr)
 
 
 static int
-do_test (void)
+do_test_clock (clockid_t clockid, const char *fnname)
 {
   pthread_t thwr[NWRITERS];
   pthread_t thrd[NREADERS];
   int n;
-  void *res;
   pthread_rwlockattr_t a;
 
   if (pthread_rwlockattr_init (&a) != 0)
@@ -142,23 +172,37 @@ do_test (void)
   /* Make sure we see all message, even those on stdout.  */
   setvbuf (stdout, NULL, _IONBF, 0);
 
-  for (n = 0; n < NWRITERS; ++n)
-    if (pthread_create (&thwr[n], NULL, writer_thread,
-			(void *) (long int) n) != 0)
-      FAIL_EXIT1 ("writer create failed");
-
-  for (n = 0; n < NREADERS; ++n)
-    if (pthread_create (&thrd[n], NULL, reader_thread,
-			(void *) (long int) n) != 0)
-      FAIL_EXIT1 ("reader create failed");
+  struct thread_args wargs[NWRITERS];
+  for (n = 0; n < NWRITERS; ++n) {
+    wargs[n].nr = n;
+    wargs[n].clockid = clockid;
+    wargs[n].fnname = fnname;
+    thwr[n] = xpthread_create (NULL, writer_thread, &wargs[n]);
+  }
+
+  struct thread_args rargs[NREADERS];
+  for (n = 0; n < NREADERS; ++n) {
+    rargs[n].nr = n;
+    rargs[n].clockid = clockid;
+    rargs[n].fnname = fnname;
+    thrd[n] = xpthread_create (NULL, reader_thread, &rargs[n]);
+  }
 
   /* Wait for all the threads.  */
   for (n = 0; n < NWRITERS; ++n)
-    if (pthread_join (thwr[n], &res) != 0)
-      FAIL_EXIT1 ("writer join failed");
+    xpthread_join (thwr[n]);
   for (n = 0; n < NREADERS; ++n)
-    if (pthread_join (thrd[n], &res) != 0)
-      FAIL_EXIT1 ("reader join failed");
+    xpthread_join (thrd[n]);
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  do_test_clock (CLOCK_USE_TIMEDLOCK, "timed");
+  do_test_clock (CLOCK_REALTIME, "clock(realtime)");
+  do_test_clock (CLOCK_MONOTONIC, "clock(monotonic)");
 
   return 0;
 }
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index f000b1e..e78003e 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -909,6 +909,13 @@ extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
 				       __abstime) __THROWNL __nonnull ((1, 2));
 # endif
 
+# ifdef __USE_GNU
+extern int pthread_rwlock_clockrdlock (pthread_rwlock_t *__restrict __rwlock,
+				       clockid_t __clockid,
+				       const struct timespec *__restrict
+				       __abstime) __THROWNL __nonnull ((1, 3));
+# endif
+
 /* Acquire write lock for RWLOCK.  */
 extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
      __THROWNL __nonnull ((1));
@@ -924,6 +931,13 @@ extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
 				       __abstime) __THROWNL __nonnull ((1, 2));
 # endif
 
+# ifdef __USE_GNU
+extern int pthread_rwlock_clockwrlock (pthread_rwlock_t *__restrict __rwlock,
+				       clockid_t __clockid,
+				       const struct timespec *__restrict
+				       __abstime) __THROWNL __nonnull ((1, 3));
+# endif
+
 /* Unlock RWLOCK.  */
 extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
      __THROWNL __nonnull ((1));
diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
index 5af4b8a..9f65baf 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
@@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
index a00adfb..0709855 100644
--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
@@ -228,6 +228,8 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.3.2 pthread_cond_broadcast F
 GLIBC_2.3.2 pthread_cond_destroy F
diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
index 4aeee7b..a2be572 100644
--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
@@ -28,6 +28,8 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 _IO_flockfile F
 GLIBC_2.4 _IO_ftrylockfile F
diff --git a/sysdeps/unix/sysv/linux/csky/libpthread.abilist b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
index 2c08b76..c3a1834 100644
--- a/sysdeps/unix/sysv/linux/csky/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
@@ -234,4 +234,6 @@ GLIBC_2.29 wait F
 GLIBC_2.29 waitpid F
 GLIBC_2.29 write F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
index dc0d4ad..2a00ebc 100644
--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
@@ -246,6 +246,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
index 1830e40..4479947 100644
--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
@@ -254,6 +254,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
index 0811d73..40a1faf 100644
--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
@@ -248,6 +248,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
index 4aeee7b..a2be572 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
@@ -28,6 +28,8 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 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 1830e40..4479947 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
@@ -254,6 +254,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
index f2be6b4..254b708 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
@@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
index 41527fe..29ffdd1 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
@@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
index 41527fe..29ffdd1 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
@@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
index 04fc3a6..3fae328 100644
--- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
@@ -242,4 +242,6 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
index ebdab1a..a90010d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
@@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.3.4 siglongjmp F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
index 8a1fb34..339eab8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
@@ -247,6 +247,8 @@ GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.3.4 siglongjmp F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
index 5af4b8a..9f65baf 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
@@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
index a1c8c2e..83082fb 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
@@ -236,4 +236,6 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
index 0feb3cf..54e937b 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
@@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
index cc4f160..87f978b 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
@@ -248,6 +248,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
index dc0d4ad..2a00ebc 100644
--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
@@ -246,6 +246,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
index ed0574a..bc29a66 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
@@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
index 0811d73..40a1faf 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
@@ -248,6 +248,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index aaa1c3b..70f04cc 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -246,6 +246,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
 GLIBC_2.3.4 pthread_setaffinity_np F
 GLIBC_2.3.4 pthread_setschedprio F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
 GLIBC_2.4 pthread_mutex_consistent_np F
 GLIBC_2.4 pthread_mutex_getprioceiling F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
index 5d02b03..92cd2f4 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
@@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
 GLIBC_2.28 tss_get F
 GLIBC_2.28 tss_set F
 GLIBC_2.30 pthread_cond_clockwait F
+GLIBC_2.30 pthread_rwlock_clockrdlock F
+GLIBC_2.30 pthread_rwlock_clockwrlock F
 GLIBC_2.30 sem_clockwait F
-- 
git-series 0.9.1

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

* [PATCH v3 6/6] Update NEWS for new _clockwait functions
  2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
                   ` (4 preceding siblings ...)
  2019-05-27 20:03 ` [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock Mike Crowe
@ 2019-05-27 20:03 ` Mike Crowe
  2019-06-07 14:09   ` Adhemerval Zanella
  5 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-05-27 20:03 UTC (permalink / raw
  To: libc-alpha; +Cc: Mike Crowe

* NEWS: Mention new pthread_cond_clockwait,
	pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock and
	sem_clockwait functions.
---
 ChangeLog | 6 ++++++
 NEWS      | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 66589f8..beba62b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-05-27  Mike Crowe  <mac@mcrowe.com>
 
+	* NEWS: Mention new pthread_cond_clockwait,
+	pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock and
+	sem_clockwait functions.
+
+2019-05-27  Mike Crowe  <mac@mcrowe.com>
+
 	nptl: Add POSIX-proposed pthread_rwlock_clockrdlock &
 	pthread_rwlock_clockwrlock which behave like
 	pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock
diff --git a/NEWS b/NEWS
index c885b96..76b1587 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,12 @@ Major new features:
   pointer subtraction within the allocated object, where results might
   overflow the ptrdiff_t type.
 
+* Add new POSIX-proposed pthread_cond_clockwait, pthread_rwlock_clockrdlock,
+  pthread_rwlock_clockwrlock and sem_clockwait functions. These behave
+  similarly to their "timed" equivalents, but also accept a clockid_t
+  parameter to determine which clock their timeout should be measured
+  against.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * The functions clock_gettime, clock_getres, clock_settime,
-- 
git-series 0.9.1

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

* Re: [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls
  2019-05-27 20:03 ` [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls Mike Crowe
@ 2019-06-05 17:52   ` Adhemerval Zanella
  2019-06-06 12:06     ` Adhemerval Zanella
  2019-06-12 19:32     ` Adhemerval Zanella
  0 siblings, 2 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-05 17:52 UTC (permalink / raw
  To: libc-alpha



On 27/05/2019 17:03, Mike Crowe wrote:
> In preparation for adding POSIX clockwait variants of timedwait functions,
> add a clockid_t parameter to futex_abstimed_wait functions and pass
> CLOCK_REALTIME from all callers for the time being.
> 
> Replace lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset which
> takes a clockid_t parameter rather than the magic clockbit.
> 
> * sysdeps/nptl/lowlevellock-futex.h,
>   sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
>   lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset that takes a
>   clockid rather than a special clockbit.
> 
> * sysdeps/nptl/lowlevellock-futex.h: Add lll_futex_supported_clockid so
>   that client functions can check whether their clockid parameter is valid
>   even if they don't ultimately end up calling lll_futex_clock_wait_bitset.
> 
> * sysdeps/nptl/futex-internal.h, sysdeps/unix/sysv/linux/futex-internal.h
>   (futex_abstimed_wait, futex_abstimed_wait_cancelable): Add clockid_t
>   parameter to indicate which clock the absolute time passed should be
>   measured against. Pass that clockid onto lll_futex_clock_wait_bitset.
>   Add invalid clock as reason for returning -EINVAL.
> 
> * sysdeps/nptl/futex-internal.h, sysdeps/unix/sysv/linux/futex-internal.h:
>   Introduce futex_abstimed_supported_clockid so that client functions can
>   check whether their clockid parameter is valid even if they don't
>   ultimately end up calling futex_abstimed_wait.
> 
> * nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Remove code to
>   calculate relative timeout for __PTHREAD_COND_CLOCK_MONOTONIC_MASK and
>   just pass CLOCK_MONOTONIC or CLOCK_REALTIME as required to
>   futex_abstimed_wait_cancelable.
> 
> * nptl/pthread_rwlock_common (__pthread_rwlock_rdlock_full,
>   __pthread_wrlock_full), nptl/sem_waitcommon (do_futex_wait): Pass
>   additional CLOCK_REALTIME to futex_abstimed_wait_cancelable.
> 
> * nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Switch to
>   lll_futex_clock_wait_bitset and pass CLOCK_REALTIME
> ---
>  ChangeLog                                    | 40 +++++++++++++++++++++-
>  nptl/pthread_cond_wait.c                     | 32 +++--------------
>  nptl/pthread_mutex_timedlock.c               |  4 +-
>  nptl/pthread_rwlock_common.c                 |  8 ++--
>  nptl/sem_waitcommon.c                        |  6 ++-
>  sysdeps/nptl/futex-internal.h                |  7 ++++-
>  sysdeps/nptl/lowlevellock-futex.h            | 13 ++++---
>  sysdeps/unix/sysv/linux/futex-internal.h     | 26 ++++++++++----
>  sysdeps/unix/sysv/linux/lowlevellock-futex.h | 33 +++++++++++++----
>  9 files changed, 118 insertions(+), 51 deletions(-)
> 
> diff --git a/ChangeLog b/ChangeLog
> index 53a3ae4..ff85b12 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,43 @@
> +2019-05-27  Mike Crowe  <mac@mcrowe.com>
> +
> +	nptl: Add clockid parameter to futex timed wait calls
> +
> +	* sysdeps/nptl/lowlevellock-futex.h,
> +	sysdeps/unix/sysv/linux/lowlevellock-futex.h: Replace
> +	lll_futex_timed_wait_bitset with lll_futex_clock_wait_bitset that
> +	takes a clockid rather than a special clockbit.
> +
> +	* sysdeps/nptl/lowlevellock-futex.h: Add
> +	lll_futex_supported_clockid so that client functions can check
> +	whether their clockid parameter is valid even if they don't
> +	ultimately end up calling lll_futex_clock_wait_bitset.
> +
> +	* sysdeps/nptl/futex-internal.h,
> +	sysdeps/unix/sysv/linux/futex-internal.h
> +	(futex_abstimed_wait, futex_abstimed_wait_cancelable): Add
> +	clockid_t parameter to indicate which clock the absolute time
> +	passed should be measured against. Pass that clockid onto
> +	lll_futex_clock_wait_bitset. Add invalid clock as reason for
> +	returning -EINVAL.
> +
> +	* sysdeps/nptl/futex-internal.h,
> +	sysdeps/unix/sysv/linux/futex-internal.h: Introduce
> +	futex_abstimed_supported_clockid so that client functions can check
> +	whether their clockid parameter is valid even if they don't
> +	ultimately end up calling futex_abstimed_wait.
> +
> +	* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Remove
> +	code to calculate relative timeout for
> +	__PTHREAD_COND_CLOCK_MONOTONIC_MASK and just pass CLOCK_MONOTONIC
> +	or CLOCK_REALTIME as required to futex_abstimed_wait_cancelable.
> +
> +	* nptl/pthread_rwlock_common (__pthread_rwlock_rdlock_full)
> +	(__pthread_wrlock_full), nptl/sem_waitcommon (do_futex_wait): Pass
> +	additional CLOCK_REALTIME to futex_abstimed_wait_cancelable.
> +
> +	* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock):
> +	Switch to lll_futex_clock_wait_bitset and pass CLOCK_REALTIME
> +
>  2019-05-27  Florian Weimer  <fweimer@redhat.com>
>  
>  	* nptl/nptl-init.c: Add comment.
> diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
> index 9a0f29e..7385562 100644
> --- a/nptl/pthread_cond_wait.c
> +++ b/nptl/pthread_cond_wait.c
> @@ -509,35 +509,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>  		 values despite them being valid.  */
>  	      if (__glibc_unlikely (abstime->tv_sec < 0))
>  	        err = ETIMEDOUT;
> -
> -	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
> -		{
> -		  /* CLOCK_MONOTONIC is requested.  */
> -		  struct timespec rt;
> -		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
> -		    __libc_fatal ("clock_gettime does not support "
> -				  "CLOCK_MONOTONIC\n");
> -		  /* Convert the absolute timeout value to a relative
> -		     timeout.  */
> -		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
> -		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
> -		  if (rt.tv_nsec < 0)
> -		    {
> -		      rt.tv_nsec += 1000000000;
> -		      --rt.tv_sec;
> -		    }
> -		  /* Did we already time out?  */
> -		  if (__glibc_unlikely (rt.tv_sec < 0))
> -		    err = ETIMEDOUT;
> -		  else
> -		    err = futex_reltimed_wait_cancelable
> -			(cond->__data.__g_signals + g, 0, &rt, private);
> -		}
>  	      else
>  		{
> -		  /* Use CLOCK_REALTIME.  */
> +		  const clockid_t clockid =
> +		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
> +		    CLOCK_MONOTONIC : CLOCK_REALTIME;
> +
>  		  err = futex_abstimed_wait_cancelable
> -		      (cond->__data.__g_signals + g, 0, abstime, private);
> +                    (cond->__data.__g_signals + g, 0, clockid, abstime,
> +                     private);
>  		}
>  	    }

My understanding is we need to convert an absolute timeout to a relative one
on either futex_abstimed_wait_cancelable or lll_futex_clock_wait_bitset for
CLOCK_MONOTONIC.

>  
> diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
> index 270b072..d4d11cc 100644
> --- a/nptl/pthread_mutex_timedlock.c
> +++ b/nptl/pthread_mutex_timedlock.c
> @@ -266,8 +266,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
>  	  assume_other_futex_waiters |= FUTEX_WAITERS;
>  
>  	  /* Block using the futex.  */
> -	  int err = lll_futex_timed_wait_bitset (&mutex->__data.__lock,
> -	      oldval, abstime, FUTEX_CLOCK_REALTIME,
> +	  int err = lll_futex_clock_wait_bitset (&mutex->__data.__lock,
> +	      oldval, CLOCK_REALTIME, abstime,
>  	      PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
>  	  /* The futex call timed out.  */
>  	  if (err == -ETIMEDOUT)

Ok.

> diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
> index 2560734..89ba21a 100644
> --- a/nptl/pthread_rwlock_common.c
> +++ b/nptl/pthread_rwlock_common.c
> @@ -319,7 +319,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
>  		{
>  		  int private = __pthread_rwlock_get_private (rwlock);
>  		  int err = futex_abstimed_wait (&rwlock->__data.__readers,
> -						 r, abstime, private);
> +						 r, CLOCK_REALTIME, abstime, private);
>  		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
>  		     return because we don't need to clean up anything.  */
>  		  if (err == ETIMEDOUT)

Ok.

> @@ -447,7 +447,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
>  	    continue;
>  	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
>  					 1 | PTHREAD_RWLOCK_FUTEX_USED,
> -					 abstime, private);
> +					 CLOCK_REALTIME, abstime, private);
>  	  if (err == ETIMEDOUT)
>  	    {
>  	      /* If we timed out, we need to unregister.  If no read phase

Ok.

> @@ -707,7 +707,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
>  	  may_share_futex_used_flag = true;
>  	  int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
>  					 1 | PTHREAD_RWLOCK_FUTEX_USED,
> -					 abstime, private);
> +					 CLOCK_REALTIME, abstime, private);
>  	  if (err == ETIMEDOUT)
>  	    {
>  	      if (prefer_writer)

Ok.

> @@ -806,7 +806,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
>  	    continue;
>  	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
>  					 PTHREAD_RWLOCK_FUTEX_USED,
> -					 abstime, private);
> +					 CLOCK_REALTIME, abstime, private);
>  	  if (err == ETIMEDOUT)
>  	    {
>  	      if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)

Ok.

> diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
> index 5646bea..425d040 100644
> --- a/nptl/sem_waitcommon.c
> +++ b/nptl/sem_waitcommon.c
> @@ -109,11 +109,13 @@ do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
>  
>  #if __HAVE_64B_ATOMICS
>    err = futex_abstimed_wait_cancelable (
> -      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
> +      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0,
> +      CLOCK_REALTIME, abstime,
>        sem->private);

Ok.

>  #else
>    err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
> -					abstime, sem->private);
> +					CLOCK_REALTIME, abstime,
> +					sem->private);
>  #endif
>  
>    return err;

Ok.

> diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h
> index 86a0818..54b7319 100644
> --- a/sysdeps/nptl/futex-internal.h
> +++ b/sysdeps/nptl/futex-internal.h
> @@ -159,16 +159,23 @@ futex_reltimed_wait_cancelable (unsigned int* futex_word,
>  				unsigned int expected,
>  			        const struct timespec* reltime, int private);
>  
> +/* Check whether the specified clockid is supported by
> +   futex_abstimed_wait and futex_abstimed_wait_cancelable. */
> +static __always_inline int
> +futex_abstimed_supported_clockid (clockid_t clockid);
> +
>  /* Like futex_reltimed_wait, but the provided timeout (ABSTIME) is an
>     absolute point in time; a call will time out after this point in time.  */
>  static __always_inline int
>  futex_abstimed_wait (unsigned int* futex_word, unsigned int expected,
> +		     clockid_t clockid,
>  		     const struct timespec* abstime, int private);
>  
>  /* Like futex_reltimed_wait but is a POSIX cancellation point.  */
>  static __always_inline int
>  futex_abstimed_wait_cancelable (unsigned int* futex_word,
>  				unsigned int expected,
> +				clockid_t clockid,
>  			        const struct timespec* abstime, int private);
>  
>  /* Atomically wrt other futex operations on the same futex, this unblocks the

Ok.

> diff --git a/sysdeps/nptl/lowlevellock-futex.h b/sysdeps/nptl/lowlevellock-futex.h
> index 63d917d..35fcfbb 100644
> --- a/sysdeps/nptl/lowlevellock-futex.h
> +++ b/sysdeps/nptl/lowlevellock-futex.h
> @@ -43,10 +43,15 @@
>  #define lll_futex_timed_wait(futexp, val, timeout, private)             \
>    -ENOSYS
>  
> -/* If CLOCKBIT is zero, this is identical to lll_futex_timed_wait.
> -   If CLOCKBIT has FUTEX_CLOCK_REALTIME set, then it's the same but
> -   TIMEOUT is counted by CLOCK_REALTIME rather than CLOCK_MONOTONIC.  */
> -#define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
> +/* Verify whether the supplied clockid is supported by
> +   lll_futex_clock_wait_bitset */
> +#define lll_futex_supported_clockid(clockid)				\
> +  (0)
> +
> +/* Wait until a lll_futex_wake call on FUTEXP, or the absolute TIMEOUT
> +   measured against CLOCKID elapses. CLOCKID may be CLOCK_REALTIME or
> +   CLOCK_MONOTONIC. */
> +#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
>    -ENOSYS
>  
>  /* Wake up up to NR waiters on FUTEXP.  */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
> index 501f993..03312d6 100644
> --- a/sysdeps/unix/sysv/linux/futex-internal.h
> +++ b/sysdeps/unix/sysv/linux/futex-internal.h
> @@ -162,15 +162,24 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
>  
>  /* See sysdeps/nptl/futex-internal.h for details.  */
>  static __always_inline int
> +futex_abstimed_supported_clockid (clockid_t clockid)
> +{
> +  return lll_futex_supported_clockid (clockid);
> +}
> +
> +/* See sysdeps/nptl/futex-internal.h for details.  */
> +static __always_inline int
>  futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
> +		     clockid_t clockid,
>  		     const struct timespec *abstime, int private)
>  {
>    /* Work around the fact that the kernel rejects negative timeout values
>       despite them being valid.  */
>    if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
>      return ETIMEDOUT;
> -  int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
> -					 FUTEX_CLOCK_REALTIME, private);
> +  int err = lll_futex_clock_wait_bitset (futex_word, expected,
> +					 clockid, abstime,
> +					 private);
>    switch (err)
>      {
>      case 0:
> @@ -180,9 +189,10 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
>        return -err;
>  
>      case -EFAULT: /* Must have been caused by a glibc or application bug.  */
> -    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
> -		     being normalized.  Must have been caused by a glibc or
> -		     application bug.  */
> +    case -EINVAL: /* Either due to wrong alignment, unsupported
> +		     clockid or due to the timeout not being
> +		     normalized. Must have been caused by a glibc or
> +		     application bug. */
>      case -ENOSYS: /* Must have been caused by a glibc bug.  */
>      /* No other errors are documented at this time.  */
>      default:

Ok.

> @@ -194,6 +204,7 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
>  static __always_inline int
>  futex_abstimed_wait_cancelable (unsigned int *futex_word,
>  				unsigned int expected,
> +				clockid_t clockid,
>  			        const struct timespec *abstime, int private)
>  {
>    /* Work around the fact that the kernel rejects negative timeout values
> @@ -202,8 +213,9 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
>      return ETIMEDOUT;
>    int oldtype;
>    oldtype = __pthread_enable_asynccancel ();
> -  int err = lll_futex_timed_wait_bitset (futex_word, expected, abstime,
> -					 FUTEX_CLOCK_REALTIME, private);
> +  int err = lll_futex_clock_wait_bitset (futex_word, expected,
> +					clockid, abstime,
> +					private);
>    __pthread_disable_asynccancel (oldtype);
>    switch (err)
>      {

Ok.

> diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
> index 030a14b..ba01197 100644
> --- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
> +++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
> @@ -82,12 +82,33 @@
>  		     __lll_private_flag (FUTEX_WAIT, private),  \
>  		     val, timeout)
>  
> -#define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
> -  lll_futex_syscall (6, futexp,                                         \
> -		     __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
> -					 private),                      \
> -		     val, timeout, NULL /* Unused.  */,                 \
> -		     FUTEX_BITSET_MATCH_ANY)
> +/* Verify whether the supplied clockid is supported by
> +   lll_futex_clock_wait_bitset */
> +#define lll_futex_supported_clockid(clockid)			\
> +  ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC)
> +
> +/* The kernel currently only supports CLOCK_MONOTONIC or
> + * CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to
> + * convert others here but currently do not.
> + */
> +#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
> +  ({									\
> +    long int __ret;							\
> +    if (lll_futex_supported_clockid (clockid))                          \
> +      {                                                                 \
> +        const unsigned int clockbit =                                   \
> +          (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0;       \
> +        const int op =                                                  \
> +          __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private);   \
> +                                                                        \
> +        __ret = lll_futex_syscall (6, futexp, op, val,                  \
> +                                   timeout, NULL /* Unused.  */,	\
> +                                   FUTEX_BITSET_MATCH_ANY);		\
> +      }                                                                 \
> +    else                                                                \
> +      __ret = -EINVAL;							\
> +    __ret;								\
> +  })
>  
>  #define lll_futex_wake(futexp, nr, private)                             \
>    lll_futex_syscall (4, futexp,                                         \
> 

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-05-27 20:03 ` [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait Mike Crowe
@ 2019-06-05 21:07   ` Adhemerval Zanella
  2019-06-06 15:40     ` Mike Crowe
  0 siblings, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-05 21:07 UTC (permalink / raw
  To: libc-alpha



On 27/05/2019 17:03, Mike Crowe wrote:
> Add:
> 
>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
> 
> which behaves just like sem_timedwait, but measures abstime against the
> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
> sets errno == EINVAL if any other clock is specified.

For non-POSIX definition we will need to first export it as a GNU extension
with a possible non-reserved name and later, when it is included on the 
standard, to add an alias to the expected name.  

The usual naming scheme is to append the _np suffix (non-portable) on 
implementation, similar to recent posix_spawn file action extensions.
In this case it would be sem_clockwait_np.

> 
> * nptl/sem_waitcommon.c (do_futex_wait, __new_sem_wait_slow): Add clockid
>   parameters to indicate the clock which abstime should be measured
>   against.
> 
> * nptl/sem_timedwait.c (sem_timedwait), nptl/sem_wait.c (__new_sem_wait):
>   Pass CLOCK_REALTIME as clockid to __new_sem_wait_slow.
> 
> * nptl/sem_clockwait.c: New file to implement sem_clockwait based on
>   sem_timedwait.c.
> 
> * nptl/Makefile: Add sem_clockwait.c source file. Add CFLAGS for
>   sem_clockwait.c to match those used for sem_timedwait.c.
> 
> * sysdeps/pthread/semaphore.h: Add sem_clockwait.
> 
> * nptl/Versions (GLIBC_2.30): Likewise.
> 
> * sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/microblaze/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
>   (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
>   (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
>   (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist	(GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
> * sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> * sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist (GLIBC_2.30):
>   Likewise.
> 
> * nptl/tst-sem17.c: Add new test for passing invalid clock to
>   sem_clockwait.
> 
> * nptl/tst-sem13.c, nptl/tst-sem5.c: Modify existing sem_timedwait tests to
>   also test sem_clockwait.
> 
> * manual/threads.texi: Document sem_clockwait.
> ---
>  ChangeLog                                                       | 71 +++++++-
>  manual/threads.texi                                             | 10 +-
>  nptl/Makefile                                                   |  5 +-
>  nptl/Versions                                                   |  4 +-
>  nptl/sem_clockwait.c                                            | 45 ++++-
>  nptl/sem_timedwait.c                                            |  3 +-
>  nptl/sem_wait.c                                                 |  3 +-
>  nptl/sem_waitcommon.c                                           | 15 +-
>  nptl/tst-sem13.c                                                | 39 +++-
>  nptl/tst-sem17.c                                                | 76 +++++++-
>  nptl/tst-sem5.c                                                 | 23 +-
>  sysdeps/pthread/semaphore.h                                     |  7 +-
>  sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |  1 +-
>  sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |  1 +-
>  sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |  1 +-
>  sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |  1 +-
>  sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |  1 +-
>  sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |  1 +-
>  sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |  1 +-
>  sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |  1 +-
>  sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |  1 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |  1 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |  1 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |  1 +-
>  sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |  1 +-
>  sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |  1 +-
>  sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |  1 +-
>  sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |  1 +-
>  sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |  1 +-
>  sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |  1 +-
>  sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |  1 +-
>  sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |  1 +-
>  36 files changed, 305 insertions(+), 20 deletions(-)
>  create mode 100644 nptl/sem_clockwait.c
>  create mode 100644 nptl/tst-sem17.c
> 
> diff --git a/ChangeLog b/ChangeLog
> index ff85b12..814e331 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,5 +1,76 @@
>  2019-05-27  Mike Crowe  <mac@mcrowe.com>
>  
> +	nptl: Add POSIX-proposed sem_clockwait which behaves just like
> +	sem_timedwait, but measures abstime against the specified clock.
> +
> +	* nptl/sem_waitcommon.c (do_futex_wait, __new_sem_wait_slow): Add
> +	clockid parameters to indicate the clock which abstime should be
> +	measured against.
> +
> +	* nptl/sem_timedwait.c (sem_timedwait), nptl/sem_wait.c
> +	(__new_sem_wait): Pass CLOCK_REALTIME as clockid to
> +	__new_sem_wait_slow.
> +
> +	* nptl/sem_clockwait.c: New file to implement sem_clockwait based
> +	on sem_timedwait.c.
> +
> +	* nptl/Makefile: Add sem_clockwait.c source file. Add CFLAGS for
> +	sem_clockwait.c to match those used for sem_timedwait.c.
> +
> +	* sysdeps/pthread/semaphore.h: Add sem_clockwait.
> +
> +	* nptl/Versions (GLIBC_2.30): Likewise.
> +
> +	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +
> +	* nptl/tst-sem17.c: Add new test for passing invalid clock to
> +	sem_clockwait.
> +
> +	* nptl/tst-sem13.c, nptl/tst-sem5.c: Modify existing sem_timedwait
> +	tests to also test sem_clockwait.
> +
> +	* manual/threads.texi: Document sem_clockwait.
> +
> +2019-05-27  Mike Crowe  <mac@mcrowe.com>
> +
>  	nptl: Add clockid parameter to futex timed wait calls
>  
>  	* sysdeps/nptl/lowlevellock-futex.h,
> diff --git a/manual/threads.texi b/manual/threads.texi
> index 87fda7d..674267c 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -669,6 +669,16 @@ The system does not have sufficient memory.
>  @end table
>  @end deftypefun
>  
> +@comment semaphore.h
> +@comment POSIX-proposed
> +@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clockid},
> +                               const struct timespec *@var{abstime})
> +Behaves like @code{sem_timedwait} except the time @var{abstime} is measured
> +against the clock specified by @var{clockid} rather than
> +@code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
> +@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
> +@end deftypefun
> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy

Ok.

> diff --git a/nptl/Makefile b/nptl/Makefile
> index de312b3..43a99dc 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -113,7 +113,7 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
>  		      sem_init sem_destroy \
>  		      sem_open sem_close sem_unlink \
>  		      sem_getvalue \
> -		      sem_wait sem_timedwait sem_post \
> +		      sem_wait sem_timedwait sem_clockwait sem_post \
>  		      cleanup cleanup_defer cleanup_compat \
>  		      cleanup_defer_compat unwind \
>  		      pt-longjmp pt-cleanup\
> @@ -193,6 +193,7 @@ CFLAGS-pthread_once.c += $(uses-callbacks) -fexceptions \
>  CFLAGS-pthread_cond_wait.c += -fexceptions -fasynchronous-unwind-tables
>  CFLAGS-sem_wait.c += -fexceptions -fasynchronous-unwind-tables
>  CFLAGS-sem_timedwait.c += -fexceptions -fasynchronous-unwind-tables
> +CFLAGS-sem_clockwait.c = -fexceptions -fasynchronous-unwind-tables
>  
>  # These are the function wrappers we have to duplicate here.
>  CFLAGS-fcntl.c += -fexceptions -fasynchronous-unwind-tables
> @@ -262,7 +263,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
>  	tst-key1 tst-key2 tst-key3 tst-key4 \
>  	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
>  	tst-sem8 tst-sem9 tst-sem10 tst-sem14 \
> -	tst-sem15 tst-sem16 \
> +	tst-sem15 tst-sem16 tst-sem17 \
>  	tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
>  	tst-align tst-align3 \
>  	tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \

Ok.

> diff --git a/nptl/Versions b/nptl/Versions
> index e7f691d..cd1806c 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -277,6 +277,10 @@ libpthread {
>      cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
>    }
>  
> +  GLIBC_2.30 {
> +    sem_clockwait;
> +  }
> +
>    GLIBC_PRIVATE {
>      __pthread_initialize_minimal;
>      __pthread_clock_gettime; __pthread_clock_settime;

Change to a extension name by adding a _np suffix.

> diff --git a/nptl/sem_clockwait.c b/nptl/sem_clockwait.c
> new file mode 100644
> index 0000000..c0cd667
> --- /dev/null
> +++ b/nptl/sem_clockwait.c
> @@ -0,0 +1,45 @@
> +/* sem_clockwait -- wait on a semaphore with timeout using
> +   the specified clock.
> +
> +   Copyright (C) 2003-2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.

I think it should be only 2019 in this case.

> +
> +   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 "sem_waitcommon.c"
> +
> +int
> +sem_clockwait (sem_t *sem, clockid_t clockid,
> +	       const struct timespec *abstime)
> +{
> +  /* Check that supplied clockid is one we support, even if we don't
> +     end up waiting. */
> +  if (!futex_abstimed_supported_clockid (clockid))
> +    {
> +      __set_errno (EINVAL);
> +      return -1;
> +    }
> +
> +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
> +    {
> +      __set_errno (EINVAL);
> +      return -1;
> +    }
> +
> +  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
> +    return 0;
> +  else
> +    return __new_sem_wait_slow ((struct new_sem *) sem, clockid, abstime);
> +}

Ok.  As for BZ#23006 I think we should follow Austin Group latest resolution
for sem_wait/sem_timedwait and not make it a cancellable entrypoint.

> diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
> index 3dd71ab..0918d8b 100644
> --- a/nptl/sem_timedwait.c
> +++ b/nptl/sem_timedwait.c
> @@ -36,5 +36,6 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
>    if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
>      return 0;
>    else
> -    return __new_sem_wait_slow((struct new_sem *) sem, abstime);
> +    return __new_sem_wait_slow ((struct new_sem *) sem,
> +				CLOCK_REALTIME, abstime);
>  }

Ok.

> diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
> index 6a2d26b..20a8b9d 100644
> --- a/nptl/sem_wait.c
> +++ b/nptl/sem_wait.c
> @@ -39,7 +39,8 @@ __new_sem_wait (sem_t *sem)
>    if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
>      return 0;
>    else
> -    return __new_sem_wait_slow((struct new_sem *) sem, NULL);
> +    return __new_sem_wait_slow ((struct new_sem *) sem,
> +				CLOCK_REALTIME, NULL);
>  }
>  versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
>  

Ok.

> diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
> index 425d040..cad56e9 100644
> --- a/nptl/sem_waitcommon.c
> +++ b/nptl/sem_waitcommon.c
> @@ -103,19 +103,19 @@ __sem_wait_cleanup (void *arg)
>     users don't seem to need it.  */
>  static int
>  __attribute__ ((noinline))
> -do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
> +do_futex_wait (struct new_sem *sem, clockid_t clockid,
> +	       const struct timespec *abstime)
>  {
>    int err;
>  
>  #if __HAVE_64B_ATOMICS
>    err = futex_abstimed_wait_cancelable (
>        (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0,
> -      CLOCK_REALTIME, abstime,
> +      clockid, abstime,
>        sem->private);
>  #else
>    err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
> -					CLOCK_REALTIME, abstime,
> -					sem->private);
> +					clockid, abstime, sem->private);
>  #endif
>  
>    return err;

Ok.

> @@ -162,7 +162,8 @@ __new_sem_wait_fast (struct new_sem *sem, int definitive_result)
>  /* Slow path that blocks.  */
>  static int
>  __attribute__ ((noinline))
> -__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
> +__new_sem_wait_slow (struct new_sem *sem, clockid_t clockid,
> +		     const struct timespec *abstime)
>  {
>    int err = 0;
>  
> @@ -180,7 +181,7 @@ __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
>        /* If there is no token available, sleep until there is.  */
>        if ((d & SEM_VALUE_MASK) == 0)
>  	{
> -	  err = do_futex_wait (sem, abstime);
> +	  err = do_futex_wait (sem, clockid, abstime);
>  	  /* A futex return value of 0 or EAGAIN is due to a real or spurious
>  	     wake-up, or due to a change in the number of tokens.  We retry in
>  	     these cases.
> @@ -281,7 +282,7 @@ __new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
>  	  if ((v >> SEM_VALUE_SHIFT) == 0)
>  	    {
>  	      /* See __HAVE_64B_ATOMICS variant.  */
> -	      err = do_futex_wait(sem, abstime);
> +	      err = do_futex_wait (sem, clockid, abstime);
>  	      if (err == ETIMEDOUT || err == EINTR)
>  		{
>  		  __set_errno (err);

Ok.

> diff --git a/nptl/tst-sem13.c b/nptl/tst-sem13.c
> index 28d37ed..21c3b7e 100644
> --- a/nptl/tst-sem13.c
> +++ b/nptl/tst-sem13.c
> @@ -6,9 +6,14 @@
>  #include <internaltypes.h>
>  #include <support/check.h>
>  
> +/* A bogus clock value that tells run_test to use
> +   sem_timedwait rather than sem_clockwait */
> +#define CLOCK_USE_TIMEDWAIT (-1)

This defined does not seem to be used.

>  
> -static int
> -do_test (void)
> +typedef int (*waitfn_t)(sem_t *, struct timespec *);
> +
> +static void
> +do_test_wait (waitfn_t waitfn, const char *fnname)
>  {
>    union
>    {
> @@ -16,11 +21,13 @@ do_test (void)
>      struct new_sem ns;
>    } u;
>  
> +  printf ("do_test_wait: %s\n", fnname);
> +

I think for debug logging it is better to enable only if test_verbose
(support/support_test_main.c:197) is set.

>    TEST_COMPARE (sem_init (&u.s, 0, 0), 0);
>  
>    struct timespec ts = { 0, 1000000001 };	/* Invalid.  */
>    errno = 0;
> -  TEST_VERIFY_EXIT (sem_timedwait (&u.s, &ts) < 0);
> +  TEST_VERIFY_EXIT (waitfn (&u.s, &ts) < 0);
>    TEST_COMPARE (errno, EINVAL);
>  
>  #if __HAVE_64B_ATOMICS
> @@ -33,7 +40,7 @@ do_test (void)
>    ts.tv_sec = /* Invalid.  */ -2;
>    ts.tv_nsec = 0;
>    errno = 0;
> -  TEST_VERIFY_EXIT (sem_timedwait (&u.s, &ts) < 0);
> +  TEST_VERIFY_EXIT (waitfn (&u.s, &ts) < 0);
>    TEST_COMPARE (errno, ETIMEDOUT);
>  #if __HAVE_64B_ATOMICS
>    nwaiters = (u.ns.data >> SEM_NWAITERS_SHIFT);
> @@ -41,7 +48,31 @@ do_test (void)
>    nwaiters = u.ns.nwaiters;
>  #endif
>    TEST_COMPARE (nwaiters, 0);
> +}
>  
> +int test_sem_timedwait (sem_t *sem, struct timespec *ts)
> +{
> +  return sem_timedwait (sem, ts);
> +}
> +
> +int test_sem_clockwait_monotonic (sem_t *sem, struct timespec *ts)
> +{
> +  return sem_clockwait (sem, CLOCK_MONOTONIC, ts);
> +}
> +
> +int test_sem_clockwait_realtime (sem_t *sem, struct timespec *ts)
> +{
> +  return sem_clockwait (sem, CLOCK_REALTIME, ts);
> +}
> +
> +static int do_test (void)
> +{
> +  do_test_wait (&test_sem_timedwait,
> +                "sem_timedwait");
> +  do_test_wait (&test_sem_clockwait_monotonic,
> +                "sem_clockwait(monotonic)");
> +  do_test_wait (&test_sem_clockwait_realtime,
> +                "sem_clockwait(realtime)");
>    return 0;
>  }
>  

Ok.

> diff --git a/nptl/tst-sem17.c b/nptl/tst-sem17.c
> new file mode 100644
> index 0000000..78c52c8
> --- /dev/null
> +++ b/nptl/tst-sem17.c
> @@ -0,0 +1,76 @@
> +/* Test unsupported/bad clocks passed to sem_clockwait.
> +
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <semaphore.h>
> +#include <stdio.h>
> +#include <time.h>
> +#include <unistd.h>
> +#include <sys/time.h>
> +#include <support/check.h>
> +#include <support/timespec.h>
> +
> +
> +#define NOT_A_VALID_CLOCK 123456
> +
> +static int
> +do_test (void)
> +{
> +  sem_t s;
> +  TEST_COMPARE (sem_init (&s, 0, 1), 0);
> +
> +  const struct timespec ts = make_timespec (0, 0);
> +
> +  /* These clocks are meaningless to sem_clockwait. */
> +#if defined(CLOCK_PROCESS_CPUTIME_ID)
> +  TEST_COMPARE (sem_clockwait (&s, CLOCK_PROCESS_CPUTIME_ID, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +#endif
> +#if defined(CLOCK_THREAD_CPUTIME_ID)
> +  TEST_COMPARE (sem_clockwait (&s, CLOCK_THREAD_CPUTIME_ID, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +#endif
> +
> +  /* These clocks might be meaningful, but are currently unsupported
> +     by pthread_cond_clockwait. */
> +#if defined(CLOCK_REALTIME_COARSE)
> +  TEST_COMPARE (sem_clockwait (&s, CLOCK_REALTIME_COARSE, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +#endif
> +#if defined(CLOCK_MONOTONIC_RAW)
> +  TEST_COMPARE (sem_clockwait (&s, CLOCK_MONOTONIC_RAW, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +#endif
> +#if defined(CLOCK_MONOTONIC_COARSE)
> +  TEST_COMPARE (sem_clockwait (&s, CLOCK_MONOTONIC_COARSE, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +#endif
> +#if defined(CLOCK_BOOTTIME)
> +  TEST_COMPARE (sem_clockwait (&s, CLOCK_BOOTTIME, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +#endif
> +
> +  /* This is a completely invalid clock */
> +  TEST_COMPARE (sem_clockwait (&s, NOT_A_VALID_CLOCK, &ts), -1);
> +  TEST_COMPARE (errno, EINVAL);
> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>

Ok.

> diff --git a/nptl/tst-sem5.c b/nptl/tst-sem5.c
> index 396222b..843839b 100644
> --- a/nptl/tst-sem5.c
> +++ b/nptl/tst-sem5.c
> @@ -25,10 +25,15 @@
>  #include <support/timespec.h>
>  #include <support/xtime.h>
>  
> +/* A bogus clock value that tells run_test to use
> +   sem_timedwait rather than sem_clockwait */
> +#define CLOCK_USE_TIMEDWAIT (-1)

Maybe use a enum instead of a magic constant ?

>  
> -static int
> -do_test (void)
> +static void
> +do_test_clock (clockid_t clockid)
>  {
> +  const clockid_t clockid_for_get =
> +    clockid == CLOCK_USE_TIMEDWAIT ? CLOCK_REALTIME : clockid;
>    sem_t s;
>    struct timespec ts;
>  
> @@ -36,14 +41,22 @@ do_test (void)
>    TEST_COMPARE (TEMP_FAILURE_RETRY (sem_wait (&s)), 0);
>  
>    /* We wait for half a second.  */
> -  xclock_gettime (CLOCK_REALTIME, &ts);
> +  xclock_gettime (clockid_for_get, &ts);
>    ts = timespec_add (ts, make_timespec (0, TIMESPEC_HZ/2));
>  
>    errno = 0;
> -  TEST_COMPARE (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)), -1);
> +  TEST_COMPARE (TEMP_FAILURE_RETRY ((clockid == CLOCK_USE_TIMEDWAIT)
> +                                    ? sem_timedwait (&s, &ts)
> +                                    : sem_clockwait (&s, clockid, &ts)), -1);
>    TEST_COMPARE (errno, ETIMEDOUT);
> -  TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts);
> +  TEST_TIMESPEC_NOW_OR_AFTER (clockid_for_get, ts);
> +}
>  
> +static int do_test (void)
> +{
> +  do_test_clock (CLOCK_USE_TIMEDWAIT);
> +  do_test_clock (CLOCK_REALTIME);
> +  do_test_clock (CLOCK_MONOTONIC);
>    return 0;
>  }
>  
> diff --git a/sysdeps/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
> index 87c0543..6e74aa3 100644
> --- a/sysdeps/pthread/semaphore.h
> +++ b/sysdeps/pthread/semaphore.h
> @@ -64,6 +64,13 @@ extern int sem_timedwait (sem_t *__restrict __sem,
>    __nonnull ((1, 2));
>  #endif
>  
> +#ifdef __USE_GNU
> +extern int sem_clockwait (sem_t *__restrict __sem,
> +			  clockid_t clock,
> +			  const struct timespec *__restrict __abstime)
> +  __nonnull ((1, 3));
> +#endif
> +
>  /* Test whether SEM is posted.  */
>  extern int sem_trywait (sem_t *__sem) __THROWNL __nonnull ((1));
>  

Naming scheme as described before.

> diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> index 9a9e4ce..0294cb3 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> @@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> index b413007..1f63759 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> @@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.3.2 pthread_cond_broadcast F
>  GLIBC_2.3.2 pthread_cond_destroy F
>  GLIBC_2.3.2 pthread_cond_init F
> diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> index af82a4c..905392e 100644
> --- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> @@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 _IO_flockfile F
>  GLIBC_2.4 _IO_ftrylockfile F
>  GLIBC_2.4 _IO_funlockfile F
> diff --git a/sysdeps/unix/sysv/linux/csky/libpthread.abilist b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> index ea4b79a..fdf577c 100644
> --- a/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> @@ -233,3 +233,4 @@ GLIBC_2.29 tss_set F
>  GLIBC_2.29 wait F
>  GLIBC_2.29 waitpid F
>  GLIBC_2.29 write F
> +GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> index bcba07f..fa02154 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> @@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> index bece86d..86eb656 100644
> --- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> @@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> index ccc9449..406da6f 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> @@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> index af82a4c..905392e 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> @@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 _IO_flockfile F
>  GLIBC_2.4 _IO_ftrylockfile F
>  GLIBC_2.4 _IO_funlockfile F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> index bece86d..86eb656 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> @@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> index 5067375..bd9455d 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> @@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> index 0214496..c1792c5 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> index 0214496..c1792c5 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> index 78cac2a..8eca3c2 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> @@ -241,3 +241,4 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> index 09e8447..ca68bd7 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.3.4 siglongjmp F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> index 8300958..9e0500d 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> @@ -246,6 +246,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.3.4 siglongjmp F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> index 9a9e4ce..0294cb3 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> @@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> index c370fda..c6bddf9 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> @@ -235,3 +235,4 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> index d05468f..581e3be 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> index e8161aa..ed422c3 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> @@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> index bcba07f..fa02154 100644
> --- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> @@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> index b413007..e31e905 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> index ccc9449..406da6f 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> @@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> index 931c827..454d340 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> @@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
>  GLIBC_2.4 pthread_mutex_setprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> index c09c9b0..db565a1 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> @@ -243,3 +243,4 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 sem_clockwait F
> 

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

* Re: [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls
  2019-06-05 17:52   ` Adhemerval Zanella
@ 2019-06-06 12:06     ` Adhemerval Zanella
  2019-06-12 19:32     ` Adhemerval Zanella
  1 sibling, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-06 12:06 UTC (permalink / raw
  To: libc-alpha



>> diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
>> index 501f993..03312d6 100644
>> --- a/sysdeps/unix/sysv/linux/futex-internal.h
>> +++ b/sysdeps/unix/sysv/linux/futex-internal.h
>> @@ -162,15 +162,24 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
>>  
>>  /* See sysdeps/nptl/futex-internal.h for details.  */
>>  static __always_inline int
>> +futex_abstimed_supported_clockid (clockid_t clockid)
>> +{
>> +  return lll_futex_supported_clockid (clockid);
>> +}

An addendum is to change it to return bool instead of int, since you using
with contraction checks on all patchset.

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

* Re: [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait
  2019-05-27 20:03 ` [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait Mike Crowe
@ 2019-06-06 12:53   ` Adhemerval Zanella
  2019-06-12 20:22     ` Adhemerval Zanella
  2019-06-18 13:53     ` Mike Crowe
  0 siblings, 2 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-06 12:53 UTC (permalink / raw
  To: libc-alpha



On 27/05/2019 17:03, Mike Crowe wrote:
> Add:
> 
>  int pthread_cond_clockwait (pthread_cond_t *cond,
>                              pthread_mutex_t *mutex,
>                              clockid_t clockid,
>                              const struct timespec *abstime)
> 
> which behaves just like pthread_cond_timedwait except it always measures
> abstime against the supplied clockid. Currently supports CLOCK_REALTIME and
> CLOCK_MONOTONIC and returns EINVAL if any other clock is specified.
> 
> Includes feedback from many others. This function was originally
> proposed[1] as pthread_cond_timedwaitonclock_np, but The Austin Group
> preferred the new name.

For an initial implementation we will need to use a possible non reserved
name, like pthread_cond_clockwait_np.  Wehen Austin Group finally add this
on standard we can then add an alias with an update to abilist.

> 
> 	* nptl/Makefile: Add tst-cond26 and tst-cond27
> 
> 	* nptl/Versions (GLIBC_2.30): Add pthread_cond_clockwait
> 
> 	* sysdeps/nptl/pthread.h: Likewise
> 
> 	* nptl/forward.c: Add __pthread_cond_clockwait
> 
> 	* nptl/forward.c: Likewise
> 
> 	* nptl/pthreadP.h: Likewise
> 
> 	* sysdeps/nptl/pthread-functions.h: Likewise
> 
> 	* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Add
> 	clockid parameter and comment describing why we don't need to check
> 	its value. Use that value when calling
> 	futex_abstimed_wait_cancelable rather than reading the clock from
> 	the flags. (__pthread_cond_wait): Pass unused clockid parameter.
> 	(__pthread_cond_timedwait): Read clock from flags and pass it to
> 	__pthread_cond_wait_common. (__pthread_cond_clockwait): Add new
> 	function with weak alias from pthread_cond_clockwait.
> 
> 	* sysdeps/mach/hurd/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 
> 	* nptl/tst-cond11.c (run_test): Support testing
> 	pthread_cond_clockwait too by using a special magic
> 	CLOCK_USE_ATTR_CLOCK value to determine whether to call
> 	pthread_cond_timedwait or pthread_cond_clockwait. (do_test): Pass
> 	CLOCK_USE_ATTR_CLOCK for existing tests, and add new tests using
> 	all combinations of CLOCK_MONOTONIC and CLOCK_REALTIME.
> 
> 	* ntpl/tst-cond26.c: New test for passing unsupported and invalid
> 	clocks to pthread_cond_clockwait.
> 
> 	* nptl/tst-cond27.c: Add test similar to tst-cond5.c, but using
> 	struct timespec and pthread_cond_clockwait.
> 
> 	* manual/threads.texi: Document pthread_cond_clockwait. The comment
> 	was provided by Carlos O'Donell.
> 
> [1] https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html

For this addition we will also need a NEWS entry.

> ---
>  ChangeLog                                                       | 85 +++++++-
>  manual/threads.texi                                             | 20 ++-
>  nptl/Makefile                                                   |  1 +-
>  nptl/Versions                                                   |  2 +-
>  nptl/forward.c                                                  |  5 +-
>  nptl/nptl-init.c                                                |  1 +-
>  nptl/pthreadP.h                                                 |  4 +-
>  nptl/pthread_cond_wait.c                                        | 44 +++-
>  nptl/tst-cond11.c                                               | 37 ++-
>  nptl/tst-cond26.c                                               | 77 ++++++-
>  nptl/tst-cond27.c                                               | 68 ++++++-
>  sysdeps/nptl/pthread-functions.h                                |  4 +-
>  sysdeps/nptl/pthread.h                                          | 15 +-
>  sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |  1 +-
>  sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |  1 +-
>  sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |  1 +-
>  sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |  1 +-
>  sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |  1 +-
>  sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |  1 +-
>  sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |  1 +-
>  sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |  1 +-
>  sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |  1 +-
>  sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |  1 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |  1 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |  1 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |  1 +-
>  sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |  1 +-
>  sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |  1 +-
>  sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |  1 +-
>  sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |  1 +-
>  sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |  1 +-
>  sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |  1 +-
>  sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |  1 +-
>  sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |  1 +-
>  37 files changed, 369 insertions(+), 18 deletions(-)
>  create mode 100644 nptl/tst-cond26.c
>  create mode 100644 nptl/tst-cond27.c
> 
> diff --git a/ChangeLog b/ChangeLog
> index 814e331..1f95dd4 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,5 +1,90 @@
>  2019-05-27  Mike Crowe  <mac@mcrowe.com>
>  
> +	nptl: Add POSIX-proposed pthread_cond_clockwait which behaves just
> +	like pthread_cond_timedwait except it always measures abstime
> +	against the supplied clockid.
> +
> +	* nptl/Makefile: Add tst-cond26 and tst-cond27
> +
> +	* nptl/Versions (GLIBC_2.30): Add pthread_cond_clockwait
> +
> +	* sysdeps/nptl/pthread.h: Likewise
> +
> +	* nptl/forward.c: Add __pthread_cond_clockwait
> +
> +	* nptl/forward.c: Likewise
> +
> +	* nptl/pthreadP.h: Likewise
> +
> +	* sysdeps/nptl/pthread-functions.h: Likewise
> +
> +	* nptl/pthread_cond_wait.c (__pthread_cond_wait_common): Add
> +	clockid parameter and comment describing why we don't need to check
> +	its value. Use that value when calling
> +	futex_abstimed_wait_cancelable rather than reading the clock from
> +	the flags. (__pthread_cond_wait): Pass unused clockid parameter.
> +	(__pthread_cond_timedwait): Read clock from flags and pass it to
> +	__pthread_cond_wait_common. (__pthread_cond_clockwait): Add new
> +	function with weak alias from pthread_cond_clockwait.
> +
> +	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +
> +	* nptl/tst-cond11.c (run_test): Support testing
> +	pthread_cond_clockwait too by using a special magic
> +	CLOCK_USE_ATTR_CLOCK value to determine whether to call
> +	pthread_cond_timedwait or pthread_cond_clockwait. (do_test): Pass
> +	CLOCK_USE_ATTR_CLOCK for existing tests, and add new tests using
> +	all combinations of CLOCK_MONOTONIC and CLOCK_REALTIME.
> +
> +	* ntpl/tst-cond26.c: New test for passing unsupported and invalid
> +	clocks to pthread_cond_clockwait.
> +
> +	* nptl/tst-cond27.c: Add test similar to tst-cond5.c, but using
> +	struct timespec and pthread_cond_clockwait.
> +
> +	* manual/threads.texi: Document pthread_cond_clockwait. The comment
> +	was provided by Carlos O'Donell.
> +
> +2019-05-27  Mike Crowe  <mac@mcrowe.com>
> +
>  	nptl: Add POSIX-proposed sem_clockwait which behaves just like
>  	sem_timedwait, but measures abstime against the specified clock.
>  
> diff --git a/manual/threads.texi b/manual/threads.texi
> index 674267c..91462f5 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -679,6 +679,26 @@ against the clock specified by @var{clockid} rather than
>  @code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
>  @end deftypefun
>  
> +@comment pthread.h
> +@comment POSIX-proposed
> +@deftypefun int pthread_cond_clockwait (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 @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,
> +@var{clockid} must be either @code{CLOCK_MONOTONIC} or
> +@code{CLOCK_REALTIME}.
> +@end deftypefun
> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy

Ok modules the symbol name change.

> diff --git a/nptl/Makefile b/nptl/Makefile
> index 43a99dc..70a2139 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -250,6 +250,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
>  	tst-cond8 tst-cond9 tst-cond10 tst-cond11 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-cond26 tst-cond27 \
>  	tst-cond-except \
>  	tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
>  	tst-robust6 tst-robust7 tst-robust8 tst-robust9 \
> diff --git a/nptl/Versions b/nptl/Versions
> index cd1806c..8c094d0 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -278,7 +278,7 @@ libpthread {
>    }
>  
>    GLIBC_2.30 {
> -    sem_clockwait;
> +    sem_clockwait; pthread_cond_clockwait;
>    }
>  
>    GLIBC_PRIVATE {

Ok.

> diff --git a/nptl/forward.c b/nptl/forward.c
> index ed1e7d0..50f358f 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_clockwait,
> +	 (pthread_cond_t *cond, pthread_mutex_t *mutex, clockid_t clockid,
> +	  const struct timespec *abstime), (cond, mutex, clockid, abstime),
> +	 0)
> +weak_alias (__pthread_cond_clockwait, pthread_cond_clockwait);
>  
>  
>  FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),

Ok.

> diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
> index 73935f8..9c2a3d7 100644
> --- a/nptl/nptl-init.c
> +++ b/nptl/nptl-init.c
> @@ -95,6 +95,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_clockwait = __pthread_cond_clockwait,
>  # 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,

Ok.

> diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
> index 66527d8..9caa2b4 100644
> --- a/nptl/pthreadP.h
> +++ b/nptl/pthreadP.h
> @@ -449,6 +449,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_clockwait (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 *));

Ok.

> diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
> index 7385562..558f930 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;
> @@ -386,6 +387,11 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>  
>    LIBC_PROBE (cond_wait, 2, cond, mutex);
>  
> +  /* clockid will already have been checked by
> +     __pthread_cond_clockwait or pthread_condattr_setclock, or we
> +     don't use it if abstime is NULL, so we don't need to check it
> +     here. */
> +
>    /* Acquire a position (SEQ) in the waiter sequence (WSEQ).  We use an
>       atomic operation because signals and broadcasts may update the group
>       switch without acquiring the mutex.  We do not need release MO here

Ok.

> @@ -511,10 +517,6 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>  	        err = ETIMEDOUT;
>  	      else
>  		{
> -		  const clockid_t clockid =
> -		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
> -		    CLOCK_MONOTONIC : CLOCK_REALTIME;
> -
>  		  err = futex_abstimed_wait_cancelable
>                      (cond->__data.__g_signals + g, 0, clockid, abstime,
>                       private);

Ok.

> @@ -632,7 +634,8 @@ __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);
> +  /* clockid is unused when abstime is NULL. */
> +  return __pthread_cond_wait_common (cond, mutex, 0, NULL);
>  }
>  
>  /* See __pthread_cond_wait_common.  */

Ok.

> @@ -644,10 +647,39 @@ __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);
> +
> +  /* 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 clockid = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
> +                    ? CLOCK_MONOTONIC : CLOCK_REALTIME;
> +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
> +}
> +

The relaxed atomic seems right, but I would like to a ack from another mantainer.

> +/* See __pthread_cond_wait_common.  */
> +int
> +__pthread_cond_clockwait (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;

Wouldn' t a  __nonnull ((X)) be better for this?

> +
> +  if (!futex_abstimed_supported_clockid (clockid))
> +    return EINVAL;
> +
> +  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
> +  if (clockid == CLOCK_MONOTONIC
> +      && !futex_supports_exact_relative_timeouts ())
> +    return EINVAL;

pthread_condattr_setclock returns ENOSUP for this case, should it does the same?

> +
> +  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_clockwait, pthread_cond_clockwait);
> diff --git a/nptl/tst-cond11.c b/nptl/tst-cond11.c
> index 3bc4ff4..e42e71d 100644
> --- a/nptl/tst-cond11.c
> +++ b/nptl/tst-cond11.c
> @@ -26,24 +26,27 @@
>  #include <support/xthread.h>
>  #include <support/xtime.h>
>  
> +/* A bogus clock value that tells run_test to use
> +   pthread_cond_timedwait rather than pthread_condclockwait. */
> +#define CLOCK_USE_ATTR_CLOCK (-1)

Wouldn't a enum be better to set the clock to use?

>  
>  #if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
>  static int
> -run_test (clockid_t cl)
> +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 ("clock = %d\n", (int) cl);
> +  printf ("attr_clock = %d\n", (int) attr_clock);

I think for debug logging it is better to enable only if test_verbose
(support/support_test_main.c:197) is set.

>  
>    TEST_COMPARE (pthread_condattr_init (&condattr), 0);
> -  TEST_COMPARE (pthread_condattr_setclock (&condattr, cl), 0);
> +  TEST_COMPARE (pthread_condattr_setclock (&condattr, attr_clock), 0);
>  
> -  clockid_t cl2;
> -  TEST_COMPARE (pthread_condattr_getclock (&condattr, &cl2), 0);
> -  TEST_COMPARE (cl, cl2);
> +  clockid_t attr_clock_read;
> +  TEST_COMPARE (pthread_condattr_getclock (&condattr, &attr_clock_read), 0);
> +  TEST_COMPARE (attr_clock, attr_clock_read);
>  
>    TEST_COMPARE (pthread_cond_init (&cond, &condattr), 0);
>    TEST_COMPARE (pthread_condattr_destroy (&condattr), 0);
> @@ -57,13 +60,20 @@ run_test (clockid_t cl)
>    TEST_COMPARE (pthread_mutex_lock (&mut), EDEADLK);
>  
>    struct timespec ts_timeout;
> -  xclock_gettime (cl, &ts_timeout);
> +  xclock_gettime (wait_clock == CLOCK_USE_ATTR_CLOCK ? attr_clock : wait_clock,
> +                  &ts_timeout);
>  
>    /* Wait one second.  */
>    ++ts_timeout.tv_sec;
>  
> -  TEST_COMPARE (pthread_cond_timedwait (&cond, &mut, &ts_timeout), ETIMEDOUT);
> -  TEST_TIMESPEC_BEFORE_NOW (ts_timeout, cl);
> +  if (wait_clock == CLOCK_USE_ATTR_CLOCK) {
> +    TEST_COMPARE (pthread_cond_timedwait (&cond, &mut, &ts_timeout), ETIMEDOUT);
> +    TEST_TIMESPEC_BEFORE_NOW (ts_timeout, attr_clock);
> +  } else {
> +    TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, wait_clock, &ts_timeout),
> +                  ETIMEDOUT);
> +    TEST_TIMESPEC_BEFORE_NOW (ts_timeout, wait_clock);
> +  }
>  
>    xpthread_mutex_unlock (&mut);
>    xpthread_mutex_destroy (&mut);
> @@ -83,7 +93,7 @@ do_test (void)
>  
>  #else
>  
> -  run_test (CLOCK_REALTIME);
> +  run_test (CLOCK_REALTIME, CLOCK_USE_ATTR_CLOCK);
>  
>  # if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
>  #  if _POSIX_MONOTONIC_CLOCK == 0
> @@ -93,8 +103,13 @@ do_test (void)
>    else if (e == 0)
>        FAIL_RET ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
>    else
> +    {
>  #  endif
> -    run_test (CLOCK_MONOTONIC);
> +      run_test (CLOCK_MONOTONIC, CLOCK_USE_ATTR_CLOCK);
> +      run_test (CLOCK_REALTIME, CLOCK_MONOTONIC);
> +      run_test (CLOCK_MONOTONIC, CLOCK_MONOTONIC);
> +      run_test (CLOCK_MONOTONIC, CLOCK_REALTIME);
> +    }
>  # else
>    puts ("_POSIX_MONOTONIC_CLOCK not defined");
>  # endif> diff --git a/nptl/tst-cond26.c b/nptl/tst-cond26.c
> new file mode 100644
> index 0000000..2db7d2e
> --- /dev/null
> +++ b/nptl/tst-cond26.c
> @@ -0,0 +1,77 @@
> +/* Test unsupported/bad clocks passed to pthread_cond_clockwait.
> +
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <pthread.h>
> +#include <stdio.h>
> +#include <time.h>
> +#include <unistd.h>
> +#include <support/check.h>
> +#include <support/timespec.h>
> +#include <support/xthread.h>
> +
> +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
> +static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
> +
> +#define NOT_A_VALID_CLOCK 123456> +
> +static int
> +do_test (void)
> +{
> +  xpthread_mutex_lock (&mut);
> +
> +  const struct timespec ts = make_timespec (0, 0);
> +
> +  /* These clocks are meaningless to sem_clockwait. */
> +#if defined(CLOCK_PROCESS_CPUTIME_ID)
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        CLOCK_PROCESS_CPUTIME_ID, &ts), EINVAL);
> +#endif
> +#if defined(CLOCK_THREAD_CPUTIME_ID)
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        CLOCK_THREAD_CPUTIME_ID, &ts), EINVAL);
> +#endif
> +
> +  /* These clocks might be meaningful, but are currently unsupported
> +     by pthread_cond_clockwait. */
> +#if defined(CLOCK_REALTIME_COARSE)
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        CLOCK_REALTIME_COARSE, &ts), EINVAL);
> +#endif
> +#if defined(CLOCK_MONOTONIC_RAW)
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        CLOCK_MONOTONIC_RAW, &ts), EINVAL);
> +#endif
> +#if defined(CLOCK_MONOTONIC_COARSE)
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        CLOCK_MONOTONIC_COARSE, &ts), EINVAL);
> +#endif
> +#if defined(CLOCK_BOOTTIME)
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        CLOCK_BOOTTIME, &ts), EINVAL);
> +#endif
> +
> +  /* This is a completely invalid clock */
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
> +                                        NOT_A_VALID_CLOCK, &ts), EINVAL);
> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>

Ok.

> diff --git a/nptl/tst-cond27.c b/nptl/tst-cond27.c
> new file mode 100644
> index 0000000..8d20663
> --- /dev/null
> +++ b/nptl/tst-cond27.c
> @@ -0,0 +1,68 @@
> +/* Test pthread_cond_clockwait timeout.
> +
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <pthread.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <time.h>
> +#include <sys/time.h>
> +#include <support/check.h>
> +#include <support/timespec.h>
> +#include <support/xthread.h>
> +
> +
> +static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
> +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
> +
> +
> +static int
> +do_test_clock (clockid_t clockid)
> +{
> +  /* Get the mutex.  */
> +  xpthread_mutex_lock (&mut);
> +
> +  /* Waiting for the condition will fail.  But we want the timeout here.  */
> +  struct timespec ts_now;
> +  xclock_gettime (clockid, &ts_now);
> +
> +  const struct timespec ts_timeout =
> +    timespec_add (ts_now, make_timespec (0, 500000000));
> +
> +  /* In theory pthread_cond_clockwait could return zero here due to
> +     spurious wakeup. However that can't happen without a signal or an
> +     additional waiter. */
> +  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, clockid, &ts_timeout),
> +                ETIMEDOUT);
> +
> +  xpthread_mutex_unlock (&mut);
> +
> +  return 0;
> +}
> +
> +static int
> +do_test (void)
> +{
> +  do_test_clock (CLOCK_MONOTONIC);
> +  do_test_clock (CLOCK_REALTIME);
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>

Ok.

> diff --git a/sysdeps/nptl/pthread-functions.h b/sysdeps/nptl/pthread-functions.h
> index cd5e94d..cfa9660 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_clockwait) (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 *,

Ok.

> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
> index 704a3c4..f000b1e 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_clockwait (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.  */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> index 0294cb3..5af4b8a 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> @@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> index 1f63759..a00adfb 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> @@ -227,6 +227,7 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.3.2 pthread_cond_broadcast F
>  GLIBC_2.3.2 pthread_cond_destroy F
> diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> index 905392e..4aeee7b 100644
> --- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> @@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 _IO_flockfile F
>  GLIBC_2.4 _IO_ftrylockfile F
> diff --git a/sysdeps/unix/sysv/linux/csky/libpthread.abilist b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> index fdf577c..2c08b76 100644
> --- a/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> @@ -233,4 +233,5 @@ GLIBC_2.29 tss_set F
>  GLIBC_2.29 wait F
>  GLIBC_2.29 waitpid F
>  GLIBC_2.29 write F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> index fa02154..dc0d4ad 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> @@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> index 86eb656..1830e40 100644
> --- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> @@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> index 406da6f..0811d73 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> @@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> index 905392e..4aeee7b 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> @@ -27,6 +27,7 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  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 86eb656..1830e40 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> @@ -253,6 +253,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> index bd9455d..f2be6b4 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> @@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> index c1792c5..41527fe 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> index c1792c5..41527fe 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> index 8eca3c2..04fc3a6 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> @@ -241,4 +241,5 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> index ca68bd7..ebdab1a 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.3.4 siglongjmp F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> index 9e0500d..8a1fb34 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> @@ -246,6 +246,7 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.3.4 siglongjmp F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> index 0294cb3..5af4b8a 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> @@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> index c6bddf9..a1c8c2e 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> @@ -235,4 +235,5 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> index 581e3be..0feb3cf 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> index ed422c3..cc4f160 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> @@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> index fa02154..dc0d4ad 100644
> --- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> @@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> index e31e905..ed0574a 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> @@ -255,6 +255,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> index 406da6f..0811d73 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> @@ -247,6 +247,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> index 454d340..aaa1c3b 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> @@ -245,6 +245,7 @@ GLIBC_2.3.4 pthread_attr_setaffinity_np F
>  GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> index db565a1..5d02b03 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> @@ -243,4 +243,5 @@ GLIBC_2.28 tss_create F
>  GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
> +GLIBC_2.30 pthread_cond_clockwait F
>  GLIBC_2.30 sem_clockwait F
> 

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-05 21:07   ` Adhemerval Zanella
@ 2019-06-06 15:40     ` Mike Crowe
  2019-06-06 17:43       ` Adhemerval Zanella
  2019-06-25 18:06       ` Florian Weimer
  0 siblings, 2 replies; 36+ messages in thread
From: Mike Crowe @ 2019-06-06 15:40 UTC (permalink / raw
  To: libc-alpha

On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
> On 27/05/2019 17:03, Mike Crowe wrote:
> > Add:
> > 
> >  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
> > 
> > which behaves just like sem_timedwait, but measures abstime against the
> > specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
> > sets errno == EINVAL if any other clock is specified.
> 
> For non-POSIX definition we will need to first export it as a GNU extension
> with a possible non-reserved name and later, when it is included on the 
> standard, to add an alias to the expected name.  
> 
> The usual naming scheme is to append the _np suffix (non-portable) on 
> implementation, similar to recent posix_spawn file action extensions.
> In this case it would be sem_clockwait_np.

Hi Adhemerval,

I thought we went through this before[1] and agreed that the _np suffix wasn't
necessary in this case. However, I couldn't find a reply to Florian
agreeing to that.

[1] https://marc.info/?l=glibc-alpha&m=155256303513500

[snip other helpful review comments that I will work on]

> > +
> > +   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 "sem_waitcommon.c"
> > +
> > +int
> > +sem_clockwait (sem_t *sem, clockid_t clockid,
> > +	       const struct timespec *abstime)
> > +{
> > +  /* Check that supplied clockid is one we support, even if we don't
> > +     end up waiting. */
> > +  if (!futex_abstimed_supported_clockid (clockid))
> > +    {
> > +      __set_errno (EINVAL);
> > +      return -1;
> > +    }
> > +
> > +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
> > +    {
> > +      __set_errno (EINVAL);
> > +      return -1;
> > +    }
> > +
> > +  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
> > +    return 0;
> > +  else
> > +    return __new_sem_wait_slow ((struct new_sem *) sem, clockid, abstime);
> > +}
> 
> Ok.  As for BZ#23006 I think we should follow Austin Group latest resolution
> for sem_wait/sem_timedwait and not make it a cancellable entrypoint.

I think that's what I've done here (perhaps purely by accident because I'd
probably copied the code prior to
47677f2edc815e85d0383a89b09733e95e5d7302.) Would you like me to add a
comment to describe why there's no call to __pthread_test_cancel() here?

> > diff --git a/nptl/tst-sem5.c b/nptl/tst-sem5.c
> > index 396222b..843839b 100644
> > --- a/nptl/tst-sem5.c
> > +++ b/nptl/tst-sem5.c
> > @@ -25,10 +25,15 @@
> >  #include <support/timespec.h>
> >  #include <support/xtime.h>
> >  
> > +/* A bogus clock value that tells run_test to use
> > +   sem_timedwait rather than sem_clockwait */
> > +#define CLOCK_USE_TIMEDWAIT (-1)
> 
> Maybe use a enum instead of a magic constant ?

Do you mean just:

enum { CLOCK_USE_TIMEDWAIT = -1 };

or something like:

enum
{
  CLOCK_MONOTONIC_ = CLOCK_MONOTONIC,
  CLOCK_REALTIME_ = CLOCK_REALTIME,
  CLOCK_USE_TIMEDWAIT
};

in attempt to ensure that CLOCK_USE_TIMEDWAIT doesn't overlap? I can't see
how this can work with potentially-arbitrary values for CLOCK_MONOTONIC and
CLOCK_REALTIME. This would fail if CLOCK_REALTIME=42 and
CLOCK_MONOTONIC=43.

Since glibc is responsible declaring CLOCK_MONOTONIC and CLOCK_REALTIME, and can't change
them without breaking ABI, I thought -1 would be safe. If we're worried, I
could add explicit checks that CLOCK_USE_TIMEDWAIT doesn't have the same
value as CLOCK_MONOTONIC or CLOCK_REALTIME.

Thanks.

Mike.

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-06 15:40     ` Mike Crowe
@ 2019-06-06 17:43       ` Adhemerval Zanella
  2019-06-06 19:20         ` Adhemerval Zanella
  2019-06-25 18:06       ` Florian Weimer
  1 sibling, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-06 17:43 UTC (permalink / raw
  To: libc-alpha



On 06/06/2019 12:40, Mike Crowe wrote:
> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>> On 27/05/2019 17:03, Mike Crowe wrote:
>>> Add:
>>>
>>>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>>>
>>> which behaves just like sem_timedwait, but measures abstime against the
>>> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>>> sets errno == EINVAL if any other clock is specified.
>>
>> For non-POSIX definition we will need to first export it as a GNU extension
>> with a possible non-reserved name and later, when it is included on the 
>> standard, to add an alias to the expected name.  
>>
>> The usual naming scheme is to append the _np suffix (non-portable) on 
>> implementation, similar to recent posix_spawn file action extensions.
>> In this case it would be sem_clockwait_np.
> 
> Hi Adhemerval,
> 
> I thought we went through this before[1] and agreed that the _np suffix wasn't
> necessary in this case. However, I couldn't find a reply to Florian
> agreeing to that.
> 
> [1] https://marc.info/?l=glibc-alpha&m=155256303513500
> 
> [snip other helpful review comments that I will work on]

I take it is rule of thumb to add names different than the expected one from
standard, but I don't have a strong opinion here.

The posix_spawn, for instance, were added to mimic the other system names 
(Solaris in this case) and the name originally were added with the extension 
to make it explicit it a non-portable extension. But Solaris also did not
seem to work towards to make it POSIX standard, so it might the reason to
it.

> 
>>> +
>>> +   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 "sem_waitcommon.c"
>>> +
>>> +int
>>> +sem_clockwait (sem_t *sem, clockid_t clockid,
>>> +	       const struct timespec *abstime)
>>> +{
>>> +  /* Check that supplied clockid is one we support, even if we don't
>>> +     end up waiting. */
>>> +  if (!futex_abstimed_supported_clockid (clockid))
>>> +    {
>>> +      __set_errno (EINVAL);
>>> +      return -1;
>>> +    }
>>> +
>>> +  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
>>> +    {
>>> +      __set_errno (EINVAL);
>>> +      return -1;
>>> +    }
>>> +
>>> +  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
>>> +    return 0;
>>> +  else
>>> +    return __new_sem_wait_slow ((struct new_sem *) sem, clockid, abstime);
>>> +}
>>
>> Ok.  As for BZ#23006 I think we should follow Austin Group latest resolution
>> for sem_wait/sem_timedwait and not make it a cancellable entrypoint.
> 
> I think that's what I've done here (perhaps purely by accident because I'd
> probably copied the code prior to
> 47677f2edc815e85d0383a89b09733e95e5d7302.) Would you like me to add a
> comment to describe why there's no call to __pthread_test_cancel() here?

Yes, please do.

> 
>>> diff --git a/nptl/tst-sem5.c b/nptl/tst-sem5.c
>>> index 396222b..843839b 100644
>>> --- a/nptl/tst-sem5.c
>>> +++ b/nptl/tst-sem5.c
>>> @@ -25,10 +25,15 @@
>>>  #include <support/timespec.h>
>>>  #include <support/xtime.h>
>>>  
>>> +/* A bogus clock value that tells run_test to use
>>> +   sem_timedwait rather than sem_clockwait */
>>> +#define CLOCK_USE_TIMEDWAIT (-1)
>>
>> Maybe use a enum instead of a magic constant ?
> 
> Do you mean just:
> 
> enum { CLOCK_USE_TIMEDWAIT = -1 };
> 
> or something like:
> 
> enum
> {
>   CLOCK_MONOTONIC_ = CLOCK_MONOTONIC,
>   CLOCK_REALTIME_ = CLOCK_REALTIME,
>   CLOCK_USE_TIMEDWAIT
> };
> 
> in attempt to ensure that CLOCK_USE_TIMEDWAIT doesn't overlap? I can't see
> how this can work with potentially-arbitrary values for CLOCK_MONOTONIC and
> CLOCK_REALTIME. This would fail if CLOCK_REALTIME=42 and
> CLOCK_MONOTONIC=43.
> 
> Since glibc is responsible declaring CLOCK_MONOTONIC and CLOCK_REALTIME, and can't change
> them without breaking ABI, I thought -1 would be safe. If we're worried, I
> could add explicit checks that CLOCK_USE_TIMEDWAIT doesn't have the same
> value as CLOCK_MONOTONIC or CLOCK_REALTIME.

Yeah, I think this over-engineering is not really required.

> 
> Thanks.
> 
> Mike.
> 

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

* Re: [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions
  2019-05-27 20:03 ` [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions Mike Crowe
@ 2019-06-06 19:18   ` Adhemerval Zanella
  2019-06-07 17:01     ` Mike Crowe
  0 siblings, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-06 19:18 UTC (permalink / raw
  To: libc-alpha



On 27/05/2019 17:03, Mike Crowe wrote:
> As recommended by the comments in the implementations of
> pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock, let's move the
> timeout validity checks into the corresponding pthread_rwlock_rdlock_full
> and pthread_rwlock_wrlock_full functions. Since these functions may be
> called with abstime == NULL, an extra check for that is necessary too.

Is this really a gain here? It just moves some code around and add
an extra non required check. Wouldn't be better just to remove the
comments?

> 
> 	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full):
> 	Check validity of abstime parameter.
> 	(__pthread_rwlock_rwlock_full): Likewise.
> 
> 	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
> 	Remove check for validity of abstime parameter.
> 
> 	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
> 	Likewise.
> ---
>  ChangeLog                         | 14 ++++++++++++++
>  nptl/pthread_rwlock_common.c      | 20 ++++++++++++++++++++
>  nptl/pthread_rwlock_timedrdlock.c | 10 ----------
>  nptl/pthread_rwlock_timedwrlock.c | 10 ----------
>  4 files changed, 34 insertions(+), 20 deletions(-)
> 
> diff --git a/ChangeLog b/ChangeLog
> index 1f95dd4..22a8bdc 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,5 +1,19 @@
>  2019-05-27  Mike Crowe  <mac@mcrowe.com>
>  
> +	nptl: pthread_rwlock: Move timeout validation into _full functions
> +
> +	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full):
> +	Check validity of abstime parameter.
> +	(__pthread_rwlock_rwlock_full): Likewise.
> +
> +	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
> +	Remove check for validity of abstime parameter.
> +
> +	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
> +	Likewise.
> +
> +2019-05-27  Mike Crowe  <mac@mcrowe.com>
> +
>  	nptl: Add POSIX-proposed pthread_cond_clockwait which behaves just
>  	like pthread_cond_timedwait except it always measures abstime
>  	against the supplied clockid.
> diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
> index 89ba21a..120b880 100644
> --- a/nptl/pthread_rwlock_common.c
> +++ b/nptl/pthread_rwlock_common.c
> @@ -282,6 +282,16 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
>  {
>    unsigned int r;
>  
> +  /* Make sure any passed in timeout value is valid.  Note that the previous
> +     implementation assumed that this check *must* not be performed if there
> +     would in fact be no blocking; however, POSIX only requires that "the
> +     validity of the abstime parameter need not be checked if the lock can be
> +     immediately acquired" (i.e., we need not but may check it).  */
> +  if (abstime
> +      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
> +      || abstime->tv_nsec < 0))
> +    return EINVAL;
> +
>    /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
>       situation we recognize and report.  */
>    if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
> @@ -576,6 +586,16 @@ static __always_inline int
>  __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
>      const struct timespec *abstime)
>  {
> +  /* Make sure any passed in timeout value is valid.  Note that the previous
> +     implementation assumed that this check *must* not be performed if there
> +     would in fact be no blocking; however, POSIX only requires that "the
> +     validity of the abstime parameter need not be checked if the lock can be
> +     immediately acquired" (i.e., we need not but may check it).  */
> +  if (abstime
> +      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
> +      || abstime->tv_nsec < 0))
> +    return EINVAL;
> +
>    /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
>       situation we recognize and report.  */
>    if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
> diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c
> index aa00530..84c1983 100644
> --- a/nptl/pthread_rwlock_timedrdlock.c
> +++ b/nptl/pthread_rwlock_timedrdlock.c
> @@ -23,15 +23,5 @@ int
>  pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
>      const struct timespec *abstime)
>  {
> -  /* Make sure the passed in timeout value is valid.  Note that the previous
> -     implementation assumed that this check *must* not be performed if there
> -     would in fact be no blocking; however, POSIX only requires that "the
> -     validity of the abstime parameter need not be checked if the lock can be
> -     immediately acquired" (i.e., we need not but may check it).  */
> -  /* ??? Just move this to __pthread_rwlock_rdlock_full?  */
> -  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
> -      || abstime->tv_nsec < 0))
> -    return EINVAL;
> -
>    return __pthread_rwlock_rdlock_full (rwlock, abstime);
>  }
> diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
> index 3c92e44..f0b745d 100644
> --- a/nptl/pthread_rwlock_timedwrlock.c
> +++ b/nptl/pthread_rwlock_timedwrlock.c
> @@ -23,15 +23,5 @@ int
>  pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
>      const struct timespec *abstime)
>  {
> -  /* Make sure the passed in timeout value is valid.  Note that the previous
> -     implementation assumed that this check *must* not be performed if there
> -     would in fact be no blocking; however, POSIX only requires that "the
> -     validity of the abstime parameter need not be checked if the lock can be
> -     immediately acquired" (i.e., we need not but may check it).  */
> -  /* ??? Just move this to __pthread_rwlock_wrlock_full?  */
> -  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
> -      || abstime->tv_nsec < 0))
> -    return EINVAL;
> -
>    return __pthread_rwlock_wrlock_full (rwlock, abstime);
>  }
> 

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-06 17:43       ` Adhemerval Zanella
@ 2019-06-06 19:20         ` Adhemerval Zanella
  0 siblings, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-06 19:20 UTC (permalink / raw
  To: libc-alpha; +Cc: Joseph Myers



On 06/06/2019 14:43, Adhemerval Zanella wrote:
> 
> 
> On 06/06/2019 12:40, Mike Crowe wrote:
>> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>>> On 27/05/2019 17:03, Mike Crowe wrote:
>>>> Add:
>>>>
>>>>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>>>>
>>>> which behaves just like sem_timedwait, but measures abstime against the
>>>> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>>>> sets errno == EINVAL if any other clock is specified.
>>>
>>> For non-POSIX definition we will need to first export it as a GNU extension
>>> with a possible non-reserved name and later, when it is included on the 
>>> standard, to add an alias to the expected name.  
>>>
>>> The usual naming scheme is to append the _np suffix (non-portable) on 
>>> implementation, similar to recent posix_spawn file action extensions.
>>> In this case it would be sem_clockwait_np.
>>
>> Hi Adhemerval,
>>
>> I thought we went through this before[1] and agreed that the _np suffix wasn't
>> necessary in this case. However, I couldn't find a reply to Florian
>> agreeing to that.
>>
>> [1] https://marc.info/?l=glibc-alpha&m=155256303513500
>>
>> [snip other helpful review comments that I will work on]
> 
> I take it is rule of thumb to add names different than the expected one from
> standard, but I don't have a strong opinion here.
> 
> The posix_spawn, for instance, were added to mimic the other system names 
> (Solaris in this case) and the name originally were added with the extension 
> to make it explicit it a non-portable extension. But Solaris also did not
> seem to work towards to make it POSIX standard, so it might the reason to
> it.

Joseph added on IRC that we should add the symbols with the expected naming, 
but remember there might be future incompatibilities requiring symbol versioning.
I think it would be fine as well.

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

* Re: [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock
  2019-05-27 20:03 ` [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock Mike Crowe
@ 2019-06-07 14:05   ` Adhemerval Zanella
  2019-06-07 17:14     ` Mike Crowe
  0 siblings, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-07 14:05 UTC (permalink / raw
  To: libc-alpha



On 27/05/2019 17:03, Mike Crowe wrote:
> Add:
>  int pthread_rwlock_clockrdlock (pthread_rwlock_t *rwlock,
>                                  clockid_t clockid,
>                                  const struct timespec *abstime)
> and:
>  int pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
>                                  clockid_t clockid,
>                                  const struct timespec *abstime)
> 
> which behave like pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock
> respectively, except they always measure abstime against the supplied
> clockid. The functions currently support CLOCK_REALTIME and CLOCK_MONOTONIC
> and return EINVAL if any other clock is specified.
> 
> 	* sysdeps/nptl/pthread.h: Add pthread_rwlock_clockrdlock and
> 	pthread_wrlock_clockwrlock.
> 
> 	* nptl/Makefile: Build pthread_rwlock_clockrdlock.c and
> 	pthread_rwlock_clockwrlock.c.
> 
> 	* nptl/pthread_rwlock_clockrdlock.c: Implement
> 	pthread_rwlock_clockrdlock.
> 
> 	* nptl/pthread_rwlock_clockwrlock.c: Implement
> 	pthread_rwlock_clockwrlock.
> 
> 	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full): Add
> 	clockid parameter and verify that it indicates a supported clock on
> 	entry so that we fail even if it doesn't end up being used. Pass
> 	that clock on to futex_abstimed_wait when necessary.
> 	(__pthread_rwlock_wrlock_full): Likewise.
> 
> 	* nptl/pthread_rwlock_rdlock.c: (__pthread_rwlock_rdlock): Pass
> 	CLOCK_REALTIME to __pthread_rwlock_rdlock_full even though it won't
> 	be used because there's no timeout.
> 
> 	* nptl/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Pass
> 	CLOCK_REALTIME to __pthread_rwlock_wrlock_full even though it won't
> 	be used because there is no timeout.
> 
> 	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
> 	Pass CLOCK_REALTIME to __pthread_rwlock_rdlock_full since abstime
> 	uses that clock.
> 
> 	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
> 	Pass CLOCK_REALTIME to __pthread_rwlock_wrlock_full since abstime
> 	uses that clock.
> 
> 	* sysdeps/mach/hurd/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> 	(GLIBC_2.30): Likewise.
> 
> 	* nptl/tst-abstime.c (th): Add pthread_rwlock_clockrdlock and
> 	pthread_rwlock_clockwrlock timeout tests to match the existing
> 	pthread_rwlock_timedrdloock and pthread_rwlock_timedwrlock tests.
> 
> 	* nptl/tst-rwlock14.c (do_test): Likewise.
> 
> 	* nptl/tst-rwlock6.c (tf): Accept thread_args structure so that
> 	rwlock, a clockid and function name can be passed to the thread.
> 	(do_test_clock): Rename from do_test. Accept clockid parameter to
> 	specify test clock. Use the magic clockid value of
> 	CLOCK_USE_TIMEDLOCK to indicate that pthread_rwlock_timedrdlock and
> 	pthread_rwlock_timedwrlock should be tested, otherwise pass the
> 	specified clockid to pthread_rwlock_clockrdlock and
> 	pthread_rwlock_clockwrlock. Use xpthread_create and xpthread_join.
> 	(do_test): Call do_test_clock to test each clockid in turn.
> 
> 	* nptl/tst-rwlock7.c: Likewise.
> 
> 	* nptl/tst-rwlock9.c (writer_thread, reader_thread): Accept
> 	thread_args structure so that the (now int) thread number, the
> 	clockid and the function name can be passed to the thread.
> 	(do_test_clock): Renamed from do_test. Pass the necessary
> 	thread_args when creating the reader and writer threads. Use
> 	xpthread_create and xpthread_join.
> 	(do_test): Call do_test_clock to test each clockid in turn.
> 
> 	* manual/threads.texi: Add documentation for
> 	pthread_rwlock_clockrdlock and pthread_rwlock_clockwrclock.
> ---
>  ChangeLog                                                       | 113 +++++++-
>  manual/threads.texi                                             |  28 ++-
>  nptl/Makefile                                                   |   2 +-
>  nptl/Versions                                                   |   1 +-
>  nptl/pthread_rwlock_clockrdlock.c                               |  29 ++-
>  nptl/pthread_rwlock_clockwrlock.c                               |  29 ++-
>  nptl/pthread_rwlock_common.c                                    |  40 +-
>  nptl/pthread_rwlock_rdlock.c                                    |   2 +-
>  nptl/pthread_rwlock_timedrdlock.c                               |   2 +-
>  nptl/pthread_rwlock_timedwrlock.c                               |   2 +-
>  nptl/pthread_rwlock_wrlock.c                                    |   2 +-
>  nptl/tst-abstime.c                                              |   8 +-
>  nptl/tst-rwlock14.c                                             |  12 +-
>  nptl/tst-rwlock6.c                                              |  94 ++++--
>  nptl/tst-rwlock7.c                                              |  83 +++--
>  nptl/tst-rwlock9.c                                              | 102 ++++--
>  sysdeps/nptl/pthread.h                                          |  14 +-
>  sysdeps/unix/sysv/linux/aarch64/libpthread.abilist              |   2 +-
>  sysdeps/unix/sysv/linux/alpha/libpthread.abilist                |   2 +-
>  sysdeps/unix/sysv/linux/arm/libpthread.abilist                  |   2 +-
>  sysdeps/unix/sysv/linux/csky/libpthread.abilist                 |   2 +-
>  sysdeps/unix/sysv/linux/hppa/libpthread.abilist                 |   2 +-
>  sysdeps/unix/sysv/linux/i386/libpthread.abilist                 |   2 +-
>  sysdeps/unix/sysv/linux/ia64/libpthread.abilist                 |   2 +-
>  sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist        |   2 +-
>  sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist          |   2 +-
>  sysdeps/unix/sysv/linux/microblaze/libpthread.abilist           |   2 +-
>  sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist          |   2 +-
>  sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist          |   2 +-
>  sysdeps/unix/sysv/linux/nios2/libpthread.abilist                |   2 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist    |   2 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist |   2 +-
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist |   2 +-
>  sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist           |   2 +-
>  sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist         |   2 +-
>  sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist         |   2 +-
>  sysdeps/unix/sysv/linux/sh/libpthread.abilist                   |   2 +-
>  sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist        |   2 +-
>  sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist        |   2 +-
>  sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist            |   2 +-
>  sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist           |   2 +-
>  41 files changed, 511 insertions(+), 100 deletions(-)
>  create mode 100644 nptl/pthread_rwlock_clockrdlock.c
>  create mode 100644 nptl/pthread_rwlock_clockwrlock.c
> 
> diff --git a/ChangeLog b/ChangeLog
> index 22a8bdc..66589f8 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,5 +1,118 @@
>  2019-05-27  Mike Crowe  <mac@mcrowe.com>
>  
> +	nptl: Add POSIX-proposed pthread_rwlock_clockrdlock &
> +	pthread_rwlock_clockwrlock which behave like
> +	pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock
> +	respectively, except they always measure abstime against the
> +	supplied clockid. The functions currently support CLOCK_REALTIME
> +	and CLOCK_MONOTONIC and return EINVAL if any other clock is
> +	specified.
> +
> +	* sysdeps/nptl/pthread.h: Add pthread_rwlock_clockrdlock and
> +	pthread_wrlock_clockwrlock.
> +
> +	* nptl/Makefile: Build pthread_rwlock_clockrdlock.c and
> +	pthread_rwlock_clockwrlock.c.
> +
> +	* nptl/pthread_rwlock_clockrdlock.c: Implement
> +	pthread_rwlock_clockrdlock.
> +
> +	* nptl/pthread_rwlock_clockwrlock.c: Implement
> +	pthread_rwlock_clockwrlock.
> +
> +	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full): Add
> +	clockid parameter and verify that it indicates a supported clock on
> +	entry so that we fail even if it doesn't end up being used. Pass
> +	that clock on to futex_abstimed_wait when necessary.
> +	(__pthread_rwlock_wrlock_full): Likewise.
> +
> +	* nptl/pthread_rwlock_rdlock.c: (__pthread_rwlock_rdlock): Pass
> +	CLOCK_REALTIME to __pthread_rwlock_rdlock_full even though it won't
> +	be used because there's no timeout.
> +
> +	* nptl/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Pass
> +	CLOCK_REALTIME to __pthread_rwlock_wrlock_full even though it won't
> +	be used because there is no timeout.
> +
> +	* nptl/pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
> +	Pass CLOCK_REALTIME to __pthread_rwlock_rdlock_full since abstime
> +	uses that clock.
> +
> +	* nptl/pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
> +	Pass CLOCK_REALTIME to __pthread_rwlock_wrlock_full since abstime
> +	uses that clock.
> +
> +	* sysdeps/unix/sysv/linux/aarch64/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/alpha/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/arm/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/csky/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/hppa/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/i386/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/ia64/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/nios2/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sh/libpthread.abilist (GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +	* sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +	(GLIBC_2.30): Likewise.
> +
> +	* nptl/tst-abstime.c (th): Add pthread_rwlock_clockrdlock and
> +	pthread_rwlock_clockwrlock timeout tests to match the existing
> +	pthread_rwlock_timedrdloock and pthread_rwlock_timedwrlock tests.
> +
> +	* nptl/tst-rwlock14.c (do_test): Likewise.
> +
> +	* nptl/tst-rwlock6.c (tf): Accept thread_args structure so that
> +	rwlock, a clockid and function name can be passed to the thread.
> +	(do_test_clock): Rename from do_test. Accept clockid parameter to
> +	specify test clock. Use the magic clockid value of
> +	CLOCK_USE_TIMEDLOCK to indicate that pthread_rwlock_timedrdlock and
> +	pthread_rwlock_timedwrlock should be tested, otherwise pass the
> +	specified clockid to pthread_rwlock_clockrdlock and
> +	pthread_rwlock_clockwrlock. Use xpthread_create and xpthread_join.
> +	(do_test): Call do_test_clock to test each clockid in turn.
> +
> +	* nptl/tst-rwlock7.c: Likewise.
> +
> +	* nptl/tst-rwlock9.c (writer_thread, reader_thread): Accept
> +	thread_args structure so that the (now int) thread number, the
> +	clockid and the function name can be passed to the thread.
> +	(do_test_clock): Renamed from do_test. Pass the necessary
> +	thread_args when creating the reader and writer threads. Use
> +	xpthread_create and xpthread_join.
> +	(do_test): Call do_test_clock to test each clockid in turn.
> +
> +	* manual/threads.texi: Add documentation for
> +	pthread_rwlock_clockrdlock and pthread_rwlock_clockwrclock.
> +
> +2019-05-27  Mike Crowe  <mac@mcrowe.com>
> +
>  	nptl: pthread_rwlock: Move timeout validation into _full functions
>  
>  	* nptl/pthread_rwlock_common.c (__pthread_rwlock_rdlock_full):
> diff --git a/manual/threads.texi b/manual/threads.texi
> index 91462f5..83b8bb6 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -699,6 +699,34 @@ specified or defaulted when @code{pthread_cond_init} was called. Currently,
>  @code{CLOCK_REALTIME}.
>  @end deftypefun
>  
> +@comment pthread.h
> +@comment POSIX-proposed
> +@deftypefun int pthread_rwlock_clockrdlock (pthread_rwlock_t *@var{rwlock},
> +				       clockid_t @var{clockid},
> +				       const struct timespec *@var{abstime})
> +
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +Behaves like @code{pthread_rwlock_timedrdlock} except the time
> +@var{abstime} is measured against the clock specified by @var{clockid}
> +rather than @code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
> +@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}, otherwise @code{EINVAL} is
> +returned.
> +@end deftypefun
> +
> +@comment pthread.h
> +@comment POSIX-proposed
> +@deftypefun int pthread_rwlock_clockwrlock (pthread_rwlock_t *@var{rwlock},
> +				       clockid_t @var{clockid},
> +				       const struct timespec *@var{abstime})
> +
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +Behaves like @code{pthread_rwlock_timedwrlock} except the time
> +@var{abstime} is measured against the clock specified by @var{clockid}
> +rather than @code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
> +@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}, otherwise @code{EINVAL} is
> +returned.
> +@end deftypefun
> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy

Ok.

> diff --git a/nptl/Makefile b/nptl/Makefile
> index 70a2139..d86513a 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -76,7 +76,9 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \
>  		      pthread_mutexattr_gettype pthread_mutexattr_settype \
>  		      pthread_rwlock_init pthread_rwlock_destroy \
>  		      pthread_rwlock_rdlock pthread_rwlock_timedrdlock \
> +		      pthread_rwlock_clockrdlock \
>  		      pthread_rwlock_wrlock pthread_rwlock_timedwrlock \
> +		      pthread_rwlock_clockwrlock \
>  		      pthread_rwlock_tryrdlock pthread_rwlock_trywrlock \
>  		      pthread_rwlock_unlock \
>  		      pthread_rwlockattr_init pthread_rwlockattr_destroy \

Ok.

> diff --git a/nptl/Versions b/nptl/Versions
> index 8c094d0..ce79959 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -279,6 +279,7 @@ libpthread {
>  
>    GLIBC_2.30 {
>      sem_clockwait; pthread_cond_clockwait;
> +    pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
>    }
>  
>    GLIBC_PRIVATE {

Ok.

> diff --git a/nptl/pthread_rwlock_clockrdlock.c b/nptl/pthread_rwlock_clockrdlock.c
> new file mode 100644
> index 0000000..3c252f5
> --- /dev/null
> +++ b/nptl/pthread_rwlock_clockrdlock.c
> @@ -0,0 +1,29 @@
> +/* Implement pthread_rwlock_clockrdlock.
> +
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include "pthread_rwlock_common.c"
> +
> +/* See pthread_rwlock_common.c.  */
> +int
> +pthread_rwlock_clockrdlock (pthread_rwlock_t *rwlock,
> +    clockid_t clockid,
> +    const struct timespec *abstime)
> +{
> +  return __pthread_rwlock_rdlock_full (rwlock, clockid, abstime);
> +}

Ok.

> diff --git a/nptl/pthread_rwlock_clockwrlock.c b/nptl/pthread_rwlock_clockwrlock.c
> new file mode 100644
> index 0000000..38ba693
> --- /dev/null
> +++ b/nptl/pthread_rwlock_clockwrlock.c
> @@ -0,0 +1,29 @@
> +/* Implement pthread_rwlock_clockwrlock.
> +
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include "pthread_rwlock_common.c"
> +
> +/* See pthread_rwlock_common.c.  */
> +int
> +pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
> +    clockid_t clockid,
> +    const struct timespec *abstime)
> +{
> +  return __pthread_rwlock_wrlock_full (rwlock, clockid, abstime);
> +}

Ok.

As a side note, the '__pthread_rwlock_wrlock_full' implementation is currently
included on 6 implementations (pthread_rwlock_timedrdlock.c, 
pthread_rwlock_wrlock.c, pthread_rwlock_rdlock.c, pthread_rwlock_tryrdlock.c,
pthread_rwlock_unlock.c, and pthread_rwlock_timedwrlock.c).  I wonder if it
would be better to factored it out to be an internal symbol instead.

It would incur in a slight better code size, but we will need to check how
it changes the performance. I would not expect much, since it would be tail
call to an internal symbol.

> diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
> index 120b880..50a366e 100644
> --- a/nptl/pthread_rwlock_common.c
> +++ b/nptl/pthread_rwlock_common.c
> @@ -278,17 +278,19 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock)
>  
>  static __always_inline int
>  __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
> +    clockid_t clockid,
>      const struct timespec *abstime)
>  {
>    unsigned int r;
>  
> -  /* Make sure any passed in timeout value is valid.  Note that the previous
> -     implementation assumed that this check *must* not be performed if there
> -     would in fact be no blocking; however, POSIX only requires that "the
> -     validity of the abstime parameter need not be checked if the lock can be
> -     immediately acquired" (i.e., we need not but may check it).  */
> -  if (abstime
> -      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
> +  /* Make sure any passed in clockid and timeout value are valid. Note
> +     that the previous implementation assumed that this check *must*
> +     not be performed if there would in fact be no blocking; however,
> +     POSIX only requires that "the validity of the abstime parameter
> +     need not be checked if the lock can be immediately acquired"
> +     (i.e., we need not but may check it). */
> +  if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
> +      || abstime->tv_nsec >= 1000000000
>        || abstime->tv_nsec < 0))
>      return EINVAL;

The futex_abstimed_wait already check for abstime and if its tv_sec < 0.  Would 
it be better to move the clock validity when it would be really used?

>  
> @@ -329,7 +331,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
>  		{
>  		  int private = __pthread_rwlock_get_private (rwlock);
>  		  int err = futex_abstimed_wait (&rwlock->__data.__readers,
> -						 r, CLOCK_REALTIME, abstime, private);
> +						 r, clockid, abstime, private);
>  		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
>  		     return because we don't need to clean up anything.  */
>  		  if (err == ETIMEDOUT)
> @@ -457,7 +459,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
>  	    continue;
>  	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
>  					 1 | PTHREAD_RWLOCK_FUTEX_USED,
> -					 CLOCK_REALTIME, abstime, private);
> +					 clockid, abstime, private);
>  	  if (err == ETIMEDOUT)
>  	    {
>  	      /* If we timed out, we need to unregister.  If no read phase

Ok.

> @@ -584,15 +586,17 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
>  
>  static __always_inline int
>  __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
> +    clockid_t clockid,
>      const struct timespec *abstime)
>  {
> -  /* Make sure any passed in timeout value is valid.  Note that the previous
> -     implementation assumed that this check *must* not be performed if there
> -     would in fact be no blocking; however, POSIX only requires that "the
> -     validity of the abstime parameter need not be checked if the lock can be
> -     immediately acquired" (i.e., we need not but may check it).  */
> -  if (abstime
> -      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
> +  /* Make sure any passed in clockid and timeout value are valid. Note
> +     that the previous implementation assumed that this check *must*
> +     not be performed if there would in fact be no blocking; however,
> +     POSIX only requires that "the validity of the abstime parameter
> +     need not be checked if the lock can be immediately acquired"
> +     (i.e., we need not but may check it). */
> +  if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
> +      || abstime->tv_nsec >= 1000000000
>        || abstime->tv_nsec < 0))
>      return EINVAL;

As before.

>  
> @@ -727,7 +731,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
>  	  may_share_futex_used_flag = true;
>  	  int err = futex_abstimed_wait (&rwlock->__data.__writers_futex,
>  					 1 | PTHREAD_RWLOCK_FUTEX_USED,
> -					 CLOCK_REALTIME, abstime, private);
> +					 clockid, abstime, private);
>  	  if (err == ETIMEDOUT)
>  	    {
>  	      if (prefer_writer)
> @@ -826,7 +830,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
>  	    continue;
>  	  int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
>  					 PTHREAD_RWLOCK_FUTEX_USED,
> -					 CLOCK_REALTIME, abstime, private);
> +					 clockid, abstime, private);
>  	  if (err == ETIMEDOUT)
>  	    {
>  	      if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)

Ok.

> diff --git a/nptl/pthread_rwlock_rdlock.c b/nptl/pthread_rwlock_rdlock.c
> index 5fdc89e..387c824 100644
> --- a/nptl/pthread_rwlock_rdlock.c
> +++ b/nptl/pthread_rwlock_rdlock.c
> @@ -24,7 +24,7 @@ __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
>  {
>    LIBC_PROBE (rdlock_entry, 1, rwlock);
>  
> -  int result = __pthread_rwlock_rdlock_full (rwlock, NULL);
> +  int result = __pthread_rwlock_rdlock_full (rwlock, CLOCK_REALTIME, NULL);
>    LIBC_PROBE (rdlock_acquire_read, 1, rwlock);
>    return result;
>  }

Ok.

> diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c
> index 84c1983..8f8e680 100644
> --- a/nptl/pthread_rwlock_timedrdlock.c
> +++ b/nptl/pthread_rwlock_timedrdlock.c
> @@ -23,5 +23,5 @@ int
>  pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
>      const struct timespec *abstime)
>  {
> -  return __pthread_rwlock_rdlock_full (rwlock, abstime);
> +  return __pthread_rwlock_rdlock_full (rwlock, CLOCK_REALTIME, abstime);
>  }

Ok.

> diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
> index f0b745d..a5616de 100644
> --- a/nptl/pthread_rwlock_timedwrlock.c
> +++ b/nptl/pthread_rwlock_timedwrlock.c
> @@ -23,5 +23,5 @@ int
>  pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
>      const struct timespec *abstime)
>  {
> -  return __pthread_rwlock_wrlock_full (rwlock, abstime);
> +  return __pthread_rwlock_wrlock_full (rwlock, CLOCK_REALTIME, abstime);
>  }

Ok.

> diff --git a/nptl/pthread_rwlock_wrlock.c b/nptl/pthread_rwlock_wrlock.c
> index 194a14c..da246d8 100644
> --- a/nptl/pthread_rwlock_wrlock.c
> +++ b/nptl/pthread_rwlock_wrlock.c
> @@ -24,7 +24,7 @@ __pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
>  {
>    LIBC_PROBE (wrlock_entry, 1, rwlock);
>  
> -  int result = __pthread_rwlock_wrlock_full (rwlock, NULL);
> +  int result = __pthread_rwlock_wrlock_full (rwlock, CLOCK_REALTIME, NULL);
>    LIBC_PROBE (wrlock_acquire_write, 1, rwlock);
>    return result;
>  }

Ok.

> diff --git a/nptl/tst-abstime.c b/nptl/tst-abstime.c
> index 56fb8a5..c5040c5 100644
> --- a/nptl/tst-abstime.c
> +++ b/nptl/tst-abstime.c
> @@ -38,6 +38,14 @@ th (void *arg)
>    TEST_COMPARE (pthread_mutex_timedlock (&m1, &t), ETIMEDOUT);
>    TEST_COMPARE (pthread_rwlock_timedrdlock (&rw1, &t), ETIMEDOUT);
>    TEST_COMPARE (pthread_rwlock_timedwrlock (&rw2, &t), ETIMEDOUT);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&rw1, CLOCK_REALTIME, &t),
> +                ETIMEDOUT);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&rw2, CLOCK_REALTIME, &t),
> +                ETIMEDOUT);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&rw1, CLOCK_MONOTONIC, &t),
> +                ETIMEDOUT);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&rw2, CLOCK_MONOTONIC, &t),
> +                ETIMEDOUT);
>    return NULL;
>  }
>  

Ok.

> diff --git a/nptl/tst-rwlock14.c b/nptl/tst-rwlock14.c
> index af176b6..f4e1422 100644
> --- a/nptl/tst-rwlock14.c
> +++ b/nptl/tst-rwlock14.c
> @@ -64,19 +64,31 @@ do_test (void)
>    ts.tv_nsec = -1;
>  
>    TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
>    TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
>  
>    ts.tv_nsec = 1000000000;
>  
>    TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
>    TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
>  
>    ts.tv_nsec = (__typeof (ts.tv_nsec)) 0x100001000LL;
>    if ((__typeof (ts.tv_nsec)) 0x100001000LL != 0x100001000LL)
>      ts.tv_nsec = 2000000000;
>  
>    TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_REALTIME, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockrdlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
>    TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_REALTIME, &ts), EINVAL);
> +  TEST_COMPARE (pthread_rwlock_clockwrlock (&r, CLOCK_MONOTONIC, &ts), EINVAL);
>  
>    return 0;
>  }

Ok.

> diff --git a/nptl/tst-rwlock6.c b/nptl/tst-rwlock6.c
> index 5e73f50..d6020bf 100644
> --- a/nptl/tst-rwlock6.c
> +++ b/nptl/tst-rwlock6.c
> @@ -28,6 +28,11 @@
>  #include <support/xtime.h>
>  
>  
> +/* A bogus clock value that tells run_test to use
> +   pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock rather
> +   than pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. */
> +#define CLOCK_USE_TIMEDLOCK (-1)
> +
>  static int kind[] =
>    {
>      PTHREAD_RWLOCK_PREFER_READER_NP,
> @@ -35,43 +40,63 @@ static int kind[] =
>      PTHREAD_RWLOCK_PREFER_WRITER_NP,
>    };
>  
> +struct thread_args
> +{
> +  pthread_rwlock_t *rwlock;
> +  clockid_t clockid;
> +  const char *fnname;
> +};
>  
>  static void *
>  tf (void *arg)
>  {
> -  pthread_rwlock_t *r = arg;
> +  struct thread_args *args = arg;
> +  pthread_rwlock_t *r = args->rwlock;
> +  const clockid_t clockid = args->clockid;
> +  const clockid_t clockid_for_get =
> +    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
> +  const char *fnname = args->fnname;
>  
>    /* Timeout: 0.3 secs.  */
>    struct timespec ts_start;
> -  xclock_gettime (CLOCK_REALTIME, &ts_start);
> +  xclock_gettime (clockid_for_get, &ts_start);
>  
>    struct timespec ts_timeout = timespec_add (ts_start,
>                                               make_timespec (0, 300000000));
>  
> -  puts ("child calling timedrdlock");
> +  printf ("child calling %srdlock\n", fnname);

I think for debug logging it is better to enable only if test_verbose
(support/support_test_main.c:197) is set.

>  
> -  TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), ETIMEDOUT);
> +  if (clockid == CLOCK_USE_TIMEDLOCK)
> +    TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), ETIMEDOUT);
> +  else
> +    TEST_COMPARE (pthread_rwlock_clockrdlock (r, clockid, &ts_timeout),
> +                  ETIMEDOUT);
>  
> -  puts ("1st child timedrdlock done");
> +  printf ("1st child %srdlock done\n", fnname);

Ditto.

>  
>    TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts_timeout);
>  
> -  xclock_gettime (CLOCK_REALTIME, &ts_timeout);
> +  xclock_gettime (clockid_for_get, &ts_timeout);
>    ts_timeout.tv_sec += 10;
>    /* Note that the following operation makes ts invalid.  */
>    ts_timeout.tv_nsec += 1000000000;
>  
> -  TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), EINVAL);
> +  if (clockid == CLOCK_USE_TIMEDLOCK)
> +    TEST_COMPARE (pthread_rwlock_timedrdlock (r, &ts_timeout), EINVAL);
> +  else
> +    TEST_COMPARE (pthread_rwlock_clockrdlock (r, clockid, &ts_timeout), EINVAL);
>  
> -  puts ("2nd child timedrdlock done");
> +  printf ("2nd child %srdlock done\n", fnname);
>  
>    return NULL;
>  }
>  

Ok.

>  
>  static int
> -do_test (void)
> +do_test_clock (clockid_t clockid, const char *fnname)
>  {
> +  const clockid_t clockid_for_get =
> +    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
>    size_t cnt;
>    for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
>      {
> @@ -91,39 +116,46 @@ do_test (void)
>          FAIL_EXIT1 ("round %Zu: rwlockattr_destroy failed\n", cnt);
>  
>        struct timespec ts;
> -      xclock_gettime (CLOCK_REALTIME, &ts);
> +      xclock_gettime (clockid_for_get, &ts);
>        ++ts.tv_sec;
>  
>        /* Get a write lock.  */
> -      int e = pthread_rwlock_timedwrlock (&r, &ts);
> +      int e = (clockid == CLOCK_USE_TIMEDLOCK)
> +	? pthread_rwlock_timedwrlock (&r, &ts)
> +	: pthread_rwlock_clockwrlock (&r, clockid, &ts);
>        if (e != 0)
> -        FAIL_EXIT1 ("round %Zu: rwlock_timedwrlock failed (%d)\n", cnt, e);
> +        FAIL_EXIT1 ("round %Zu: %swrlock failed (%d)\n",
> +                    cnt, fnname, e);
>  
> -      puts ("1st timedwrlock done");
> +      printf ("1st %swrlock done\n", fnname);

Ditto.

>  
> -      xclock_gettime (CLOCK_REALTIME, &ts);
> +      xclock_gettime (clockid_for_get, &ts);
>        ++ts.tv_sec;
> -      TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EDEADLK);
> +      if (clockid == CLOCK_USE_TIMEDLOCK)
> +        TEST_COMPARE (pthread_rwlock_timedrdlock (&r, &ts), EDEADLK);
> +      else
> +        TEST_COMPARE (pthread_rwlock_clockrdlock (&r, clockid, &ts), EDEADLK);
>  
> -      puts ("1st timedrdlock done");
> +      printf ("1st %srdlock done\n", fnname);

Ditto.

>  
> -      xclock_gettime (CLOCK_REALTIME, &ts);
> +      xclock_gettime (clockid_for_get, &ts);
>        ++ts.tv_sec;
> -      TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EDEADLK);
> +      if (clockid == CLOCK_USE_TIMEDLOCK)
> +        TEST_COMPARE (pthread_rwlock_timedwrlock (&r, &ts), EDEADLK);
> +      else
> +        TEST_COMPARE (pthread_rwlock_clockwrlock (&r, clockid, &ts), EDEADLK);
>  
> -      puts ("2nd timedwrlock done");
> +      printf ("2nd %swrlock done\n", fnname);

Ditto.

>  
> -      pthread_t th;
> -      if (pthread_create (&th, NULL, tf, &r) != 0)
> -        FAIL_EXIT1 ("round %Zu: create failed\n", cnt);
> +      struct thread_args args;
> +      args.rwlock = &r;
> +      args.clockid = clockid;
> +      args.fnname = fnname;
> +      pthread_t th = xpthread_create (NULL, tf, &args);
>  
>        puts ("started thread");
>  
> -      void *status;
> -      if (pthread_join (th, &status) != 0)
> -        FAIL_EXIT1 ("round %Zu: join failed\n", cnt);
> -      if (status != NULL)
> -        FAIL_EXIT1 ("failure in round %Zu\n", cnt);
> +      (void) xpthread_join (th);
>  
>        puts ("joined thread");
>  
> @@ -134,4 +166,12 @@ do_test (void)
>    return 0;
>  }
>  
> +static int do_test (void)
> +{
> +  do_test_clock (CLOCK_USE_TIMEDLOCK, "timed");
> +  do_test_clock (CLOCK_REALTIME, "clock(realtime)");
> +  do_test_clock (CLOCK_MONOTONIC, "clock(monotonic)");
> +  return 0;
> +}
> +
>  #include <support/test-driver.c>

Ok.

> diff --git a/nptl/tst-rwlock7.c b/nptl/tst-rwlock7.c
> index df50f0a..1c31572 100644
> --- a/nptl/tst-rwlock7.c
> +++ b/nptl/tst-rwlock7.c
> @@ -28,6 +28,11 @@
>  #include <support/xtime.h>
>  
>  
> +/* A bogus clock value that tells run_test to use
> +   pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock rather
> +   than pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. */
> +#define CLOCK_USE_TIMEDLOCK (-1)
> +
>  static int kind[] =
>    {
>      PTHREAD_RWLOCK_PREFER_READER_NP,
> @@ -35,40 +40,60 @@ static int kind[] =
>      PTHREAD_RWLOCK_PREFER_WRITER_NP,
>    };
>  
> +struct thread_args
> +{
> +  pthread_rwlock_t *rwlock;
> +  clockid_t clockid;
> +  const char *fnname;
> +};
>  
>  static void *
>  tf (void *arg)
>  {
> -  pthread_rwlock_t *r = arg;
> +  struct thread_args *args = arg;
> +  pthread_rwlock_t *r = args->rwlock;
> +  const clockid_t clockid = args->clockid;
> +  const clockid_t clockid_for_get =
> +    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
> +  const char *fnname = args->fnname;
>  
>    /* Timeout: 0.3 secs.  */
>    struct timespec ts_start;
> -  xclock_gettime (CLOCK_REALTIME, &ts_start);
> +  xclock_gettime (clockid_for_get, &ts_start);
>    const struct timespec ts_timeout = timespec_add (ts_start,
>                                                     make_timespec (0, 300000000));
>  
> -  TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_timeout), ETIMEDOUT);
> -  puts ("child: timedwrlock failed with ETIMEDOUT");
> +  if (clockid == CLOCK_USE_TIMEDLOCK)
> +    TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_timeout), ETIMEDOUT);
> +  else
> +    TEST_COMPARE (pthread_rwlock_clockwrlock (r, clockid, &ts_timeout),
> +                  ETIMEDOUT);
> +  printf ("child: %swrlock failed with ETIMEDOUT", fnname);
>  
> -  TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts_timeout);
> +  TEST_TIMESPEC_NOW_OR_AFTER (clockid_for_get, ts_timeout);
>  
>    struct timespec ts_invalid;
> -  xclock_gettime (CLOCK_REALTIME, &ts_invalid);
> +  xclock_gettime (clockid_for_get, &ts_invalid);
>    ts_invalid.tv_sec += 10;
>    /* Note that the following operation makes ts invalid.  */
>    ts_invalid.tv_nsec += 1000000000;
>  
> -  TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_invalid), EINVAL);
> +  if (clockid == CLOCK_USE_TIMEDLOCK)
> +    TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_invalid), EINVAL);
> +  else
> +    TEST_COMPARE (pthread_rwlock_clockwrlock (r, clockid, &ts_invalid), EINVAL);
>  
> -  puts ("child: timedwrlock failed with EINVAL");
> +  printf ("child: %swrlock failed with EINVAL", fnname);
>  
>    return NULL;
>  }
>  
>  

Ok.

>  static int
> -do_test (void)
> +do_test_clock (clockid_t clockid, const char *fnname)
>  {
> +  const clockid_t clockid_for_get =
> +    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
>    size_t cnt;
>    for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
>      {
> @@ -88,23 +113,27 @@ do_test (void)
>          FAIL_EXIT1 ("round %Zu: rwlockattr_destroy failed\n", cnt);
>  
>        struct timespec ts;
> -      xclock_gettime (CLOCK_REALTIME, &ts);
> +      xclock_gettime (clockid_for_get, &ts);
>  
>        ++ts.tv_sec;
>  
>        /* Get a read lock.  */
> -      if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
> -        FAIL_EXIT1 ("round %Zu: rwlock_timedrdlock failed\n", cnt);
> -
> -      printf ("%zu: got timedrdlock\n", cnt);
> -
> -      pthread_t th;
> -      if (pthread_create (&th, NULL, tf, &r) != 0)
> -        FAIL_EXIT1 ("round %Zu: create failed\n", cnt);
> -
> -      void *status;
> -      if (pthread_join (th, &status) != 0)
> -        FAIL_EXIT1 ("round %Zu: join failed\n", cnt);
> +      if (clockid == CLOCK_USE_TIMEDLOCK) {
> +        if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
> +          FAIL_EXIT1 ("round %Zu: rwlock_timedrdlock failed\n", cnt);
> +      } else {
> +        if (pthread_rwlock_clockrdlock (&r, clockid, &ts) != 0)
> +          FAIL_EXIT1 ("round %Zu: rwlock_%srdlock failed\n", cnt, fnname);
> +      }
> +
> +      printf ("%zu: got %srdlock\n", cnt, fnname);

Ditto.

> +
> +      struct thread_args args;
> +      args.rwlock = &r;
> +      args.clockid = clockid;
> +      args.fnname = fnname;
> +      pthread_t th = xpthread_create(NULL, tf, &args);
> +      void *status = xpthread_join (th);
>        if (status != NULL)
>          FAIL_EXIT1 ("failure in round %Zu\n", cnt);

Ok.

>  
> @@ -115,4 +144,14 @@ do_test (void)
>    return 0;
>  }
>  
> +static int
> +do_test (void)
> +{
> +  do_test_clock (CLOCK_USE_TIMEDLOCK, "timed");
> +  do_test_clock (CLOCK_MONOTONIC, "clock(monotonic)");
> +  do_test_clock (CLOCK_REALTIME, "clock(realtime)");
> +
> +  return 0;
> +}
> +
>  #include <support/test-driver.c>

Ok.

> diff --git a/nptl/tst-rwlock9.c b/nptl/tst-rwlock9.c
> index e772247..e975554 100644
> --- a/nptl/tst-rwlock9.c
> +++ b/nptl/tst-rwlock9.c
> @@ -26,6 +26,7 @@
>  #include <sys/time.h>
>  #include <support/check.h>
>  #include <support/timespec.h>
> +#include <support/xthread.h>
>  
>  
>  #define NWRITERS 15
> @@ -40,12 +41,30 @@ static const struct timespec delay = { 0, 1000000 };
>  # define KIND PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
>  #endif
>  
> +/* A bogus clock value that tells the tests to use
> +   pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock rather
> +   than pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock. */
> +#define CLOCK_USE_TIMEDLOCK (-1)
> +
>  static pthread_rwlock_t lock;
>  
> +struct thread_args
> +{
> +  int nr;
> +  clockid_t clockid;
> +  const char *fnname;
> +};
>  
>  static void *
> -writer_thread (void *nr)
> +writer_thread (void *arg)
>  {
> +  struct thread_args *args = arg;
> +  const int nr = args->nr;
> +  const clockid_t clockid = args->clockid;
> +  const clockid_t clockid_for_get =
> +    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
> +  const char *fnname = args->fnname;
> +
>    struct timespec ts;
>    int n;
>  
> @@ -54,27 +73,29 @@ writer_thread (void *nr)
>        int e;
>        do
>  	{
> -	  xclock_gettime (CLOCK_REALTIME, &ts);
> +	  xclock_gettime (clockid_for_get, &ts);
>  
>            ts = timespec_add (ts, timeout);
>            ts = timespec_add (ts, timeout);
>  
> -	  printf ("writer thread %ld tries again\n", (long int) nr);
> +	  printf ("writer thread %d tries again\n", nr);
>  
> -	  e = pthread_rwlock_timedwrlock (&lock, &ts);
> +	  e = (clockid == CLOCK_USE_TIMEDLOCK)
> +	    ? pthread_rwlock_timedwrlock (&lock, &ts)
> +	    : pthread_rwlock_clockwrlock (&lock, clockid, &ts);
>  	  if (e != 0 && e != ETIMEDOUT)
> -            FAIL_EXIT1 ("timedwrlock failed");
> +            FAIL_EXIT1 ("%swrlock failed", fnname);
>  	}
>        while (e == ETIMEDOUT);
>  
> -      printf ("writer thread %ld succeeded\n", (long int) nr);
> +      printf ("writer thread %d succeeded\n", nr);
>  
>        nanosleep (&delay, NULL);
>  
>        if (pthread_rwlock_unlock (&lock) != 0)
>          FAIL_EXIT1 ("unlock for writer failed");
>  
> -      printf ("writer thread %ld released\n", (long int) nr);
> +      printf ("writer thread %d released\n", nr);
>      }
>  
>    return NULL;

Ok.

> @@ -82,8 +103,15 @@ writer_thread (void *nr)
>  
>  
>  static void *
> -reader_thread (void *nr)
> +reader_thread (void *arg)
>  {
> +  struct thread_args *args = arg;
> +  const int nr = args->nr;
> +  const clockid_t clockid = args->clockid;
> +  const clockid_t clockid_for_get =
> +    (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
> +  const char *fnname = args->fnname;
> +
>    struct timespec ts;
>    int n;
>  
> @@ -92,26 +120,29 @@ reader_thread (void *nr)
>        int e;
>        do
>  	{
> -	  xclock_gettime (CLOCK_REALTIME, &ts);
> +	  xclock_gettime (clockid_for_get, &ts);
>  
>            ts = timespec_add (ts, timeout);
>  
> -	  printf ("reader thread %ld tries again\n", (long int) nr);
> +	  printf ("reader thread %d tries again\n", nr);
>  
> -	  e = pthread_rwlock_timedrdlock (&lock, &ts);
> +	  if (clockid == CLOCK_USE_TIMEDLOCK)
> +	    e = pthread_rwlock_timedrdlock (&lock, &ts);
> +          else
> +	    e = pthread_rwlock_clockrdlock (&lock, clockid, &ts);
>  	  if (e != 0 && e != ETIMEDOUT)
> -            FAIL_EXIT1 ("timedrdlock failed");
> +            FAIL_EXIT1 ("%srdlock failed", fnname);
>  	}
>        while (e == ETIMEDOUT);
>  
> -      printf ("reader thread %ld succeeded\n", (long int) nr);
> +      printf ("reader thread %d succeeded\n", nr);
>  
>        nanosleep (&delay, NULL);
>  
>        if (pthread_rwlock_unlock (&lock) != 0)
>          FAIL_EXIT1 ("unlock for reader failed");
>  
> -      printf ("reader thread %ld released\n", (long int) nr);
> +      printf ("reader thread %d released\n", nr);
>      }
>  
>    return NULL;

Ok.

> @@ -119,12 +150,11 @@ reader_thread (void *nr)
>  
>  
>  static int
> -do_test (void)
> +do_test_clock (clockid_t clockid, const char *fnname)
>  {
>    pthread_t thwr[NWRITERS];
>    pthread_t thrd[NREADERS];
>    int n;
> -  void *res;
>    pthread_rwlockattr_t a;
>  
>    if (pthread_rwlockattr_init (&a) != 0)
> @@ -142,23 +172,37 @@ do_test (void)
>    /* Make sure we see all message, even those on stdout.  */
>    setvbuf (stdout, NULL, _IONBF, 0);
>  
> -  for (n = 0; n < NWRITERS; ++n)
> -    if (pthread_create (&thwr[n], NULL, writer_thread,
> -			(void *) (long int) n) != 0)
> -      FAIL_EXIT1 ("writer create failed");
> -
> -  for (n = 0; n < NREADERS; ++n)
> -    if (pthread_create (&thrd[n], NULL, reader_thread,
> -			(void *) (long int) n) != 0)
> -      FAIL_EXIT1 ("reader create failed");
> +  struct thread_args wargs[NWRITERS];
> +  for (n = 0; n < NWRITERS; ++n) {
> +    wargs[n].nr = n;
> +    wargs[n].clockid = clockid;
> +    wargs[n].fnname = fnname;
> +    thwr[n] = xpthread_create (NULL, writer_thread, &wargs[n]);
> +  }
> +
> +  struct thread_args rargs[NREADERS];
> +  for (n = 0; n < NREADERS; ++n) {
> +    rargs[n].nr = n;
> +    rargs[n].clockid = clockid;
> +    rargs[n].fnname = fnname;
> +    thrd[n] = xpthread_create (NULL, reader_thread, &rargs[n]);
> +  }
>  
>    /* Wait for all the threads.  */
>    for (n = 0; n < NWRITERS; ++n)
> -    if (pthread_join (thwr[n], &res) != 0)
> -      FAIL_EXIT1 ("writer join failed");
> +    xpthread_join (thwr[n]);
>    for (n = 0; n < NREADERS; ++n)
> -    if (pthread_join (thrd[n], &res) != 0)
> -      FAIL_EXIT1 ("reader join failed");
> +    xpthread_join (thrd[n]);
> +
> +  return 0;
> +}
> +

Ok.

> +static int
> +do_test (void)
> +{
> +  do_test_clock (CLOCK_USE_TIMEDLOCK, "timed");
> +  do_test_clock (CLOCK_REALTIME, "clock(realtime)");
> +  do_test_clock (CLOCK_MONOTONIC, "clock(monotonic)");
>  
>    return 0;
>  }

Ok.

> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
> index f000b1e..e78003e 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -909,6 +909,13 @@ extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
>  				       __abstime) __THROWNL __nonnull ((1, 2));
>  # endif
>  
> +# ifdef __USE_GNU
> +extern int pthread_rwlock_clockrdlock (pthread_rwlock_t *__restrict __rwlock,
> +				       clockid_t __clockid,
> +				       const struct timespec *__restrict
> +				       __abstime) __THROWNL __nonnull ((1, 3));
> +# endif
> +
>  /* Acquire write lock for RWLOCK.  */
>  extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
>       __THROWNL __nonnull ((1));

Ok.

> @@ -924,6 +931,13 @@ extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
>  				       __abstime) __THROWNL __nonnull ((1, 2));
>  # endif
>  
> +# ifdef __USE_GNU
> +extern int pthread_rwlock_clockwrlock (pthread_rwlock_t *__restrict __rwlock,
> +				       clockid_t __clockid,
> +				       const struct timespec *__restrict
> +				       __abstime) __THROWNL __nonnull ((1, 3));
> +# endif
> +
>  /* Unlock RWLOCK.  */
>  extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
>       __THROWNL __nonnull ((1));

Ok.

> diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> index 5af4b8a..9f65baf 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist
> @@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> index a00adfb..0709855 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist
> @@ -228,6 +228,8 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.3.2 pthread_cond_broadcast F
>  GLIBC_2.3.2 pthread_cond_destroy F
> diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> index 4aeee7b..a2be572 100644
> --- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist
> @@ -28,6 +28,8 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 _IO_flockfile F
>  GLIBC_2.4 _IO_ftrylockfile F
> diff --git a/sysdeps/unix/sysv/linux/csky/libpthread.abilist b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> index 2c08b76..c3a1834 100644
> --- a/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libpthread.abilist
> @@ -234,4 +234,6 @@ GLIBC_2.29 wait F
>  GLIBC_2.29 waitpid F
>  GLIBC_2.29 write F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> index dc0d4ad..2a00ebc 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist
> @@ -246,6 +246,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> index 1830e40..4479947 100644
> --- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist
> @@ -254,6 +254,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> index 0811d73..40a1faf 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist
> @@ -248,6 +248,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> index 4aeee7b..a2be572 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist
> @@ -28,6 +28,8 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  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 1830e40..4479947 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist
> @@ -254,6 +254,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> index f2be6b4..254b708 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist
> @@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> index 41527fe..29ffdd1 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist
> @@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> index 41527fe..29ffdd1 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist
> @@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> index 04fc3a6..3fae328 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libpthread.abilist
> @@ -242,4 +242,6 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> index ebdab1a..a90010d 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist
> @@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.3.4 siglongjmp F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> index 8a1fb34..339eab8 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libpthread.abilist
> @@ -247,6 +247,8 @@ GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.3.4 siglongjmp F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> index 5af4b8a..9f65baf 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libpthread.abilist
> @@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> index a1c8c2e..83082fb 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libpthread.abilist
> @@ -236,4 +236,6 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> index 0feb3cf..54e937b 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist
> @@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> index cc4f160..87f978b 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist
> @@ -248,6 +248,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> index dc0d4ad..2a00ebc 100644
> --- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist
> @@ -246,6 +246,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> index ed0574a..bc29a66 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist
> @@ -256,6 +256,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> index 0811d73..40a1faf 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist
> @@ -248,6 +248,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> index aaa1c3b..70f04cc 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
> @@ -246,6 +246,8 @@ GLIBC_2.3.4 pthread_getaffinity_np F
>  GLIBC_2.3.4 pthread_setaffinity_np F
>  GLIBC_2.3.4 pthread_setschedprio F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
>  GLIBC_2.4 pthread_mutex_consistent_np F
>  GLIBC_2.4 pthread_mutex_getprioceiling F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> index 5d02b03..92cd2f4 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist
> @@ -244,4 +244,6 @@ GLIBC_2.28 tss_delete F
>  GLIBC_2.28 tss_get F
>  GLIBC_2.28 tss_set F
>  GLIBC_2.30 pthread_cond_clockwait F
> +GLIBC_2.30 pthread_rwlock_clockrdlock F
> +GLIBC_2.30 pthread_rwlock_clockwrlock F
>  GLIBC_2.30 sem_clockwait F
> 

Ok (all affected ABI seems to be taking in consideration).

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

* Re: [PATCH v3 6/6] Update NEWS for new _clockwait functions
  2019-05-27 20:03 ` [PATCH v3 6/6] Update NEWS for new _clockwait functions Mike Crowe
@ 2019-06-07 14:09   ` Adhemerval Zanella
  0 siblings, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-07 14:09 UTC (permalink / raw
  To: libc-alpha



On 27/05/2019 17:03, Mike Crowe wrote:
> * NEWS: Mention new pthread_cond_clockwait,
> 	pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock and
> 	sem_clockwait functions.
> ---
>  ChangeLog | 6 ++++++
>  NEWS      | 6 ++++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/ChangeLog b/ChangeLog
> index 66589f8..beba62b 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,5 +1,11 @@
>  2019-05-27  Mike Crowe  <mac@mcrowe.com>
>  
> +	* NEWS: Mention new pthread_cond_clockwait,
> +	pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock and
> +	sem_clockwait functions.
> +
> +2019-05-27  Mike Crowe  <mac@mcrowe.com>
> +
>  	nptl: Add POSIX-proposed pthread_rwlock_clockrdlock &
>  	pthread_rwlock_clockwrlock which behave like
>  	pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock
> diff --git a/NEWS b/NEWS
> index c885b96..76b1587 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -34,6 +34,12 @@ Major new features:
>    pointer subtraction within the allocated object, where results might
>    overflow the ptrdiff_t type.
>  
> +* Add new POSIX-proposed pthread_cond_clockwait, pthread_rwlock_clockrdlock,
> +  pthread_rwlock_clockwrlock and sem_clockwait functions. These behave
> +  similarly to their "timed" equivalents, but also accept a clockid_t
> +  parameter to determine which clock their timeout should be measured
> +  against.
> +

I think it would be good to add the idea is to currently support CLOCK_MONOTONIC
as a different clock source.

>  Deprecated and removed features, and other changes affecting compatibility:
>  
>  * The functions clock_gettime, clock_getres, clock_settime,
> 

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

* Re: [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions
  2019-06-06 19:18   ` Adhemerval Zanella
@ 2019-06-07 17:01     ` Mike Crowe
  2019-06-12 20:56       ` Adhemerval Zanella
  0 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-06-07 17:01 UTC (permalink / raw
  To: libc-alpha

On Thursday 06 June 2019 at 16:18:05 -0300, Adhemerval Zanella wrote:
> 
> 
> On 27/05/2019 17:03, Mike Crowe wrote:
> > As recommended by the comments in the implementations of
> > pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock, let's move the
> > timeout validity checks into the corresponding pthread_rwlock_rdlock_full
> > and pthread_rwlock_wrlock_full functions. Since these functions may be
> > called with abstime == NULL, an extra check for that is necessary too.
> 
> Is this really a gain here? It just moves some code around and add
> an extra non required check. Wouldn't be better just to remove the
> comments?

It looks like the comment was added by Torvald Riegel in
cc25c8b4c1196a8c29e9a45b1e096b99a87b7f8c back in 2017.

From what I can tell from the x86_64 disassembly, the compiler throws away the extra check because
these functions are all inline and it knows that abstime will be NULL.

However, I'm perfectly happy not to make this change, but it means that
I'll need to add the same checks to pthread_rwlock_clockwrlock and
pthread_wlock_clockrdlock.

I think that you've suggested consolidating these checks into a single
function in the past, which would make that easier. How about adding
is_valid_timespec or similar? Where would it be declared?

Thanks.

Mike.

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

* Re: [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock
  2019-06-07 14:05   ` Adhemerval Zanella
@ 2019-06-07 17:14     ` Mike Crowe
  2019-06-11 12:19       ` Adhemerval Zanella
  0 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-06-07 17:14 UTC (permalink / raw
  To: libc-alpha

[snip review comments that I will address]

On Friday 07 June 2019 at 11:05:44 -0300, Adhemerval Zanella wrote:
> > diff --git a/nptl/pthread_rwlock_clockwrlock.c b/nptl/pthread_rwlock_clockwrlock.c
> > new file mode 100644
> > index 0000000..38ba693
> > --- /dev/null
> > +++ b/nptl/pthread_rwlock_clockwrlock.c
> > @@ -0,0 +1,29 @@
> > +/* Implement pthread_rwlock_clockwrlock.
> > +
> > +   Copyright (C) 2019 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <http://www.gnu.org/licenses/>.  */
> > +
> > +#include "pthread_rwlock_common.c"
> > +
> > +/* See pthread_rwlock_common.c.  */
> > +int
> > +pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
> > +    clockid_t clockid,
> > +    const struct timespec *abstime)
> > +{
> > +  return __pthread_rwlock_wrlock_full (rwlock, clockid, abstime);
> > +}
> 
> Ok.
> 
> As a side note, the '__pthread_rwlock_wrlock_full' implementation is currently
> included on 6 implementations (pthread_rwlock_timedrdlock.c, 
> pthread_rwlock_wrlock.c, pthread_rwlock_rdlock.c, pthread_rwlock_tryrdlock.c,
> pthread_rwlock_unlock.c, and pthread_rwlock_timedwrlock.c).  I wonder if it
> would be better to factored it out to be an internal symbol instead.
> 
> It would incur in a slight better code size, but we will need to check how
> it changes the performance. I would not expect much, since it would be tail
> call to an internal symbol.

For x86_64, it looks like pthread_rwlock_timedrdlock is about 700 bytes, so
we could gain approximately 3.5K by doing that.

I'm not sure that I'm knowledgeable enough in benchmarking real-world
scenarios to be able to come up with a test I'd trust, and I can come up
with theoretical arguments in both directions.

> > diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
> > index 120b880..50a366e 100644
> > --- a/nptl/pthread_rwlock_common.c
> > +++ b/nptl/pthread_rwlock_common.c
> > @@ -278,17 +278,19 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock)
> >  
> >  static __always_inline int
> >  __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
> > +    clockid_t clockid,
> >      const struct timespec *abstime)
> >  {
> >    unsigned int r;
> >  
> > -  /* Make sure any passed in timeout value is valid.  Note that the previous
> > -     implementation assumed that this check *must* not be performed if there
> > -     would in fact be no blocking; however, POSIX only requires that "the
> > -     validity of the abstime parameter need not be checked if the lock can be
> > -     immediately acquired" (i.e., we need not but may check it).  */
> > -  if (abstime
> > -      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
> > +  /* Make sure any passed in clockid and timeout value are valid. Note
> > +     that the previous implementation assumed that this check *must*
> > +     not be performed if there would in fact be no blocking; however,
> > +     POSIX only requires that "the validity of the abstime parameter
> > +     need not be checked if the lock can be immediately acquired"
> > +     (i.e., we need not but may check it). */
> > +  if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
> > +      || abstime->tv_nsec >= 1000000000
> >        || abstime->tv_nsec < 0))
> >      return EINVAL;
> 
> The futex_abstimed_wait already check for abstime and if its tv_sec < 0.  Would 
> it be better to move the clock validity when it would be really used?

I think that it's better to consistently return an error if an invalid
clock is supplied, even if it is not necessary to use the timeout. Doing
otherwise risks bugs (in code using glibc) that aren't found until much
later.

Mike.

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

* Re: [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock
  2019-06-07 17:14     ` Mike Crowe
@ 2019-06-11 12:19       ` Adhemerval Zanella
  2019-06-11 12:33         ` Torvald Riegel
  0 siblings, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-11 12:19 UTC (permalink / raw
  To: libc-alpha, Torvald Riegel



On 07/06/2019 14:14, Mike Crowe wrote:
> [snip review comments that I will address]
> 
> On Friday 07 June 2019 at 11:05:44 -0300, Adhemerval Zanella wrote:
>>> diff --git a/nptl/pthread_rwlock_clockwrlock.c b/nptl/pthread_rwlock_clockwrlock.c
>>> new file mode 100644
>>> index 0000000..38ba693
>>> --- /dev/null
>>> +++ b/nptl/pthread_rwlock_clockwrlock.c
>>> @@ -0,0 +1,29 @@
>>> +/* Implement pthread_rwlock_clockwrlock.
>>> +
>>> +   Copyright (C) 2019 Free Software Foundation, Inc.
>>> +   This file is part of the GNU C Library.
>>> +
>>> +   The GNU C Library is free software; you can redistribute it and/or
>>> +   modify it under the terms of the GNU Lesser General Public
>>> +   License as published by the Free Software Foundation; either
>>> +   version 2.1 of the License, or (at your option) any later version.
>>> +
>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
>>> +   Lesser General Public License for more details.
>>> +
>>> +   You should have received a copy of the GNU Lesser General Public
>>> +   License along with the GNU C Library; if not, see
>>> +   <http://www.gnu.org/licenses/>.  */
>>> +
>>> +#include "pthread_rwlock_common.c"
>>> +
>>> +/* See pthread_rwlock_common.c.  */
>>> +int
>>> +pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
>>> +    clockid_t clockid,
>>> +    const struct timespec *abstime)
>>> +{
>>> +  return __pthread_rwlock_wrlock_full (rwlock, clockid, abstime);
>>> +}
>>
>> Ok.
>>
>> As a side note, the '__pthread_rwlock_wrlock_full' implementation is currently
>> included on 6 implementations (pthread_rwlock_timedrdlock.c, 
>> pthread_rwlock_wrlock.c, pthread_rwlock_rdlock.c, pthread_rwlock_tryrdlock.c,
>> pthread_rwlock_unlock.c, and pthread_rwlock_timedwrlock.c).  I wonder if it
>> would be better to factored it out to be an internal symbol instead.
>>
>> It would incur in a slight better code size, but we will need to check how
>> it changes the performance. I would not expect much, since it would be tail
>> call to an internal symbol.
> 
> For x86_64, it looks like pthread_rwlock_timedrdlock is about 700 bytes, so
> we could gain approximately 3.5K by doing that.
> 
> I'm not sure that I'm knowledgeable enough in benchmarking real-world
> scenarios to be able to come up with a test I'd trust, and I can come up
> with theoretical arguments in both directions.

I think 3.5k is noticeable and if performance-wise it does not yield any
drawback I think it would be good refactor. I don't have neither performance
workload to validate this change, but I presume on most architecture it would
be a tail call which would just an extra jump without the need to handle 
potential extra code segments.

I am ccing Torvalds, who rewrote the pthread cond code. Torvalds, do you recall
why you set the code to be inline instead of create an internal common symbol? 
Do you think refactoring to share the code would yield any performance
regressions?

> 
>>> diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
>>> index 120b880..50a366e 100644
>>> --- a/nptl/pthread_rwlock_common.c
>>> +++ b/nptl/pthread_rwlock_common.c
>>> @@ -278,17 +278,19 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock)
>>>  
>>>  static __always_inline int
>>>  __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
>>> +    clockid_t clockid,
>>>      const struct timespec *abstime)
>>>  {
>>>    unsigned int r;
>>>  
>>> -  /* Make sure any passed in timeout value is valid.  Note that the previous
>>> -     implementation assumed that this check *must* not be performed if there
>>> -     would in fact be no blocking; however, POSIX only requires that "the
>>> -     validity of the abstime parameter need not be checked if the lock can be
>>> -     immediately acquired" (i.e., we need not but may check it).  */
>>> -  if (abstime
>>> -      && __glibc_unlikely (abstime->tv_nsec >= 1000000000
>>> +  /* Make sure any passed in clockid and timeout value are valid. Note
>>> +     that the previous implementation assumed that this check *must*
>>> +     not be performed if there would in fact be no blocking; however,
>>> +     POSIX only requires that "the validity of the abstime parameter
>>> +     need not be checked if the lock can be immediately acquired"
>>> +     (i.e., we need not but may check it). */
>>> +  if (abstime && __glibc_unlikely (!futex_abstimed_supported_clockid (clockid)
>>> +      || abstime->tv_nsec >= 1000000000
>>>        || abstime->tv_nsec < 0))
>>>      return EINVAL;
>>
>> The futex_abstimed_wait already check for abstime and if its tv_sec < 0.  Would 
>> it be better to move the clock validity when it would be really used?
> 
> I think that it's better to consistently return an error if an invalid
> clock is supplied, even if it is not necessary to use the timeout. Doing
> otherwise risks bugs (in code using glibc) that aren't found until much
> later.

Right, but I am thinking that if we eventually refactor to make it a common
internal symbol compiler might not be able infer abstime is always null (even
if is called with a NULL value for abstime). I will check again if current
organization with all patchset applied is ok.

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

* Re: [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock
  2019-06-11 12:19       ` Adhemerval Zanella
@ 2019-06-11 12:33         ` Torvald Riegel
  0 siblings, 0 replies; 36+ messages in thread
From: Torvald Riegel @ 2019-06-11 12:33 UTC (permalink / raw
  To: Adhemerval Zanella, libc-alpha

On Tue, 2019-06-11 at 09:19 -0300, Adhemerval Zanella wrote:
> 
> On 07/06/2019 14:14, Mike Crowe wrote:
> > [snip review comments that I will address]
> > 
> > On Friday 07 June 2019 at 11:05:44 -0300, Adhemerval Zanella wrote:
> > > > diff --git a/nptl/pthread_rwlock_clockwrlock.c b/nptl/pthread_rwlock_clockwrlock.c
> > > > new file mode 100644
> > > > index 0000000..38ba693
> > > > --- /dev/null
> > > > +++ b/nptl/pthread_rwlock_clockwrlock.c
> > > > @@ -0,0 +1,29 @@
> > > > +/* Implement pthread_rwlock_clockwrlock.
> > > > +
> > > > +   Copyright (C) 2019 Free Software Foundation, Inc.
> > > > +   This file is part of the GNU C Library.
> > > > +
> > > > +   The GNU C Library is free software; you can redistribute it and/or
> > > > +   modify it under the terms of the GNU Lesser General Public
> > > > +   License as published by the Free Software Foundation; either
> > > > +   version 2.1 of the License, or (at your option) any later version.
> > > > +
> > > > +   The GNU C Library is distributed in the hope that it will be useful,
> > > > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > > > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
> > > > +   Lesser General Public License for more details.
> > > > +
> > > > +   You should have received a copy of the GNU Lesser General Public
> > > > +   License along with the GNU C Library; if not, see
> > > > +   <http://www.gnu.org/licenses/>.  */
> > > > +
> > > > +#include "pthread_rwlock_common.c"
> > > > +
> > > > +/* See pthread_rwlock_common.c.  */
> > > > +int
> > > > +pthread_rwlock_clockwrlock (pthread_rwlock_t *rwlock,
> > > > +    clockid_t clockid,
> > > > +    const struct timespec *abstime)
> > > > +{
> > > > +  return __pthread_rwlock_wrlock_full (rwlock, clockid, abstime);
> > > > +}
> > > 
> > > Ok.
> > > 
> > > As a side note, the '__pthread_rwlock_wrlock_full' implementation is currently
> > > included on 6 implementations (pthread_rwlock_timedrdlock.c, 
> > > pthread_rwlock_wrlock.c, pthread_rwlock_rdlock.c, pthread_rwlock_tryrdlock.c,
> > > pthread_rwlock_unlock.c, and pthread_rwlock_timedwrlock.c).  I wonder if it
> > > would be better to factored it out to be an internal symbol instead.
> > > 
> > > It would incur in a slight better code size, but we will need to check how
> > > it changes the performance. I would not expect much, since it would be tail
> > > call to an internal symbol.
> > 
> > For x86_64, it looks like pthread_rwlock_timedrdlock is about 700 bytes, so
> > we could gain approximately 3.5K by doing that.
> > 
> > I'm not sure that I'm knowledgeable enough in benchmarking real-world
> > scenarios to be able to come up with a test I'd trust, and I can come up
> > with theoretical arguments in both directions.
> 
> I think 3.5k is noticeable and if performance-wise it does not yield any
> drawback I think it would be good refactor. I don't have neither performance
> workload to validate this change, but I presume on most architecture it would
> be a tail call which would just an extra jump without the need to handle 
> potential extra code segments.
> 
> I am ccing Torvalds, who rewrote the pthread cond code. Torvalds, do you recall
> why you set the code to be inline instead of create an internal common symbol?

I wasn't aware that there was that much concern about code size, and I
wanted to give as much optimization opportunity to the compiler as
possible.  There is not that much information (like abstime==NULL) that is
passed in into the full algorithm, so maybe it doesn't matter as much in
the end.

> Do you think refactoring to share the code would yield any performance
> regressions?

Not sure.  It might only be noticable matter on the fast paths, so maybe
check those (eg, single-threaded pthread_rwlock_tryrdlock).


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

* Re: [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls
  2019-06-05 17:52   ` Adhemerval Zanella
  2019-06-06 12:06     ` Adhemerval Zanella
@ 2019-06-12 19:32     ` Adhemerval Zanella
  2019-06-18 11:44       ` Mike Crowe
  1 sibling, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-12 19:32 UTC (permalink / raw
  To: libc-alpha, Mike Crowe



On 05/06/2019 14:52, Adhemerval Zanella wrote:

>> diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
>> index 9a0f29e..7385562 100644
>> --- a/nptl/pthread_cond_wait.c
>> +++ b/nptl/pthread_cond_wait.c
>> @@ -509,35 +509,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>>  		 values despite them being valid.  */
>>  	      if (__glibc_unlikely (abstime->tv_sec < 0))
>>  	        err = ETIMEDOUT;
>> -
>> -	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
>> -		{
>> -		  /* CLOCK_MONOTONIC is requested.  */
>> -		  struct timespec rt;
>> -		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
>> -		    __libc_fatal ("clock_gettime does not support "
>> -				  "CLOCK_MONOTONIC\n");
>> -		  /* Convert the absolute timeout value to a relative
>> -		     timeout.  */
>> -		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
>> -		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
>> -		  if (rt.tv_nsec < 0)
>> -		    {
>> -		      rt.tv_nsec += 1000000000;
>> -		      --rt.tv_sec;
>> -		    }
>> -		  /* Did we already time out?  */
>> -		  if (__glibc_unlikely (rt.tv_sec < 0))
>> -		    err = ETIMEDOUT;
>> -		  else
>> -		    err = futex_reltimed_wait_cancelable
>> -			(cond->__data.__g_signals + g, 0, &rt, private);
>> -		}
>>  	      else
>>  		{
>> -		  /* Use CLOCK_REALTIME.  */
>> +		  const clockid_t clockid =
>> +		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
>> +		    CLOCK_MONOTONIC : CLOCK_REALTIME;
>> +
>>  		  err = futex_abstimed_wait_cancelable
>> -		      (cond->__data.__g_signals + g, 0, abstime, private);
>> +                    (cond->__data.__g_signals + g, 0, clockid, abstime,
>> +                     private);
>>  		}
>>  	    }
> 
> My understanding is we need to convert an absolute timeout to a relative one
> on either futex_abstimed_wait_cancelable or lll_futex_clock_wait_bitset for
> CLOCK_MONOTONIC.

Ok rechecking the patchset, it now uses futex_abstimed_wait_cancelable instead 
of futex_reltimed_wait_cancelable, so my comment indeed does not apply.

However the naming is somewhat confusing because 'abstimed' only applies for 
clockid being CLOCK_MONOTONIC. I think we should just name the new interfaces 
as futex_timed_wait{_cancelable}.  

As a side node maybe we could simplify the futex_{abs,rel}timed_wait to call 
futex_timed_wait with expected clock on Linux implementation.

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

* Re: [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait
  2019-06-06 12:53   ` Adhemerval Zanella
@ 2019-06-12 20:22     ` Adhemerval Zanella
  2019-06-18 13:53     ` Mike Crowe
  1 sibling, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-12 20:22 UTC (permalink / raw
  To: libc-alpha, Mike Crowe



On 06/06/2019 09:53, Adhemerval Zanella wrote:
> 
> 
> On 27/05/2019 17:03, Mike Crowe wrote:
>> Add:
>>
>>  int pthread_cond_clockwait (pthread_cond_t *cond,
>>                              pthread_mutex_t *mutex,
>>                              clockid_t clockid,
>>                              const struct timespec *abstime)
>>
>> which behaves just like pthread_cond_timedwait except it always measures
>> abstime against the supplied clockid. Currently supports CLOCK_REALTIME and
>> CLOCK_MONOTONIC and returns EINVAL if any other clock is specified.
>>
>> Includes feedback from many others. This function was originally
>> proposed[1] as pthread_cond_timedwaitonclock_np, but The Austin Group
>> preferred the new name.
> 
> For an initial implementation we will need to use a possible non reserved
> name, like pthread_cond_clockwait_np.  Wehen Austin Group finally add this
> on standard we can then add an alias with an update to abilist.

It seems that there is no need to actually use a non future reserved name,
so I withdrew this suggestion.

>>
>> 	* manual/threads.texi: Document pthread_cond_clockwait. The comment
>> 	was provided by Carlos O'Donell.
>>
>> [1] https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html
> 
> For this addition we will also need a NEWS entry.

I missed the last patch in the set where it indeed adds a NEWS entry.
So I think it would be fine without a NEWS entry for this patch.

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

* Re: [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions
  2019-06-07 17:01     ` Mike Crowe
@ 2019-06-12 20:56       ` Adhemerval Zanella
  0 siblings, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-12 20:56 UTC (permalink / raw
  To: libc-alpha



On 07/06/2019 14:01, Mike Crowe wrote:
> On Thursday 06 June 2019 at 16:18:05 -0300, Adhemerval Zanella wrote:
>>
>>
>> On 27/05/2019 17:03, Mike Crowe wrote:
>>> As recommended by the comments in the implementations of
>>> pthread_rwlock_timedrdlock and pthread_rwlock_timedwrlock, let's move the
>>> timeout validity checks into the corresponding pthread_rwlock_rdlock_full
>>> and pthread_rwlock_wrlock_full functions. Since these functions may be
>>> called with abstime == NULL, an extra check for that is necessary too.
>>
>> Is this really a gain here? It just moves some code around and add
>> an extra non required check. Wouldn't be better just to remove the
>> comments?
> 
> It looks like the comment was added by Torvald Riegel in
> cc25c8b4c1196a8c29e9a45b1e096b99a87b7f8c back in 2017.
> 
> From what I can tell from the x86_64 disassembly, the compiler throws away the extra check because
> these functions are all inline and it knows that abstime will be NULL.
> 
> However, I'm perfectly happy not to make this change, but it means that
> I'll need to add the same checks to pthread_rwlock_clockwrlock and
> pthread_wlock_clockrdlock.
> 
> I think that you've suggested consolidating these checks into a single
> function in the past, which would make that easier. How about adding
> is_valid_timespec or similar? Where would it be declared?

It seems we have multiple check that might be redundant, although it would
be likely removed from compiler.  On __pthread_rwlock_rdlock_full we have
the abstime check and futex_abstimed_wait, also present on futex_abstimed_wait.

However I think this should be ok and if we eventually make 
__pthread_rwlock_wrlock_full we can rearrange the checks to avoid
useless one.

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

* Re: [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls
  2019-06-12 19:32     ` Adhemerval Zanella
@ 2019-06-18 11:44       ` Mike Crowe
  2019-06-18 14:00         ` Adhemerval Zanella
  0 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-06-18 11:44 UTC (permalink / raw
  To: Adhemerval Zanella, libc-alpha

On Wednesday 12 June 2019 at 16:32:08 -0300, Adhemerval Zanella wrote:
> On 05/06/2019 14:52, Adhemerval Zanella wrote:
> 
> >> diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
> >> index 9a0f29e..7385562 100644
> >> --- a/nptl/pthread_cond_wait.c
> >> +++ b/nptl/pthread_cond_wait.c
> >> @@ -509,35 +509,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
> >>  		 values despite them being valid.  */
> >>  	      if (__glibc_unlikely (abstime->tv_sec < 0))
> >>  	        err = ETIMEDOUT;
> >> -
> >> -	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
> >> -		{
> >> -		  /* CLOCK_MONOTONIC is requested.  */
> >> -		  struct timespec rt;
> >> -		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
> >> -		    __libc_fatal ("clock_gettime does not support "
> >> -				  "CLOCK_MONOTONIC\n");
> >> -		  /* Convert the absolute timeout value to a relative
> >> -		     timeout.  */
> >> -		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
> >> -		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
> >> -		  if (rt.tv_nsec < 0)
> >> -		    {
> >> -		      rt.tv_nsec += 1000000000;
> >> -		      --rt.tv_sec;
> >> -		    }
> >> -		  /* Did we already time out?  */
> >> -		  if (__glibc_unlikely (rt.tv_sec < 0))
> >> -		    err = ETIMEDOUT;
> >> -		  else
> >> -		    err = futex_reltimed_wait_cancelable
> >> -			(cond->__data.__g_signals + g, 0, &rt, private);
> >> -		}
> >>  	      else
> >>  		{
> >> -		  /* Use CLOCK_REALTIME.  */
> >> +		  const clockid_t clockid =
> >> +		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
> >> +		    CLOCK_MONOTONIC : CLOCK_REALTIME;
> >> +
> >>  		  err = futex_abstimed_wait_cancelable
> >> -		      (cond->__data.__g_signals + g, 0, abstime, private);
> >> +                    (cond->__data.__g_signals + g, 0, clockid, abstime,
> >> +                     private);
> >>  		}
> >>  	    }
> > 
> > My understanding is we need to convert an absolute timeout to a relative one
> > on either futex_abstimed_wait_cancelable or lll_futex_clock_wait_bitset for
> > CLOCK_MONOTONIC.
> 
> Ok rechecking the patchset, it now uses futex_abstimed_wait_cancelable instead 
> of futex_reltimed_wait_cancelable, so my comment indeed does not apply.
> 
> However the naming is somewhat confusing because 'abstimed' only applies for 
> clockid being CLOCK_MONOTONIC. I think we should just name the new interfaces 
> as futex_timed_wait{_cancelable}.

I'm afraid that I don't understand this paragraph. I don't believe that
I've added a new interface here (well, apart from the
futex_abstimed_supported_clockid function.)

futex_abstimed_wait{,_cancelable} always take an absolute timeout measured
against the specified clock. They end up calling
lll_futex_clock_wait_bitset, which passes that absolute timeout directly to
the futex syscall. It is not converted to a relative timeout at any point.

> As a side node maybe we could simplify the futex_{abs,rel}timed_wait to call
> futex_timed_wait with expected clock on Linux implementation.

This confuses me too, but that is probably due to my earlier confusion.

Thanks.

Mike.

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

* Re: [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait
  2019-06-06 12:53   ` Adhemerval Zanella
  2019-06-12 20:22     ` Adhemerval Zanella
@ 2019-06-18 13:53     ` Mike Crowe
  2019-06-18 14:05       ` Mike Crowe
  2019-06-18 14:18       ` Adhemerval Zanella
  1 sibling, 2 replies; 36+ messages in thread
From: Mike Crowe @ 2019-06-18 13:53 UTC (permalink / raw
  To: Adhemerval Zanella, libc-alpha

On Thursday 06 June 2019 at 09:53:59 -0300, Adhemerval Zanella wrote:
> 
> 
> On 27/05/2019 17:03, Mike Crowe wrote:
> > @@ -644,10 +647,39 @@ __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);
> > +
> > +  /* 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 clockid = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
> > +                    ? CLOCK_MONOTONIC : CLOCK_REALTIME;
> > +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
> > +}
> > +
> 
> The relaxed atomic seems right, but I would like to a ack from another
> mantainer.

I remembered doing this based on a recommendation on this list. When I dug
up the email in question I was surprised to discover that it was you. :-)
So we still need a third pair of eyes.

> > +/* See __pthread_cond_wait_common.  */
> > +int
> > +__pthread_cond_clockwait (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;
> 
> Wouldn' t a  __nonnull ((X)) be better for this?

Well, I think that the check is important itself, and it just so happens to
have the side effect mentioned. I just copied the comment from
__pthread_cond_timedwait.

> > +
> > +  if (!futex_abstimed_supported_clockid (clockid))
> > +    return EINVAL;
> > +
> > +  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
> > +  if (clockid == CLOCK_MONOTONIC
> > +      && !futex_supports_exact_relative_timeouts ())
> > +    return EINVAL;
> 
> pthread_condattr_setclock returns ENOSUP for this case, should it does
> the same?

I discussed this with the Austin Group, and I believe that they were happy
with EINVAL.

I'd considered using ENOTSUP for valid but not supported clocks, and EINVAL
for invalid clocks. This would mean that the implementation would need to
keep a list of all clocks to check against, and I was worried that this
list could become out of date.

However, the only implementation of
futex_supports_exact_relative_timeouts() always returns true, so this code
never runs anyway.

(Maybe we should consider removing futex_supports_exact_relative_timeouts?)

Thanks.

Mike.

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

* Re: [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls
  2019-06-18 11:44       ` Mike Crowe
@ 2019-06-18 14:00         ` Adhemerval Zanella
  0 siblings, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-18 14:00 UTC (permalink / raw
  To: Mike Crowe, libc-alpha



On 18/06/2019 08:44, Mike Crowe wrote:
> On Wednesday 12 June 2019 at 16:32:08 -0300, Adhemerval Zanella wrote:
>> On 05/06/2019 14:52, Adhemerval Zanella wrote:
>>
>>>> diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
>>>> index 9a0f29e..7385562 100644
>>>> --- a/nptl/pthread_cond_wait.c
>>>> +++ b/nptl/pthread_cond_wait.c
>>>> @@ -509,35 +509,15 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
>>>>  		 values despite them being valid.  */
>>>>  	      if (__glibc_unlikely (abstime->tv_sec < 0))
>>>>  	        err = ETIMEDOUT;
>>>> -
>>>> -	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
>>>> -		{
>>>> -		  /* CLOCK_MONOTONIC is requested.  */
>>>> -		  struct timespec rt;
>>>> -		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
>>>> -		    __libc_fatal ("clock_gettime does not support "
>>>> -				  "CLOCK_MONOTONIC\n");
>>>> -		  /* Convert the absolute timeout value to a relative
>>>> -		     timeout.  */
>>>> -		  rt.tv_sec = abstime->tv_sec - rt.tv_sec;
>>>> -		  rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
>>>> -		  if (rt.tv_nsec < 0)
>>>> -		    {
>>>> -		      rt.tv_nsec += 1000000000;
>>>> -		      --rt.tv_sec;
>>>> -		    }
>>>> -		  /* Did we already time out?  */
>>>> -		  if (__glibc_unlikely (rt.tv_sec < 0))
>>>> -		    err = ETIMEDOUT;
>>>> -		  else
>>>> -		    err = futex_reltimed_wait_cancelable
>>>> -			(cond->__data.__g_signals + g, 0, &rt, private);
>>>> -		}
>>>>  	      else
>>>>  		{
>>>> -		  /* Use CLOCK_REALTIME.  */
>>>> +		  const clockid_t clockid =
>>>> +		    ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0) ?
>>>> +		    CLOCK_MONOTONIC : CLOCK_REALTIME;
>>>> +
>>>>  		  err = futex_abstimed_wait_cancelable
>>>> -		      (cond->__data.__g_signals + g, 0, abstime, private);
>>>> +                    (cond->__data.__g_signals + g, 0, clockid, abstime,
>>>> +                     private);
>>>>  		}
>>>>  	    }
>>>
>>> My understanding is we need to convert an absolute timeout to a relative one
>>> on either futex_abstimed_wait_cancelable or lll_futex_clock_wait_bitset for
>>> CLOCK_MONOTONIC.
>>
>> Ok rechecking the patchset, it now uses futex_abstimed_wait_cancelable instead 
>> of futex_reltimed_wait_cancelable, so my comment indeed does not apply.
>>
>> However the naming is somewhat confusing because 'abstimed' only applies for 
>> clockid being CLOCK_MONOTONIC. I think we should just name the new interfaces 
>> as futex_timed_wait{_cancelable}.
> 
> I'm afraid that I don't understand this paragraph. I don't believe that
> I've added a new interface here (well, apart from the
> futex_abstimed_supported_clockid function.)
> 
> futex_abstimed_wait{,_cancelable} always take an absolute timeout measured
> against the specified clock. They end up calling
> lll_futex_clock_wait_bitset, which passes that absolute timeout directly to
> the futex syscall. It is not converted to a relative timeout at any point.

It was a confusion from my part, sorry for the noise.  I withdrew my suggestion
here, the change looks ok thanks.

> 
>> As a side node maybe we could simplify the futex_{abs,rel}timed_wait to call
>> futex_timed_wait with expected clock on Linux implementation.
> 
> This confuses me too, but that is probably due to my earlier confusion.
> 
> Thanks.
> 
> Mike.
> 

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

* Re: [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait
  2019-06-18 13:53     ` Mike Crowe
@ 2019-06-18 14:05       ` Mike Crowe
  2019-06-18 14:18       ` Adhemerval Zanella
  1 sibling, 0 replies; 36+ messages in thread
From: Mike Crowe @ 2019-06-18 14:05 UTC (permalink / raw
  To: Adhemerval Zanella, libc-alpha

On Tuesday 18 June 2019 at 14:53:31 +0100, Mike Crowe wrote:
> (Maybe we should consider removing
> futex_supports_exact_relative_timeouts?)

Oh, it seems that you'd already suggested doing exactly that. I shall
prepare a patch to do so.

Thanks.

Mike.

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

* Re: [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait
  2019-06-18 13:53     ` Mike Crowe
  2019-06-18 14:05       ` Mike Crowe
@ 2019-06-18 14:18       ` Adhemerval Zanella
  1 sibling, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-18 14:18 UTC (permalink / raw
  To: Mike Crowe, libc-alpha; +Cc: Torvald Riegel



On 18/06/2019 10:53, Mike Crowe wrote:
> On Thursday 06 June 2019 at 09:53:59 -0300, Adhemerval Zanella wrote:
>>
>>
>> On 27/05/2019 17:03, Mike Crowe wrote:
>>> @@ -644,10 +647,39 @@ __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);
>>> +
>>> +  /* 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 clockid = (flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK)
>>> +                    ? CLOCK_MONOTONIC : CLOCK_REALTIME;
>>> +  return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
>>> +}
>>> +
>>
>> The relaxed atomic seems right, but I would like to a ack from another
>> mantainer.
> 
> I remembered doing this based on a recommendation on this list. When I dug
> up the email in question I was surprised to discover that it was you. :-)
> So we still need a third pair of eyes.

Torvald, do you think a relaxed load here would be right?

> 
>>> +/* See __pthread_cond_wait_common.  */
>>> +int
>>> +__pthread_cond_clockwait (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;
>>
>> Wouldn' t a  __nonnull ((X)) be better for this?
> 
> Well, I think that the check is important itself, and it just so happens to
> have the side effect mentioned. I just copied the comment from
> __pthread_cond_timedwait.

The check is required indeed, I was referring to also add __nonnull attribute
on internal __pthread_cond_clockwait signature.

> 
>>> +
>>> +  if (!futex_abstimed_supported_clockid (clockid))
>>> +    return EINVAL;
>>> +
>>> +  /* If we do not support waiting using CLOCK_MONOTONIC, return an error.  */
>>> +  if (clockid == CLOCK_MONOTONIC
>>> +      && !futex_supports_exact_relative_timeouts ())
>>> +    return EINVAL;
>>
>> pthread_condattr_setclock returns ENOSUP for this case, should it does
>> the same?
> 
> I discussed this with the Austin Group, and I believe that they were happy
> with EINVAL.
> 
> I'd considered using ENOTSUP for valid but not supported clocks, and EINVAL
> for invalid clocks. This would mean that the implementation would need to
> keep a list of all clocks to check against, and I was worried that this
> list could become out of date.
> 
> However, the only implementation of
> futex_supports_exact_relative_timeouts() always returns true, so this code
> never runs anyway.
> 
> (Maybe we should consider removing futex_supports_exact_relative_timeouts?)

My understanding is that NPTL is a Linux specific ABI, but it seems that
recent work from Torvald to try to decouple it and make it more a generic
interface. I am not sure if the extra-complexity does bring any gain, it
does make sense in the way the code is structured (where Linux specific
is add on sysdeps/unix/sysv/linux/).

So I do not see an issue in adding extra requirements (such as assume
futex_supports_exact_relative_timeouts) to generic futex.

> 
> Thanks.
> 
> Mike.
> 

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-06 15:40     ` Mike Crowe
  2019-06-06 17:43       ` Adhemerval Zanella
@ 2019-06-25 18:06       ` Florian Weimer
  2019-06-25 19:19         ` Mike Crowe
  1 sibling, 1 reply; 36+ messages in thread
From: Florian Weimer @ 2019-06-25 18:06 UTC (permalink / raw
  To: Mike Crowe; +Cc: libc-alpha

* Mike Crowe:

> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>> On 27/05/2019 17:03, Mike Crowe wrote:
>> > Add:
>> > 
>> >  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>> > 
>> > which behaves just like sem_timedwait, but measures abstime against the
>> > specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>> > sets errno == EINVAL if any other clock is specified.
>> 
>> For non-POSIX definition we will need to first export it as a GNU extension
>> with a possible non-reserved name and later, when it is included on the 
>> standard, to add an alias to the expected name.  
>> 
>> The usual naming scheme is to append the _np suffix (non-portable) on 
>> implementation, similar to recent posix_spawn file action extensions.
>> In this case it would be sem_clockwait_np.

> I thought we went through this before[1] and agreed that the _np suffix wasn't
> necessary in this case. However, I couldn't find a reply to Florian
> agreeing to that.

Upon second thought, I agree with Adhemerval here.  We should use a
function with the _np suffix, otherwise we'll be in a world of pain if
something else is standardized.

Thanks,
Florian

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-25 18:06       ` Florian Weimer
@ 2019-06-25 19:19         ` Mike Crowe
  2019-06-25 21:39           ` Florian Weimer
  0 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-06-25 19:19 UTC (permalink / raw
  To: Florian Weimer, libc-alpha

On Tuesday 25 June 2019 at 20:06:53 +0200, Florian Weimer wrote:
> * Mike Crowe:
> 
> > On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
> >> On 27/05/2019 17:03, Mike Crowe wrote:
> >> > Add:
> >> > 
> >> >  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
> >> > 
> >> > which behaves just like sem_timedwait, but measures abstime against the
> >> > specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
> >> > sets errno == EINVAL if any other clock is specified.
> >> 
> >> For non-POSIX definition we will need to first export it as a GNU extension
> >> with a possible non-reserved name and later, when it is included on the 
> >> standard, to add an alias to the expected name.  
> >> 
> >> The usual naming scheme is to append the _np suffix (non-portable) on 
> >> implementation, similar to recent posix_spawn file action extensions.
> >> In this case it would be sem_clockwait_np.
> 
> > I thought we went through this before[1] and agreed that the _np suffix wasn't
> > necessary in this case. However, I couldn't find a reply to Florian
> > agreeing to that.
> 
> Upon second thought, I agree with Adhemerval here.  We should use a
> function with the _np suffix, otherwise we'll be in a world of pain if
> something else is standardized.

Well, the plan is to standardise this[1] and The Austin Group are the ones
who decided on the names, but there needs to be an implementation before
that can happen. Presumably that implementation can have _np suffixes in
the short term though.

I shall apply some sed to the patch series and repost.

Thanks.

Mike.

[1] http://austingroupbugs.net/view.php?id=1216

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-25 19:19         ` Mike Crowe
@ 2019-06-25 21:39           ` Florian Weimer
  2019-06-25 22:07             ` Adhemerval Zanella
  0 siblings, 1 reply; 36+ messages in thread
From: Florian Weimer @ 2019-06-25 21:39 UTC (permalink / raw
  To: Mike Crowe, Adhemerval Zanella; +Cc: libc-alpha

* Mike Crowe:

> On Tuesday 25 June 2019 at 20:06:53 +0200, Florian Weimer wrote:
>> * Mike Crowe:
>> 
>> > On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>> >> On 27/05/2019 17:03, Mike Crowe wrote:
>> >> > Add:
>> >> > 
>> >> >  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>> >> > 
>> >> > which behaves just like sem_timedwait, but measures abstime against the
>> >> > specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>> >> > sets errno == EINVAL if any other clock is specified.
>> >> 
>> >> For non-POSIX definition we will need to first export it as a GNU extension
>> >> with a possible non-reserved name and later, when it is included on the 
>> >> standard, to add an alias to the expected name.  
>> >> 
>> >> The usual naming scheme is to append the _np suffix (non-portable) on 
>> >> implementation, similar to recent posix_spawn file action extensions.
>> >> In this case it would be sem_clockwait_np.
>> 
>> > I thought we went through this before[1] and agreed that the _np suffix wasn't
>> > necessary in this case. However, I couldn't find a reply to Florian
>> > agreeing to that.
>> 
>> Upon second thought, I agree with Adhemerval here.  We should use a
>> function with the _np suffix, otherwise we'll be in a world of pain if
>> something else is standardized.
>
> Well, the plan is to standardise this[1] and The Austin Group are the ones
> who decided on the names, but there needs to be an implementation before
> that can happen. Presumably that implementation can have _np suffixes in
> the short term though.
>
> I shall apply some sed to the patch series and repost.

Sorry, I see that we don't use _np for the other functions.
I'm confused now. 8-(

Adhemerval, is there value in keeping this consistent?  Have these
functions progressed to different stages in the POSIX process?

Thanks,
Florian

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-25 21:39           ` Florian Weimer
@ 2019-06-25 22:07             ` Adhemerval Zanella
  2019-06-26 13:02               ` Florian Weimer
  0 siblings, 1 reply; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-25 22:07 UTC (permalink / raw
  To: Florian Weimer, Mike Crowe; +Cc: libc-alpha



On 25/06/2019 18:39, Florian Weimer wrote:
> * Mike Crowe:
> 
>> On Tuesday 25 June 2019 at 20:06:53 +0200, Florian Weimer wrote:
>>> * Mike Crowe:
>>>
>>>> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>>>>> On 27/05/2019 17:03, Mike Crowe wrote:
>>>>>> Add:
>>>>>>
>>>>>>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>>>>>>
>>>>>> which behaves just like sem_timedwait, but measures abstime against the
>>>>>> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>>>>>> sets errno == EINVAL if any other clock is specified.
>>>>>
>>>>> For non-POSIX definition we will need to first export it as a GNU extension
>>>>> with a possible non-reserved name and later, when it is included on the 
>>>>> standard, to add an alias to the expected name.  
>>>>>
>>>>> The usual naming scheme is to append the _np suffix (non-portable) on 
>>>>> implementation, similar to recent posix_spawn file action extensions.
>>>>> In this case it would be sem_clockwait_np.
>>>
>>>> I thought we went through this before[1] and agreed that the _np suffix wasn't
>>>> necessary in this case. However, I couldn't find a reply to Florian
>>>> agreeing to that.
>>>
>>> Upon second thought, I agree with Adhemerval here.  We should use a
>>> function with the _np suffix, otherwise we'll be in a world of pain if
>>> something else is standardized.
>>
>> Well, the plan is to standardise this[1] and The Austin Group are the ones
>> who decided on the names, but there needs to be an implementation before
>> that can happen. Presumably that implementation can have _np suffixes in
>> the short term though.
>>
>> I shall apply some sed to the patch series and repost.
> 
> Sorry, I see that we don't use _np for the other functions.
> I'm confused now. 8-(
> 
> Adhemerval, is there value in keeping this consistent?  Have these
> functions progressed to different stages in the POSIX process?

My understanding of Austin proposal [1] (Mike can correct me) is naming is
settled and Android will also probably follow the same naming scheme. However, 
since Austin Group does not really propose newer interfaces, they
required a actual implementation to move forward.

Joseph also added sometime ago on IRC that we should add the symbols with 
the expected naming, but keep in mind there might be future incompatibilities 
requiring symbol versioning.

[1] http://austingroupbugs.net/view.php?id=1216

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-25 22:07             ` Adhemerval Zanella
@ 2019-06-26 13:02               ` Florian Weimer
  2019-06-26 13:47                 ` Mike Crowe
  0 siblings, 1 reply; 36+ messages in thread
From: Florian Weimer @ 2019-06-26 13:02 UTC (permalink / raw
  To: Adhemerval Zanella; +Cc: Mike Crowe, libc-alpha

* Adhemerval Zanella:

> On 25/06/2019 18:39, Florian Weimer wrote:
>> * Mike Crowe:
>> 
>>> On Tuesday 25 June 2019 at 20:06:53 +0200, Florian Weimer wrote:
>>>> * Mike Crowe:
>>>>
>>>>> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>>>>>> On 27/05/2019 17:03, Mike Crowe wrote:
>>>>>>> Add:
>>>>>>>
>>>>>>>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>>>>>>>
>>>>>>> which behaves just like sem_timedwait, but measures abstime against the
>>>>>>> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>>>>>>> sets errno == EINVAL if any other clock is specified.
>>>>>>
>>>>>> For non-POSIX definition we will need to first export it as a GNU extension
>>>>>> with a possible non-reserved name and later, when it is included on the 
>>>>>> standard, to add an alias to the expected name.  
>>>>>>
>>>>>> The usual naming scheme is to append the _np suffix (non-portable) on 
>>>>>> implementation, similar to recent posix_spawn file action extensions.
>>>>>> In this case it would be sem_clockwait_np.
>>>>
>>>>> I thought we went through this before[1] and agreed that the _np suffix wasn't
>>>>> necessary in this case. However, I couldn't find a reply to Florian
>>>>> agreeing to that.
>>>>
>>>> Upon second thought, I agree with Adhemerval here.  We should use a
>>>> function with the _np suffix, otherwise we'll be in a world of pain if
>>>> something else is standardized.
>>>
>>> Well, the plan is to standardise this[1] and The Austin Group are the ones
>>> who decided on the names, but there needs to be an implementation before
>>> that can happen. Presumably that implementation can have _np suffixes in
>>> the short term though.
>>>
>>> I shall apply some sed to the patch series and repost.
>> 
>> Sorry, I see that we don't use _np for the other functions.
>> I'm confused now. 8-(
>> 
>> Adhemerval, is there value in keeping this consistent?  Have these
>> functions progressed to different stages in the POSIX process?
>
> My understanding of Austin proposal [1] (Mike can correct me) is naming is
> settled and Android will also probably follow the same naming scheme. However, 
> since Austin Group does not really propose newer interfaces, they
> required a actual implementation to move forward.
>
> Joseph also added sometime ago on IRC that we should add the symbols with 
> the expected naming, but keep in mind there might be future incompatibilities 
> requiring symbol versioning.
>
> [1] http://austingroupbugs.net/view.php?id=1216

I'm still puzzled what's different compared to
posix_spawn_file_actions_addfchdir_np or pthread_rwlock_clockrdlock.
Are they at different stages of the POSIX process?

Thanks,
Florian

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-26 13:02               ` Florian Weimer
@ 2019-06-26 13:47                 ` Mike Crowe
  2019-06-26 17:18                   ` Adhemerval Zanella
  0 siblings, 1 reply; 36+ messages in thread
From: Mike Crowe @ 2019-06-26 13:47 UTC (permalink / raw
  To: Florian Weimer, Adhemerval Zanella, libc-alpha

On Wednesday 26 June 2019 at 15:02:44 +0200, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
> > On 25/06/2019 18:39, Florian Weimer wrote:
> >> * Mike Crowe:
> >> 
> >>> On Tuesday 25 June 2019 at 20:06:53 +0200, Florian Weimer wrote:
> >>>> * Mike Crowe:
> >>>>
> >>>>> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
> >>>>>> On 27/05/2019 17:03, Mike Crowe wrote:
> >>>>>>> Add:
> >>>>>>>
> >>>>>>>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
> >>>>>>>
> >>>>>>> which behaves just like sem_timedwait, but measures abstime against the
> >>>>>>> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
> >>>>>>> sets errno == EINVAL if any other clock is specified.
> >>>>>>
> >>>>>> For non-POSIX definition we will need to first export it as a GNU extension
> >>>>>> with a possible non-reserved name and later, when it is included on the 
> >>>>>> standard, to add an alias to the expected name.  
> >>>>>>
> >>>>>> The usual naming scheme is to append the _np suffix (non-portable) on 
> >>>>>> implementation, similar to recent posix_spawn file action extensions.
> >>>>>> In this case it would be sem_clockwait_np.
> >>>>
> >>>>> I thought we went through this before[1] and agreed that the _np suffix wasn't
> >>>>> necessary in this case. However, I couldn't find a reply to Florian
> >>>>> agreeing to that.
> >>>>
> >>>> Upon second thought, I agree with Adhemerval here.  We should use a
> >>>> function with the _np suffix, otherwise we'll be in a world of pain if
> >>>> something else is standardized.
> >>>
> >>> Well, the plan is to standardise this[1] and The Austin Group are the ones
> >>> who decided on the names, but there needs to be an implementation before
> >>> that can happen. Presumably that implementation can have _np suffixes in
> >>> the short term though.
> >>>
> >>> I shall apply some sed to the patch series and repost.
> >> 
> >> Sorry, I see that we don't use _np for the other functions.
> >> I'm confused now. 8-(
> >> 
> >> Adhemerval, is there value in keeping this consistent?  Have these
> >> functions progressed to different stages in the POSIX process?
> >
> > My understanding of Austin proposal [1] (Mike can correct me) is naming is
> > settled and Android will also probably follow the same naming scheme. However, 
> > since Austin Group does not really propose newer interfaces, they
> > required a actual implementation to move forward.
> >
> > Joseph also added sometime ago on IRC that we should add the symbols with 
> > the expected naming, but keep in mind there might be future incompatibilities 
> > requiring symbol versioning.
> >
> > [1] http://austingroupbugs.net/view.php?id=1216
> 
> I'm still puzzled what's different compared to
> posix_spawn_file_actions_addfchdir_np or pthread_rwlock_clockrdlock.
> Are they at different stages of the POSIX process?

I'm not sure what stage posix_spawn_file_actions_addfchdir (which appears
to be http://austingroupbugs.net/view.php?id=1208 ) is at, but it looks
like Eric Blake added it with the _np suffix prior to seeking
standardisation.

I attended an Austin Group teleconference (minutes at
https://www.opengroup.org/austin/docs/austin_895.txt ) late last year and I
believe that there was consensus in favour. We haven't yet determined which
track to use to get the functions into POSIX - I've been focusing on the
implementation.

If people would feel happier with using _np suffixes for now, then I think
we should add them. However, my next step after this series lands (if it
does) is to get a change into libstdc++ to use pthread_cond_clockwait{,_np}
so we'd have to keep the _np versions around for quite a while even after
the non-_np versions are standardised. libstdc++ would need to support
either name in parallel for a while too.

If it would be sufficient, we could delay landing the series while I try
confirming with The Austin Group that they are definitely happy with the
naming and parameters of the new functions. (There's a meeting tomorrow,
and I may be able to get it on the agenda.)

Thanks.

Mike.

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

* Re: [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait
  2019-06-26 13:47                 ` Mike Crowe
@ 2019-06-26 17:18                   ` Adhemerval Zanella
  0 siblings, 0 replies; 36+ messages in thread
From: Adhemerval Zanella @ 2019-06-26 17:18 UTC (permalink / raw
  To: Mike Crowe, Florian Weimer, libc-alpha



On 26/06/2019 10:47, Mike Crowe wrote:
> On Wednesday 26 June 2019 at 15:02:44 +0200, Florian Weimer wrote:
>> * Adhemerval Zanella:
>>
>>> On 25/06/2019 18:39, Florian Weimer wrote:
>>>> * Mike Crowe:
>>>>
>>>>> On Tuesday 25 June 2019 at 20:06:53 +0200, Florian Weimer wrote:
>>>>>> * Mike Crowe:
>>>>>>
>>>>>>> On Wednesday 05 June 2019 at 18:07:18 -0300, Adhemerval Zanella wrote:
>>>>>>>> On 27/05/2019 17:03, Mike Crowe wrote:
>>>>>>>>> Add:
>>>>>>>>>
>>>>>>>>>  int sem_clockwait (sem_t *sem, clockid_t clock, const struct timespec *abstime)
>>>>>>>>>
>>>>>>>>> which behaves just like sem_timedwait, but measures abstime against the
>>>>>>>>> specified clock. Currently supports CLOCK_REALTIME and CLOCK_MONOTONIC and
>>>>>>>>> sets errno == EINVAL if any other clock is specified.
>>>>>>>>
>>>>>>>> For non-POSIX definition we will need to first export it as a GNU extension
>>>>>>>> with a possible non-reserved name and later, when it is included on the 
>>>>>>>> standard, to add an alias to the expected name.  
>>>>>>>>
>>>>>>>> The usual naming scheme is to append the _np suffix (non-portable) on 
>>>>>>>> implementation, similar to recent posix_spawn file action extensions.
>>>>>>>> In this case it would be sem_clockwait_np.
>>>>>>
>>>>>>> I thought we went through this before[1] and agreed that the _np suffix wasn't
>>>>>>> necessary in this case. However, I couldn't find a reply to Florian
>>>>>>> agreeing to that.
>>>>>>
>>>>>> Upon second thought, I agree with Adhemerval here.  We should use a
>>>>>> function with the _np suffix, otherwise we'll be in a world of pain if
>>>>>> something else is standardized.
>>>>>
>>>>> Well, the plan is to standardise this[1] and The Austin Group are the ones
>>>>> who decided on the names, but there needs to be an implementation before
>>>>> that can happen. Presumably that implementation can have _np suffixes in
>>>>> the short term though.
>>>>>
>>>>> I shall apply some sed to the patch series and repost.
>>>>
>>>> Sorry, I see that we don't use _np for the other functions.
>>>> I'm confused now. 8-(
>>>>
>>>> Adhemerval, is there value in keeping this consistent?  Have these
>>>> functions progressed to different stages in the POSIX process?
>>>
>>> My understanding of Austin proposal [1] (Mike can correct me) is naming is
>>> settled and Android will also probably follow the same naming scheme. However, 
>>> since Austin Group does not really propose newer interfaces, they
>>> required a actual implementation to move forward.
>>>
>>> Joseph also added sometime ago on IRC that we should add the symbols with 
>>> the expected naming, but keep in mind there might be future incompatibilities 
>>> requiring symbol versioning.
>>>
>>> [1] http://austingroupbugs.net/view.php?id=1216
>>
>> I'm still puzzled what's different compared to
>> posix_spawn_file_actions_addfchdir_np or pthread_rwlock_clockrdlock.
>> Are they at different stages of the POSIX process?
> 
> I'm not sure what stage posix_spawn_file_actions_addfchdir (which appears
> to be http://austingroupbugs.net/view.php?id=1208 ) is at, but it looks
> like Eric Blake added it with the _np suffix prior to seeking
> standardisation.

My guess is to make it follow Solaris11 implementation which added the symbol
with _np suffix. The POSIX was accepte with the expected name, so eventually
both Solaris and glibc will need to provide the symbol with the expected
name.

> 
> I attended an Austin Group teleconference (minutes at
> https://www.opengroup.org/austin/docs/austin_895.txt ) late last year and I
> believe that there was consensus in favour. We haven't yet determined which
> track to use to get the functions into POSIX - I've been focusing on the
> implementation.
> 
> If people would feel happier with using _np suffixes for now, then I think
> we should add them. However, my next step after this series lands (if it
> does) is to get a change into libstdc++ to use pthread_cond_clockwait{,_np}
> so we'd have to keep the _np versions around for quite a while even after
> the non-_np versions are standardised. libstdc++ would need to support
> either name in parallel for a while too.

Once it set on libc abi we can't remove without bump the major version (and
this is troublesome and it would require time). I would prefer to not add
with _np just because it will most likely add needless complexity on 
libstdc++ side (or any other project) to check for multiples names for the 
same functionality.

> 
> If it would be sufficient, we could delay landing the series while I try
> confirming with The Austin Group that they are definitely happy with the
> naming and parameters of the new functions. (There's a meeting tomorrow,
> and I may be able to get it on the agenda.)

I don't have a strong opinion, but I think it would be good to land on 2.30.
I have the remaining patchset set for inclusion in my user branch and from 
Austin Group procedures I think is unlikely they will change the naming, 
specially for a non default _np or even after glibc provides the required 
actual implementation.


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

end of thread, other threads:[~2019-06-26 17:18 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-27 20:03 [PATCH v3 0/6] Implement POSIX-proposed _clockwait variants of existing _timedwait functions Mike Crowe
2019-05-27 20:03 ` [PATCH v3 1/6] nptl: Add clockid parameter to futex timed wait calls Mike Crowe
2019-06-05 17:52   ` Adhemerval Zanella
2019-06-06 12:06     ` Adhemerval Zanella
2019-06-12 19:32     ` Adhemerval Zanella
2019-06-18 11:44       ` Mike Crowe
2019-06-18 14:00         ` Adhemerval Zanella
2019-05-27 20:03 ` [PATCH v3 2/6] nptl: Add POSIX-proposed sem_clockwait Mike Crowe
2019-06-05 21:07   ` Adhemerval Zanella
2019-06-06 15:40     ` Mike Crowe
2019-06-06 17:43       ` Adhemerval Zanella
2019-06-06 19:20         ` Adhemerval Zanella
2019-06-25 18:06       ` Florian Weimer
2019-06-25 19:19         ` Mike Crowe
2019-06-25 21:39           ` Florian Weimer
2019-06-25 22:07             ` Adhemerval Zanella
2019-06-26 13:02               ` Florian Weimer
2019-06-26 13:47                 ` Mike Crowe
2019-06-26 17:18                   ` Adhemerval Zanella
2019-05-27 20:03 ` [PATCH v3 3/6] nptl: Add POSIX-proposed pthread_cond_clockwait Mike Crowe
2019-06-06 12:53   ` Adhemerval Zanella
2019-06-12 20:22     ` Adhemerval Zanella
2019-06-18 13:53     ` Mike Crowe
2019-06-18 14:05       ` Mike Crowe
2019-06-18 14:18       ` Adhemerval Zanella
2019-05-27 20:03 ` [PATCH v3 4/6] nptl: pthread_rwlock: Move timeout validation into _full functions Mike Crowe
2019-06-06 19:18   ` Adhemerval Zanella
2019-06-07 17:01     ` Mike Crowe
2019-06-12 20:56       ` Adhemerval Zanella
2019-05-27 20:03 ` [PATCH v3 5/6] nptl: Add POSIX-proposed pthread_rwlock_clockrdlock & pthread_rwlock_clockwrlock Mike Crowe
2019-06-07 14:05   ` Adhemerval Zanella
2019-06-07 17:14     ` Mike Crowe
2019-06-11 12:19       ` Adhemerval Zanella
2019-06-11 12:33         ` Torvald Riegel
2019-05-27 20:03 ` [PATCH v3 6/6] Update NEWS for new _clockwait functions Mike Crowe
2019-06-07 14:09   ` Adhemerval Zanella

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).