[hurd,commited] htl: Add clock variants

Message ID 20200526005040.1851573-1-samuel.thibault@ens-lyon.org
State New
Headers show
Series
  • [hurd,commited] htl: Add clock variants
Related show

Commit Message

Samuel Thibault May 26, 2020, 12:50 a.m.
* htl/pt-join.c (__pthread_join): Move implementation to...
(__pthread_join_common): ... new function. Add try, timed and clock support.
(__pthread_join): Reimplement on top of __pthread_join_common.
(__pthread_tryjoin_np, __pthread_timedjoin_np, __pthread_clockjoin_np):
Implement on top of __pthread_join_common.
(pthread_tryjoin_np, pthread_timedjoin_np, pthread_clockjoin_np): New
aliases.

* hurd/hurdlock.c (__lll_abstimed_wait, __lll_abstimed_xwait,
__lll_abstimed_lock): Check for supported clock.

* sysdeps/htl/pt-cond-timedwait.c (__pthread_cond_timedwait_internal):
Add clockid parameter and support it.
(__pthread_cond_timedwait): Pass -1 as clockid.
(__pthread_cond_clockwait): New function.
(pthread_cond_clockwait): New alias.
* sysdeps/htl/pt-cond-wait.c (__pthread_cond_timedwait_internal): Update
prototype.
(__pthread_cond_wait): Pass -1 as clockid.

* sysdeps/htl/pt-rwlock-timedrdlock.c
(__pthread_rwlock_timedrdlock_internal): Add clockid parameter, and
support id.
(__pthread_rwlock_clockrdlock): New function.
(pthread_rwlock_clockrdlock): New alias.
* sysdeps/htl/pt-rwlock-rdlock.c (__pthread_rwlock_timedrdlock_internal): Update
prototype.
(__pthread_rwlock_rdlock): Pass -1 as clockid.

* sysdeps/htl/pt-rwlock-timedwrlock.c
(__pthread_rwlock_timedwrlock_internal): Add clockid parameter, and
support id.
(__pthread_rwlock_clockwrlock): New function.
(pthread_rwlock_clockwrlock): New alias.
* sysdeps/htl/pt-rwlock-wrlock.c (__pthread_rwlock_timedwrlock_internal): Update
prototype.
(__pthread_rwlock_wrlock): Pass -1 as clockid.

* sysdeps/mach/hurd/htl/pt-mutex-timedlock.c (__pthread_mutex_timedlock): Move implementation to
(__pthread_mutex_clocklock): New function with additional clockid
parameter and support it.
(pthread_mutex_clocklock): New alias.
(__pthread_mutex_timedlock): Reimplement on top of __pthread_mutex_clocklock.

* sysdeps/htl/pthread.h (pthread_tryjoin_np, pthread_timedjoin_np,
pthread_clockjoin_np, pthread_mutex_clocklock, pthread_cond_clockwait,
pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock): New prototypes.
* sysdeps/htl/pthreadP.h (__pthread_cond_clockwait): New prototype.

* htl/Versions (GLIBC_2.32): Add pthread_cond_clockwait,
pthread_mutex_clocklock, pthread_rwlock_clockrdlock, pthread_rwlock_clockwrlock,
pthread_tryjoin_np, pthread_timedjoin_np, pthread_clockjoin_np.
* sysdeps/mach/hurd/i386/libpthread.abilist (pthread_clockjoin_np,
pthread_cond_clockwait, pthread_mutex_clocklock, pthread_rwlock_clockrdlock,
pthread_rwlock_clockwrlock, pthread_timedjoin_np, pthread_tryjoin_np):
New functions.

