[v3,3/6] nptl: Add POSIX-proposed pthread_cond_clockwait

Message ID eca8a8e2415c1e6b47f9551a6048931282f5b78e.1558987219.git-series.mac@mcrowe.com
State Superseded
Headers

Commit Message

Mike Crowe May 27, 2019, 8:03 p.m. UTC
  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
  

Comments

Adhemerval Zanella June 6, 2019, 12:53 p.m. UTC | #1
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
>
  
Adhemerval Zanella June 12, 2019, 8:22 p.m. UTC | #2
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.
  
Mike Crowe June 18, 2019, 1:53 p.m. UTC | #3
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.
  
Mike Crowe June 18, 2019, 2:05 p.m. UTC | #4
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.
  
Adhemerval Zanella June 18, 2019, 2:18 p.m. UTC | #5
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.
>
  

Patch

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