* nptl/tst-abstime.c, nptl/tst-join10.c, nptl/tst-join11.c, nptl/tst-join12.c,
nptl/tst-join13.c, nptl/tst-join14.c, nptl/tst-join2.c, nptl/tst-join3.c,
nptl/tst-join8.c, nptl/tst-join9.c, nptl/tst-mutex-errorcheck.c,
nptl/tst-pthread-mutexattr.c, nptl/tst-mutex11.c, nptl/tst-mutex5.c,
nptl/tst-mutex7.c, nptl/tst-mutex7robus.c, nptl/tst-mutex9.c,
nptl/tst-rwlock12.c, nptl/tst-rwlock14.c: Move to sysdeps/pthread.
* sysdeps/pthread/tst-mutex8.c: Move back to nptl.
* nptl/Makefile (tests): Move tst-mutex5, tst-mutex7, tst-mutex7robust,
tst-mutex9, tst-mutex11, tst-rwlock12, tst-rwlock14, tst-join2, tst-join3,
tst-join8, tst-join9 tst-join10, tst-join11, tst-join12, tst-join13, tst-join14,
tst-abstime, tst-mutex-errorcheck, tst-pthread-mutexattr to ...
* sysdeps/pthread/Makefile (tests): ... here.
---
 htl/Versions                                  |  7 +++
 htl/pt-join.c                                 | 62 ++++++++++++++++---
 hurd/hurdlock.c                               | 12 ++++
 nptl/Makefile                                 | 16 ++---
 {sysdeps/pthread => nptl}/tst-mutex8.c        |  0
 sysdeps/htl/pt-cond-timedwait.c               | 24 ++++++-
 sysdeps/htl/pt-cond-wait.c                    |  3 +-
 sysdeps/htl/pt-rwlock-rdlock.c                |  3 +-
 sysdeps/htl/pt-rwlock-timedrdlock.c           | 19 +++++-
 sysdeps/htl/pt-rwlock-timedwrlock.c           | 19 +++++-
 sysdeps/htl/pt-rwlock-wrlock.c                |  3 +-
 sysdeps/htl/pthread.h                         | 62 +++++++++++++++++++
 sysdeps/htl/pthreadP.h                        |  5 ++
 sysdeps/mach/hurd/htl/pt-mutex-timedlock.c    | 20 ++++--
 sysdeps/mach/hurd/i386/libpthread.abilist     |  7 +++
 sysdeps/pthread/Makefile                      | 14 +++--
 {nptl => sysdeps/pthread}/tst-abstime.c       |  0
 {nptl => sysdeps/pthread}/tst-join10.c        |  0
 {nptl => sysdeps/pthread}/tst-join11.c        |  0
 {nptl => sysdeps/pthread}/tst-join12.c        |  0
 {nptl => sysdeps/pthread}/tst-join13.c        |  0
 {nptl => sysdeps/pthread}/tst-join14.c        |  0
 {nptl => sysdeps/pthread}/tst-join2.c         |  0
 {nptl => sysdeps/pthread}/tst-join3.c         |  0
 {nptl => sysdeps/pthread}/tst-join8.c         |  0
 {nptl => sysdeps/pthread}/tst-join9.c         |  0
 .../pthread}/tst-mutex-errorcheck.c           |  0
 {nptl => sysdeps/pthread}/tst-mutex11.c       |  0
 {nptl => sysdeps/pthread}/tst-mutex5.c        |  0
 {nptl => sysdeps/pthread}/tst-mutex7.c        |  0
 {nptl => sysdeps/pthread}/tst-mutex7robust.c  |  0
 {nptl => sysdeps/pthread}/tst-mutex9.c        |  0
 .../pthread}/tst-pthread-mutexattr.c          |  0
 {nptl => sysdeps/pthread}/tst-rwlock12.c      |  0
 {nptl => sysdeps/pthread}/tst-rwlock14.c      |  0
 35 files changed, 236 insertions(+), 40 deletions(-)
 rename {sysdeps/pthread => nptl}/tst-mutex8.c (100%)
 rename {nptl => sysdeps/pthread}/tst-abstime.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join10.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join11.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join12.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join13.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join14.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join2.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join3.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join8.c (100%)
 rename {nptl => sysdeps/pthread}/tst-join9.c (100%)
 rename {nptl => sysdeps/pthread}/tst-mutex-errorcheck.c (100%)
 rename {nptl => sysdeps/pthread}/tst-mutex11.c (100%)
 rename {nptl => sysdeps/pthread}/tst-mutex5.c (100%)
 rename {nptl => sysdeps/pthread}/tst-mutex7.c (100%)
 rename {nptl => sysdeps/pthread}/tst-mutex7robust.c (100%)
 rename {nptl => sysdeps/pthread}/tst-mutex9.c (100%)
 rename {nptl => sysdeps/pthread}/tst-pthread-mutexattr.c (100%)
 rename {nptl => sysdeps/pthread}/tst-rwlock12.c (100%)
 rename {nptl => sysdeps/pthread}/tst-rwlock14.c (100%)

-- 
2.26.2

Comments

Florian Weimer via Libc-alpha May 29, 2020, 1:29 p.m. | #1
On 25/05/2020 21:50, Samuel Thibault wrote:
> * htl/pt-join.c (__pthread_join): Move implementation to...

> (__pthread_join_common): ... new function. Add try, timed and clock support.

> (__pthread_join): Reimplement on top of __pthread_join_common.

> (__pthread_tryjoin_np, __pthread_timedjoin_np, __pthread_clockjoin_np):

> Implement on top of __pthread_join_common.

> (pthread_tryjoin_np, pthread_timedjoin_np, pthread_clockjoin_np): New

> aliases.


There is no needed to keep formatting the change with a CL in the 
commit message, although there is no rule against it. I personally
think a more descriptive commit message is more elucidative than 
a bland CL.

In this change, maybe something like 'Add hurd pthread variants
to work with different clocks (as done for Linux on 2.30) and the
required Hurd internal changes to avoid code duplication. The
patch also moves the NPTL tests to generic folder).

Patch

diff --git a/htl/Versions b/htl/Versions
index a0962e6a42..5fa9ef637c 100644
--- a/htl/Versions
+++ b/htl/Versions
@@ -151,10 +151,17 @@  libpthread {
     cnd_broadcast; cnd_destroy; cnd_init; cnd_signal; cnd_timedwait; cnd_wait;
     tss_create; tss_delete; tss_get; tss_set;
 
+    pthread_cond_clockwait;
+
     pthread_mutexattr_getrobust; pthread_mutexattr_getrobust_np;
     pthread_mutexattr_setrobust; pthread_mutexattr_setrobust_np;
 
     pthread_mutex_consistent; pthread_mutex_consistent_np;
+    pthread_mutex_clocklock;
+
+    pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
+
+    pthread_tryjoin_np; pthread_timedjoin_np; pthread_clockjoin_np;
   }
 
   GLIBC_PRIVATE {
diff --git a/htl/pt-join.c b/htl/pt-join.c
index 0473511be9..f3d17dbc65 100644
--- a/htl/pt-join.c
+++ b/htl/pt-join.c
@@ -24,8 +24,10 @@ 
 
 /* Make calling thread wait for termination of thread THREAD.  Return
    the exit status of the thread in *STATUS.  */
-int
-__pthread_join (pthread_t thread, void **status)
+static int
+__pthread_join_common (pthread_t thread, void **status, int try,
+		       clockid_t clockid,
+		       const struct timespec *abstime)
 {
   struct __pthread *pthread;
   int err = 0;
@@ -39,18 +41,30 @@  __pthread_join (pthread_t thread, void **status)
     return EDEADLK;
 
   __pthread_mutex_lock (&pthread->state_lock);
-  pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock,
-			&pthread->state_lock);
 
-  /* Rely on pthread_cond_wait being a cancellation point to make
-     pthread_join one too.  */
-  while (pthread->state == PTHREAD_JOINABLE)
-    __pthread_cond_wait (&pthread->state_cond, &pthread->state_lock);
+  if (try == 0)
+    {
+      pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock,
+			    &pthread->state_lock);
 
-  pthread_cleanup_pop (0);
+      /* Rely on pthread_cond_wait being a cancellation point to make
+	 pthread_join one too.  */
+      while (pthread->state == PTHREAD_JOINABLE && err != ETIMEDOUT)
+	err = __pthread_cond_clockwait (&pthread->state_cond,
+					&pthread->state_lock,
+					clockid, abstime);
+
+      pthread_cleanup_pop (0);
+    }
 
   switch (pthread->state)
     {
+    case PTHREAD_JOINABLE:
+      __pthread_mutex_unlock (&pthread->state_lock);
+      if (err != ETIMEDOUT)
+	err = EBUSY;
+      break;
+
     case PTHREAD_EXITED:
       /* THREAD has already exited.  Salvage its exit status.  */
       if (status != NULL)
@@ -76,4 +90,34 @@  __pthread_join (pthread_t thread, void **status)
 
   return err;
 }
+
+int
+__pthread_join (pthread_t thread, void **status)
+{
+  return __pthread_join_common (thread, status, 0, CLOCK_REALTIME, NULL);
+}
 weak_alias (__pthread_join, pthread_join);
+
+int
+__pthread_tryjoin_np (pthread_t thread, void **status)
+{
+  return __pthread_join_common (thread, status, 1, CLOCK_REALTIME, NULL);
+}
+weak_alias (__pthread_tryjoin_np, pthread_tryjoin_np);
+
+int
+__pthread_timedjoin_np (pthread_t thread, void **status,
+			const struct timespec *abstime)
+{
+  return __pthread_join_common (thread, status, 0, CLOCK_REALTIME, abstime);
+}
+weak_alias (__pthread_timedjoin_np, pthread_timedjoin_np);
+
+int
+__pthread_clockjoin_np (pthread_t thread, void **status,
+			clockid_t clockid,
+			const struct timespec *abstime)
+{
+  return __pthread_join_common (thread, status, 0, clockid, abstime);
+}
+weak_alias (__pthread_clockjoin_np, pthread_clockjoin_np);
diff --git a/hurd/hurdlock.c b/hurd/hurdlock.c
index 50da0a2121..59d017fc02 100644
--- a/hurd/hurdlock.c
+++ b/hurd/hurdlock.c
@@ -47,6 +47,9 @@  int
 __lll_abstimed_wait (void *ptr, int val,
   const struct timespec *tsp, int flags, int clk)
 {
+  if (clk != CLOCK_REALTIME)
+    return EINVAL;
+
   int mlsec = compute_reltime (tsp, clk);
   return mlsec < 0 ? KERN_TIMEDOUT : lll_timed_wait (ptr, val, mlsec, flags);
 }
@@ -55,6 +58,9 @@  int
 __lll_abstimed_xwait (void *ptr, int lo, int hi,
   const struct timespec *tsp, int flags, int clk)
 {
+  if (clk != CLOCK_REALTIME)
+    return EINVAL;
+
   int mlsec = compute_reltime (tsp, clk);
   return mlsec < 0 ? KERN_TIMEDOUT : lll_timed_xwait (ptr, lo, hi, mlsec,
 	                                              flags);
@@ -64,6 +70,9 @@  int
 __lll_abstimed_lock (void *ptr,
   const struct timespec *tsp, int flags, int clk)
 {
+  if (clk != CLOCK_REALTIME)
+    return EINVAL;
+
   if (lll_trylock (ptr) == 0)
     return 0;
 
@@ -147,6 +156,9 @@  __lll_robust_abstimed_lock (void *ptr,
   int wait_time = 25;
   unsigned int val;
 
+  if (clk != CLOCK_REALTIME)
+    return EINVAL;
+
   while (1)
     {
       val = *iptr;
diff --git a/nptl/Makefile b/nptl/Makefile
index 587b241367..0d07d6cccb 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -259,8 +259,8 @@  CFLAGS-tst-minstack-throw.o = -std=gnu++11
 LDLIBS-tst-minstack-throw = -lstdc++
 
 tests = tst-attr2 tst-attr3 tst-default-attr \
-	tst-mutex5 tst-mutex7 tst-mutex9 tst-mutex11 tst-mutex5a tst-mutex7a \
-	tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \
+	tst-mutex5a tst-mutex7a \
+	tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \
 	tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \
 	tst-mutexpi9 \
 	tst-cond11 tst-cond20 tst-cond21 tst-cond22 tst-cond26 tst-cond27 \
@@ -268,16 +268,13 @@  tests = tst-attr2 tst-attr3 tst-default-attr \
 	tst-robustpi6 tst-robustpi7 tst-robustpi9 \
 	tst-rwlock2 tst-rwlock2a tst-rwlock2b tst-rwlock3 \
 	tst-rwlock6 tst-rwlock7 tst-rwlock8 \
-	tst-rwlock9 tst-rwlock10 tst-rwlock11 tst-rwlock12 \
-	tst-rwlock14 tst-rwlock15 tst-rwlock17 tst-rwlock18 \
+	tst-rwlock9 tst-rwlock10 tst-rwlock11 \
+	tst-rwlock15 tst-rwlock17 tst-rwlock18 \
 	tst-once5 \
 	tst-sem5 tst-sem17 \
 	tst-align tst-align3 \
 	tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
 	tst-raise1 \
-	tst-join2 tst-join3 \
-	tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
-	tst-join14 \
 	tst-detach1 \
 	tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
 	tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 tst-tsd6 \
@@ -301,7 +298,7 @@  tests = tst-attr2 tst-attr3 tst-default-attr \
 	tst-exit1 tst-exit2 tst-exit3 \
 	tst-stdio1 tst-stdio2 \
 	tst-stack1 tst-stack2 tst-stack3 tst-stack4 \
-	tst-pthread-attr-affinity tst-pthread-mutexattr \
+	tst-pthread-attr-affinity \
 	tst-unload \
 	tst-dlsym1 \
 	tst-sysconf \
@@ -312,14 +309,13 @@  tests = tst-attr2 tst-attr3 tst-default-attr \
 	tst-context1 \
 	tst-sched1 \
 	tst-backtrace1 \
-	tst-abstime \
 	tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
 	tst-getpid3 \
 	tst-setuid3 \
 	tst-initializers1 $(addprefix tst-initializers1-,\
 			    c89 gnu89 c99 gnu99 c11 gnu11) \
 	tst-bad-schedattr \
-	tst-thread_local1 tst-mutex-errorcheck \
+	tst-thread_local1 \
 	tst-robust-fork tst-create-detached tst-memstream \
 	tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit \
 	tst-minstack-throw \
diff --git a/sysdeps/pthread/tst-mutex8.c b/nptl/tst-mutex8.c
similarity index 100%
rename from sysdeps/pthread/tst-mutex8.c
rename to nptl/tst-mutex8.c
diff --git a/sysdeps/htl/pt-cond-timedwait.c b/sysdeps/htl/pt-cond-timedwait.c
index d27f7ba8d6..a0ced9a074 100644
--- a/sysdeps/htl/pt-cond-timedwait.c
+++ b/sysdeps/htl/pt-cond-timedwait.c
@@ -24,6 +24,7 @@ 
 
 extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond,
 					      pthread_mutex_t *mutex,
+					      clockid_t clockid,
 					      const struct timespec *abstime);
 
 int
@@ -31,11 +32,22 @@  __pthread_cond_timedwait (pthread_cond_t *cond,
 			  pthread_mutex_t *mutex,
 			  const struct timespec *abstime)
 {
-  return __pthread_cond_timedwait_internal (cond, mutex, abstime);
+  return __pthread_cond_timedwait_internal (cond, mutex, -1, abstime);
 }
 
 weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait);
 
+int
+__pthread_cond_clockwait (pthread_cond_t *cond,
+			  pthread_mutex_t *mutex,
+			  clockid_t clockid,
+			  const struct timespec *abstime)
+{
+  return __pthread_cond_timedwait_internal (cond, mutex, clockid, abstime);
+}
+
+weak_alias (__pthread_cond_clockwait, pthread_cond_clockwait);
+
 struct cancel_ctx
 {
   struct __pthread *wakeup;
@@ -69,11 +81,17 @@  cancel_hook (void *arg)
 int
 __pthread_cond_timedwait_internal (pthread_cond_t *cond,
 				   pthread_mutex_t *mutex,
+				   clockid_t clockid,
 				   const struct timespec *abstime)
 {
   error_t err;
   int cancelled, oldtype, drain;
-  clockid_t clock_id = __pthread_default_condattr.__clock;
+  clockid_t clock_id;
+
+  if (clockid != -1)
+    clock_id = clockid;
+  else
+    clock_id = __pthread_default_condattr.__clock;
 
   if (abstime && ! valid_nanoseconds (abstime->tv_nsec))
     return EINVAL;
@@ -114,7 +132,7 @@  __pthread_cond_timedwait_internal (pthread_cond_t *cond,
          already unblocked, progressing on the return path.  */
       __pthread_spin_wait (&cond->__lock);
       __pthread_enqueue (&cond->__queue, self);
-      if (cond->__attr != NULL)
+      if (cond->__attr != NULL && clockid == -1)
 	clock_id = cond->__attr->__clock;
       __pthread_spin_unlock (&cond->__lock);
     }
diff --git a/sysdeps/htl/pt-cond-wait.c b/sysdeps/htl/pt-cond-wait.c
index 2e87db0ca6..00a6922659 100644
--- a/sysdeps/htl/pt-cond-wait.c
+++ b/sysdeps/htl/pt-cond-wait.c
@@ -23,6 +23,7 @@ 
 /* Implemented in pt-cond-timedwait.c.  */
 extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond,
 					      pthread_mutex_t *mutex,
+					      clockid_t clockid,
 					      const struct timespec *abstime);
 
 
@@ -32,7 +33,7 @@  extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond,
 int
 __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
-  return __pthread_cond_timedwait_internal (cond, mutex, 0);
+  return __pthread_cond_timedwait_internal (cond, mutex, -1, 0);
 }
 
 weak_alias (__pthread_cond_wait, pthread_cond_wait);
diff --git a/sysdeps/htl/pt-rwlock-rdlock.c b/sysdeps/htl/pt-rwlock-rdlock.c
index 07aa119cbc..6588f01f80 100644
--- a/sysdeps/htl/pt-rwlock-rdlock.c
+++ b/sysdeps/htl/pt-rwlock-rdlock.c
@@ -22,6 +22,7 @@ 
 /* Implemented in pt-rwlock-timedrdlock.c.  */
 extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock
 						  *rwlock,
+						  clockid_t clockid,
 						  const struct timespec
 						  *abstime);
 
@@ -29,6 +30,6 @@  extern int __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock
 int
 __pthread_rwlock_rdlock (struct __pthread_rwlock *rwlock)
 {
-  return __pthread_rwlock_timedrdlock_internal (rwlock, 0);
+  return __pthread_rwlock_timedrdlock_internal (rwlock, -1, 0);
 }
 weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
diff --git a/sysdeps/htl/pt-rwlock-timedrdlock.c b/sysdeps/htl/pt-rwlock-timedrdlock.c
index c2827662fd..7019085489 100644
--- a/sysdeps/htl/pt-rwlock-timedrdlock.c
+++ b/sysdeps/htl/pt-rwlock-timedrdlock.c
@@ -27,6 +27,7 @@ 
    wait forever.  */
 int
 __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock,
+				       clockid_t clockid,
 				       const struct timespec *abstime)
 {
   error_t err;
@@ -62,7 +63,10 @@  __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock,
   assert (rwlock->__readers == 0);
 
   if (abstime != NULL && ! valid_nanoseconds (abstime->tv_nsec))
-    return EINVAL;
+    {
+      __pthread_spin_unlock (&rwlock->__lock);
+      return EINVAL;
+    }
 
   self = _pthread_self ();
 
@@ -72,7 +76,7 @@  __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock,
 
   /* Block the thread.  */
   if (abstime != NULL)
-    err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
+    err = __pthread_timedblock (self, abstime, clockid);
   else
     {
       err = 0;
@@ -116,6 +120,15 @@  int
 __pthread_rwlock_timedrdlock (struct __pthread_rwlock *rwlock,
 			      const struct timespec *abstime)
 {
-  return __pthread_rwlock_timedrdlock_internal (rwlock, abstime);
+  return __pthread_rwlock_timedrdlock_internal (rwlock, CLOCK_REALTIME, abstime);
 }
 weak_alias (__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock)
+
+int
+__pthread_rwlock_clockrdlock (struct __pthread_rwlock *rwlock,
+			      clockid_t clockid,
+			      const struct timespec *abstime)
+{
+  return __pthread_rwlock_timedrdlock_internal (rwlock, clockid, abstime);
+}
+weak_alias (__pthread_rwlock_clockrdlock, pthread_rwlock_clockrdlock)
diff --git a/sysdeps/htl/pt-rwlock-timedwrlock.c b/sysdeps/htl/pt-rwlock-timedwrlock.c
index d0293c1e96..e9f8da07db 100644
--- a/sysdeps/htl/pt-rwlock-timedwrlock.c
+++ b/sysdeps/htl/pt-rwlock-timedwrlock.c
@@ -27,6 +27,7 @@ 
    shall not time out.  */
 int
 __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock,
+				       clockid_t clockid,
 				       const struct timespec *abstime)
 {
   error_t err;
@@ -48,7 +49,10 @@  __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock,
   /* The lock is busy.  */
 
   if (abstime != NULL && ! valid_nanoseconds (abstime->tv_nsec))
-    return EINVAL;
+    {
+      __pthread_spin_unlock (&rwlock->__lock);
+      return EINVAL;
+    }
 
   self = _pthread_self ();
 
@@ -58,7 +62,7 @@  __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock,
 
   /* Block the thread.  */
   if (abstime != NULL)
-    err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
+    err = __pthread_timedblock (self, abstime, clockid);
   else
     {
       err = 0;
@@ -99,6 +103,15 @@  int
 __pthread_rwlock_timedwrlock (struct __pthread_rwlock *rwlock,
 			      const struct timespec *abstime)
 {
-  return __pthread_rwlock_timedwrlock_internal (rwlock, abstime);
+  return __pthread_rwlock_timedwrlock_internal (rwlock, CLOCK_REALTIME, abstime);
 }
 weak_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock)
+
+int
+__pthread_rwlock_clockwrlock (struct __pthread_rwlock *rwlock,
+			      clockid_t clockid,
+			      const struct timespec *abstime)
+{
+  return __pthread_rwlock_timedwrlock_internal (rwlock, clockid, abstime);
+}
+weak_alias (__pthread_rwlock_clockwrlock, pthread_rwlock_clockwrlock)
diff --git a/sysdeps/htl/pt-rwlock-wrlock.c b/sysdeps/htl/pt-rwlock-wrlock.c
index dcf09d98c7..c3e9c64051 100644
--- a/sysdeps/htl/pt-rwlock-wrlock.c
+++ b/sysdeps/htl/pt-rwlock-wrlock.c
@@ -24,6 +24,7 @@ 
 /* Implemented in pt-rwlock-timedwrlock.c.  */
 extern int __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock
 						  *rwlock,
+						  clockid_t clockid,
 						  const struct timespec
 						  *abstime);
 
@@ -31,6 +32,6 @@  extern int __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock
 int
 __pthread_rwlock_wrlock (struct __pthread_rwlock *rwlock)
 {
-  return __pthread_rwlock_timedwrlock_internal (rwlock, 0);
+  return __pthread_rwlock_timedwrlock_internal (rwlock, -1, 0);
 }
 weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
diff --git a/sysdeps/htl/pthread.h b/sysdeps/htl/pthread.h
index d639385eb3..c44f70b158 100644
--- a/sysdeps/htl/pthread.h
+++ b/sysdeps/htl/pthread.h
@@ -222,6 +222,32 @@  extern void pthread_exit (void *__status) __attribute__ ((__noreturn__));
    the exit status of the thread in *STATUS.  */
 extern int pthread_join (pthread_t __threadp, void **__status);
 
+#ifdef __USE_GNU
+/* Check whether thread TH has terminated.  If yes return the status of
+   the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL.  */
+extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
+
+/* Make calling thread wait for termination of the thread TH, but only
+   until TIMEOUT.  The exit status of the thread is stored in
+   *THREAD_RETURN, if THREAD_RETURN is not NULL.
+
+   This function is a cancellation point and therefore not marked with
+   __THROW.  */
+extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
+				 const struct timespec *__abstime);
+
+/* Make calling thread wait for termination of the thread TH, but only
+   until TIMEOUT measured against the clock specified by CLOCKID.  The
+   exit status of the thread is stored in *THREAD_RETURN, if
+   THREAD_RETURN is not NULL.
+
+   This function is a cancellation point and therefore not marked with
+   __THROW.  */
+extern int pthread_clockjoin_np (pthread_t __th, void **__thread_return,
+                                 clockid_t __clockid,
+				 const struct timespec *__abstime);
+#endif
+
 /* Indicate that the storage for THREAD can be reclaimed when it
    terminates.  */
 extern int pthread_detach (pthread_t __threadp);
@@ -401,6 +427,13 @@  extern int pthread_mutex_timedlock (struct __pthread_mutex *__restrict __mutex,
 	__THROWNL __nonnull ((1, 2));
 #endif
 
+#ifdef __USE_GNU
+extern int pthread_mutex_clocklock (pthread_mutex_t *__restrict __mutex,
+				    clockid_t __clockid,
+				    const struct timespec *__restrict
+				    __abstime) __THROWNL __nonnull ((1, 3));
+#endif
+
 /* Unlock MUTEX.  */
 extern int pthread_mutex_unlock (pthread_mutex_t *__mutex)
 	__THROWNL __nonnull ((1));
@@ -517,6 +550,21 @@  extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
 				   pthread_mutex_t *__restrict __mutex,
 				   __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
 
 
 /* Spin locks.  */
@@ -623,6 +671,13 @@  extern int pthread_rwlock_timedrdlock (struct __pthread_rwlock *__restrict __rwl
 	__THROWNL __nonnull ((1, 2));
 # endif
 
+# ifdef __USE_GNU
+extern int pthread_rwlock_clockrdlock (pthread_rwlock_t *__restrict __rwlock,
+				       clockid_t __clockid,
+				       const struct timespec *__restrict
+				       __abstime) __THROWNL __nonnull ((1, 3));
+# endif
+
 /* Acquire the rwlock *RWLOCK for writing.  */
 extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
 	__THROWNL __nonnull ((1));
@@ -639,6 +694,13 @@  extern int pthread_rwlock_timedwrlock (struct __pthread_rwlock *__restrict __rwl
 	__THROWNL __nonnull ((1, 2));
 # endif
 
+# ifdef __USE_GNU
+extern int pthread_rwlock_clockwrlock (pthread_rwlock_t *__restrict __rwlock,
+				       clockid_t __clockid,
+				       const struct timespec *__restrict
+				       __abstime) __THROWNL __nonnull ((1, 3));
+# endif
+
 /* Release the lock held by the current thread on *RWLOCK.  */
 extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
 	__THROWNL __nonnull ((1));
diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h
index 1726ebb122..7486c9383e 100644
--- a/sysdeps/htl/pthreadP.h
+++ b/sysdeps/htl/pthreadP.h
@@ -50,6 +50,11 @@  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)
+  __nonnull ((1, 2, 4));
 extern int __pthread_cond_destroy (pthread_cond_t *cond);
 
 typedef struct __cthread *__cthread_t;
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c b/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c
index b11bfc87c8..198b340429 100644
--- a/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c
+++ b/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c
@@ -24,7 +24,9 @@ 
 #include <hurdlock.h>
 
 int
-__pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
+__pthread_mutex_clocklock (pthread_mutex_t *mtxp,
+			   clockid_t clockid,
+			   const struct timespec *tsp)
 {
   struct __pthread *self;
   int ret, flags = mtxp->__flags & GSYNC_SHARED;
@@ -32,7 +34,7 @@  __pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
   switch (MTX_TYPE (mtxp))
     {
     case PT_MTX_NORMAL:
-      ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags);
+      ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags, clockid);
       break;
 
     case PT_MTX_RECURSIVE:
@@ -45,7 +47,7 @@  __pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
 	  ++mtxp->__cnt;
 	  ret = 0;
 	}
-      else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags)) == 0)
+      else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags, clockid)) == 0)
 	{
 	  mtx_set_owner (mtxp, self, flags);
 	  mtxp->__cnt = 1;
@@ -57,7 +59,7 @@  __pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
       self = _pthread_self ();
       if (mtx_owned_p (mtxp, self, flags))
 	ret = EDEADLK;
-      else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags)) == 0)
+      else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags, clockid)) == 0)
 	mtx_set_owner (mtxp, self, flags);
 
       break;
@@ -66,7 +68,7 @@  __pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
     case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST:
     case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST:
       self = _pthread_self ();
-      ROBUST_LOCK (self, mtxp, lll_robust_abstimed_lock, tsp, flags);
+      ROBUST_LOCK (self, mtxp, lll_robust_abstimed_lock, tsp, flags, clockid);
       break;
 
     default:
@@ -76,5 +78,13 @@  __pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
 
   return ret;
 }
+weak_alias (__pthread_mutex_clocklock, pthread_mutex_clocklock)
+
+int
+__pthread_mutex_timedlock (pthread_mutex_t *mutex,
+			   const struct timespec *tsp)
+{
+  return __pthread_mutex_clocklock (mutex, CLOCK_REALTIME, tsp);
+}
 weak_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
 hidden_def (__pthread_mutex_timedlock)
diff --git a/sysdeps/mach/hurd/i386/libpthread.abilist b/sysdeps/mach/hurd/i386/libpthread.abilist
index 6e75c90009..a1026f0d1e 100644
--- a/sysdeps/mach/hurd/i386/libpthread.abilist
+++ b/sysdeps/mach/hurd/i386/libpthread.abilist
@@ -155,12 +155,19 @@  GLIBC_2.32 mtx_lock F
 GLIBC_2.32 mtx_timedlock F
 GLIBC_2.32 mtx_trylock F
 GLIBC_2.32 mtx_unlock F
+GLIBC_2.32 pthread_clockjoin_np F
+GLIBC_2.32 pthread_cond_clockwait F
+GLIBC_2.32 pthread_mutex_clocklock F
 GLIBC_2.32 pthread_mutex_consistent F
 GLIBC_2.32 pthread_mutex_consistent_np F
 GLIBC_2.32 pthread_mutexattr_getrobust F
 GLIBC_2.32 pthread_mutexattr_getrobust_np F
 GLIBC_2.32 pthread_mutexattr_setrobust F
 GLIBC_2.32 pthread_mutexattr_setrobust_np F
+GLIBC_2.32 pthread_rwlock_clockrdlock F
+GLIBC_2.32 pthread_rwlock_clockwrlock F
+GLIBC_2.32 pthread_timedjoin_np F
+GLIBC_2.32 pthread_tryjoin_np F
 GLIBC_2.32 thrd_create F
 GLIBC_2.32 thrd_detach F
 GLIBC_2.32 thrd_exit F
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
index 2f8aff35b2..b8dcadd2db 100644
--- a/sysdeps/pthread/Makefile
+++ b/sysdeps/pthread/Makefile
@@ -51,17 +51,23 @@  tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
 	 tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
 	 tst-cond23 tst-cond24 tst-cond25 \
 	 tst-cond-except \
-	 tst-join1 tst-join4 tst-join5 tst-join6 tst-join7 \
+	 tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
+	 tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
+	 tst-join14 \
 	 tst-key1 tst-key2 tst-key3 tst-key4 \
-	 tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex6 tst-mutex10 \
+	 tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \
+	 tst-mutex5 tst-mutex6 tst-mutex7 tst-mutex7robust tst-mutex9 \
+	 tst-mutex10 tst-mutex11 tst-pthread-mutexattr \
 	 tst-once1 tst-once2 tst-once3 tst-once4 \
 	 tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
 	 tst-robust6 tst-robust7 tst-robust9 tst-robust10 \
-	 tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock13 tst-rwlock16 \
+	 tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock12 \
+	 tst-rwlock13 tst-rwlock14 tst-rwlock16 \
 	 tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
 	 tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem6 tst-sem7 \
 	 tst-sem8 tst-sem9 tst-sem10 tst-sem14 tst-sem15 tst-sem16 \
-	 tst-spin1 tst-spin2 tst-spin3 tst-spin4
+	 tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
+	 tst-abstime
 
 tests-internal += tst-robust8
 
diff --git a/nptl/tst-abstime.c b/sysdeps/pthread/tst-abstime.c
similarity index 100%
rename from nptl/tst-abstime.c
rename to sysdeps/pthread/tst-abstime.c
diff --git a/nptl/tst-join10.c b/sysdeps/pthread/tst-join10.c
similarity index 100%
rename from nptl/tst-join10.c
rename to sysdeps/pthread/tst-join10.c
diff --git a/nptl/tst-join11.c b/sysdeps/pthread/tst-join11.c
similarity index 100%
rename from nptl/tst-join11.c
rename to sysdeps/pthread/tst-join11.c
diff --git a/nptl/tst-join12.c b/sysdeps/pthread/tst-join12.c
similarity index 100%
rename from nptl/tst-join12.c
rename to sysdeps/pthread/tst-join12.c
diff --git a/nptl/tst-join13.c b/sysdeps/pthread/tst-join13.c
similarity index 100%
rename from nptl/tst-join13.c
rename to sysdeps/pthread/tst-join13.c
diff --git a/nptl/tst-join14.c b/sysdeps/pthread/tst-join14.c
similarity index 100%
rename from nptl/tst-join14.c
rename to sysdeps/pthread/tst-join14.c
diff --git a/nptl/tst-join2.c b/sysdeps/pthread/tst-join2.c
similarity index 100%
rename from nptl/tst-join2.c
rename to sysdeps/pthread/tst-join2.c
diff --git a/nptl/tst-join3.c b/sysdeps/pthread/tst-join3.c
similarity index 100%
rename from nptl/tst-join3.c
rename to sysdeps/pthread/tst-join3.c
diff --git a/nptl/tst-join8.c b/sysdeps/pthread/tst-join8.c
similarity index 100%
rename from nptl/tst-join8.c
rename to sysdeps/pthread/tst-join8.c
diff --git a/nptl/tst-join9.c b/sysdeps/pthread/tst-join9.c
similarity index 100%
rename from nptl/tst-join9.c
rename to sysdeps/pthread/tst-join9.c
diff --git a/nptl/tst-mutex-errorcheck.c b/sysdeps/pthread/tst-mutex-errorcheck.c
similarity index 100%
rename from nptl/tst-mutex-errorcheck.c
rename to sysdeps/pthread/tst-mutex-errorcheck.c
diff --git a/nptl/tst-mutex11.c b/sysdeps/pthread/tst-mutex11.c
similarity index 100%
rename from nptl/tst-mutex11.c
rename to sysdeps/pthread/tst-mutex11.c
diff --git a/nptl/tst-mutex5.c b/sysdeps/pthread/tst-mutex5.c
similarity index 100%
rename from nptl/tst-mutex5.c
rename to sysdeps/pthread/tst-mutex5.c
diff --git a/nptl/tst-mutex7.c b/sysdeps/pthread/tst-mutex7.c
similarity index 100%
rename from nptl/tst-mutex7.c
rename to sysdeps/pthread/tst-mutex7.c
diff --git a/nptl/tst-mutex7robust.c b/sysdeps/pthread/tst-mutex7robust.c
similarity index 100%
rename from nptl/tst-mutex7robust.c
rename to sysdeps/pthread/tst-mutex7robust.c
diff --git a/nptl/tst-mutex9.c b/sysdeps/pthread/tst-mutex9.c
similarity index 100%
rename from nptl/tst-mutex9.c
rename to sysdeps/pthread/tst-mutex9.c
diff --git a/nptl/tst-pthread-mutexattr.c b/sysdeps/pthread/tst-pthread-mutexattr.c
similarity index 100%
rename from nptl/tst-pthread-mutexattr.c
rename to sysdeps/pthread/tst-pthread-mutexattr.c
diff --git a/nptl/tst-rwlock12.c b/sysdeps/pthread/tst-rwlock12.c
similarity index 100%
rename from nptl/tst-rwlock12.c
rename to sysdeps/pthread/tst-rwlock12.c
diff --git a/nptl/tst-rwlock14.c b/sysdeps/pthread/tst-rwlock14.c
similarity index 100%
rename from nptl/tst-rwlock14.c
rename to sysdeps/pthread/tst-rwlock14.c