Hi,

attached there are few commits for libpthread which allow to use 
monotonic clock, if present, for pthread conditions.
Currently they should have "no effect", since there's no monotonic 
clock, yet, but will allow to automatically use it once available, 
detecting it at runtime.

The only bit I'm not too sure is the linking to rt in case libpthread is 
compiled a glibc addon (as result of the changes by Samuel an hour ago).

-- 
Pino Toscano
From d0c2da9c229d90c2301f2263c0b8856ceaf9f517 Mon Sep 17 00:00:00 2001
From: Pino Toscano <toscano.p...@tiscali.it>
Date: Sun, 22 Apr 2012 00:22:47 +0200
Subject: [PATCH 1/3] __pthread_timedblock: add an argument for the clock id

To make `__pthread_timedblock' properly measure time using the right
clock, add a new argument representing the clock to use.

* pthread/pt-internal.h (__pthread_timedblock): New argument CLOCK_ID.
* sysdeps/l4/pt-timedblock.c (__pthread_timedblock): Likewise.
* sysdeps/mach/pt-timedblock.c (__pthread_timedblock): Likewise.
* sysdeps/generic/pt-cond-timedwait.c
(__pthread_cond_timedwait_internal): Pass the clock of the
`pthread_cond' to `__pthread_timedblock'.
* sysdeps/generic/pt-mutex-timedlock.c
(__pthread_mutex_timedlock_internal): Pass CLOCK_REALTIME to
`__pthread_timedblock'.
* sysdeps/generic/pt-rwlock-timedrdlock.c
(__pthread_rwlock_timedrdlock_internal): Likewise.
* sysdeps/generic/pt-rwlock-timedwrlock.c
(__pthread_rwlock_timedwrlock_internal): Likewise.
* sysdeps/generic/sem-timedwait.c (__sem_timedwait_internal):
Likewise.
---
 pthread/pt-internal.h                   |    3 ++-
 sysdeps/generic/pt-cond-timedwait.c     |    5 ++++-
 sysdeps/generic/pt-mutex-timedlock.c    |    2 +-
 sysdeps/generic/pt-rwlock-timedrdlock.c |    2 +-
 sysdeps/generic/pt-rwlock-timedwrlock.c |    2 +-
 sysdeps/generic/sem-timedwait.c         |    2 +-
 sysdeps/l4/pt-timedblock.c              |    3 ++-
 sysdeps/mach/pt-timedblock.c            |    3 ++-
 8 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/pthread/pt-internal.h b/pthread/pt-internal.h
index 6186c86..a1e90aa 100644
--- a/pthread/pt-internal.h
+++ b/pthread/pt-internal.h
@@ -254,7 +254,8 @@ extern void __pthread_block (struct __pthread *thread);
 
 /* Block THREAD until *ABSTIME is reached.  */
 extern error_t __pthread_timedblock (struct __pthread *__restrict thread,
-				     const struct timespec *__restrict abstime);
+				     const struct timespec *__restrict abstime,
+				     clockid_t clock_id);
 
 /* Wakeup THREAD.  */
 extern void __pthread_wakeup (struct __pthread *thread);
diff --git a/sysdeps/generic/pt-cond-timedwait.c b/sysdeps/generic/pt-cond-timedwait.c
index 483f277..56eb1ec 100644
--- a/sysdeps/generic/pt-cond-timedwait.c
+++ b/sysdeps/generic/pt-cond-timedwait.c
@@ -46,6 +46,7 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond,
 {
   error_t err;
   int canceltype;
+  clockid_t clock_id = __pthread_default_condattr.clock;
 
   void cleanup (void *arg)
     {
@@ -68,6 +69,8 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond,
   /* Add ourselves to the list of waiters.  */
   __pthread_spin_lock (&cond->__lock);
   __pthread_enqueue (&cond->__queue, self);
+  if (cond->__attr)
+    clock_id = cond->__attr->clock;
   __pthread_spin_unlock (&cond->__lock);
 
   __pthread_mutex_unlock (mutex);
@@ -79,7 +82,7 @@ __pthread_cond_timedwait_internal (pthread_cond_t *cond,
 
   if (abstime)
     {
-      err = __pthread_timedblock (self, abstime);
+      err = __pthread_timedblock (self, abstime, clock_id);
       if (err)
 	/* We timed out.  We may need to disconnect ourself from the
 	   waiter queue.
diff --git a/sysdeps/generic/pt-mutex-timedlock.c b/sysdeps/generic/pt-mutex-timedlock.c
index 883e50a..48bffaf 100644
--- a/sysdeps/generic/pt-mutex-timedlock.c
+++ b/sysdeps/generic/pt-mutex-timedlock.c
@@ -130,7 +130,7 @@ __pthread_mutex_timedlock_internal (struct __pthread_mutex *mutex,
     {
       error_t err;
 
-      err = __pthread_timedblock (self, abstime);
+      err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
       if (err)
 	/* We timed out.  We may need to disconnect ourself from the
 	   waiter queue.
diff --git a/sysdeps/generic/pt-rwlock-timedrdlock.c b/sysdeps/generic/pt-rwlock-timedrdlock.c
index ba610fa..a110213 100644
--- a/sysdeps/generic/pt-rwlock-timedrdlock.c
+++ b/sysdeps/generic/pt-rwlock-timedrdlock.c
@@ -73,7 +73,7 @@ __pthread_rwlock_timedrdlock_internal (struct __pthread_rwlock *rwlock,
     {
       error_t err;
 
-      err = __pthread_timedblock (self, abstime);
+      err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
       if (err)
 	/* We timed out.  We may need to disconnect ourself from the
 	   waiter queue.
diff --git a/sysdeps/generic/pt-rwlock-timedwrlock.c b/sysdeps/generic/pt-rwlock-timedwrlock.c
index 04eab51..a5cc579 100644
--- a/sysdeps/generic/pt-rwlock-timedwrlock.c
+++ b/sysdeps/generic/pt-rwlock-timedwrlock.c
@@ -59,7 +59,7 @@ __pthread_rwlock_timedwrlock_internal (struct __pthread_rwlock *rwlock,
     {
       error_t err;
 
-      err = __pthread_timedblock (self, abstime);
+      err = __pthread_timedblock (self, abstime, CLOCK_REALTIME);
       if (err)
 	/* We timed out.  We may need to disconnect ourself from the
 	   waiter queue.
diff --git a/sysdeps/generic/sem-timedwait.c b/sysdeps/generic/sem-timedwait.c
index e34539a..94e6dee 100644
--- a/sysdeps/generic/sem-timedwait.c
+++ b/sysdeps/generic/sem-timedwait.c
@@ -55,7 +55,7 @@ __sem_timedwait_internal (sem_t *restrict sem,
     {
       error_t err;
 
-      err = __pthread_timedblock (self, timeout);
+      err = __pthread_timedblock (self, timeout, CLOCK_REALTIME);
       if (err)
 	/* We timed out.  We may need to disconnect ourself from the
 	   waiter queue.
diff --git a/sysdeps/l4/pt-timedblock.c b/sysdeps/l4/pt-timedblock.c
index ce7972b..951644f 100644
--- a/sysdeps/l4/pt-timedblock.c
+++ b/sysdeps/l4/pt-timedblock.c
@@ -27,7 +27,8 @@
 /* Block THREAD.  */
 error_t
 __pthread_timedblock (struct __pthread *thread,
-		      const struct timespec *abstime)
+		      const struct timespec *abstime,
+		      clockid_t clock_id)
 {
 #warning Need gettimeofday to implement properly.
   __pthread_block (thread);
diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c
index 6f54726..88beaa2 100644
--- a/sysdeps/mach/pt-timedblock.c
+++ b/sysdeps/mach/pt-timedblock.c
@@ -30,7 +30,8 @@
 /* Block THREAD.  */
 error_t
 __pthread_timedblock (struct __pthread *thread,
-		      const struct timespec *abstime)
+		      const struct timespec *abstime,
+		      clockid_t clock_id)
 {
   error_t err;
   mach_msg_header_t msg;
-- 
1.7.9.5

From da0668363311ed6c3a00d65eb2745c77f35d44c7 Mon Sep 17 00:00:00 2001
From: Pino Toscano <toscano.p...@tiscali.it>
Date: Sun, 22 Apr 2012 00:44:24 +0200
Subject: [PATCH 3/3] pthread_condattr_setclock: allow a monotonic clock, if
 present

If CLOCK_MONOTONIC is requested, check (only once) for the
availability of a monotonic clock using `clock_getres'.  If it is not,
reject CLOCK_MONOTONIC with EINVAL (as before).

* sysdeps/generic/pt-condattr-setclock.c (pthread_condattr_setclock):
Check for monotonic clock if requested.
---
 sysdeps/generic/pt-condattr-setclock.c |   27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/sysdeps/generic/pt-condattr-setclock.c b/sysdeps/generic/pt-condattr-setclock.c
index 984c17e..c5a78ef 100644
--- a/sysdeps/generic/pt-condattr-setclock.c
+++ b/sysdeps/generic/pt-condattr-setclock.c
@@ -23,11 +23,30 @@
 int
 pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock)
 {
-  if (__pthread_default_condattr.clock == clock)
+  /* Only a few clocks are allowed.  CLOCK_REALTIME is always allowed.
+     CLOCK_MONOTONIC only if the kernel has the necessary support.  */
+  if (clock == CLOCK_MONOTONIC)
     {
-      attr->clock = clock;
-      return 0;
+      /* Check whether the clock is available.  */
+      static int avail;
+
+      if (avail == 0)
+	{
+	  struct timespec ts;
+	  int res;
+
+	  res = clock_getres (CLOCK_MONOTONIC, &ts);
+	  avail = res < 0 ? -1 : 1;
+	}
+
+      if (avail < 0)
+	/* Not available.  */
+	return EINVAL;
     }
+  else if (clock != CLOCK_REALTIME)
+    return EINVAL;
+
+  attr->clock = clock;
 
-  return EINVAL;
+  return 0;
 }
-- 
1.7.9.5

From e6b5a04981010be80a3249c76e7f8d5a3d88a0d5 Mon Sep 17 00:00:00 2001
From: Pino Toscano <toscano.p...@tiscali.it>
Date: Sun, 22 Apr 2012 00:38:26 +0200
Subject: [PATCH 2/3] __pthread_timedblock: switch to clock_gettime

Use `clock_gettime' with the provided clock instead of `gettimeofday',
linking to rt.

* sysdeps/mach/pt-timedblock.c (__pthread_timedblock): Switch to
`clock_gettime'.
* Makefile [!IN_GLIBC] (LDLIBS): Link to rt.
[IN_GLIBC] ($(objpfx)libpthread.so): Likewise.
* Makefile.am (libpthread_a_LDADD): Likewise.
---
 Makefile                     |    2 ++
 Makefile.am                  |    2 ++
 sysdeps/mach/pt-timedblock.c |   13 ++++++-------
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index b291177..bee4e3c 100644
--- a/Makefile
+++ b/Makefile
@@ -210,8 +210,10 @@ VPATH += $(SYSDEP_PATH)
 
 ifeq ($(IN_GLIBC),no)
 HURDLIBS = ihash
+LDLIBS = -lrt
 else
 LDLIBS-pthread.so = -lihash
+$(objpfx)libpthread.so: $(common-objpfx)rt/librt.so
 endif
 
 ifeq ($(IN_GLIBC),no)
diff --git a/Makefile.am b/Makefile.am
index e1c062c..36ede54 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -166,3 +166,5 @@ libpthread_a_SOURCES = pt-attr.c pt-attr-destroy.c pt-attr-getdetachstate.c \
 	sigwaitinfo.c							    \
 	signal-dispatch-lowlevel.c					    \
 	sigprocmask.c
+
+libpthread_a_LDADD = -lrt
diff --git a/sysdeps/mach/pt-timedblock.c b/sysdeps/mach/pt-timedblock.c
index 88beaa2..d72ef73 100644
--- a/sysdeps/mach/pt-timedblock.c
+++ b/sysdeps/mach/pt-timedblock.c
@@ -36,27 +36,26 @@ __pthread_timedblock (struct __pthread *thread,
   error_t err;
   mach_msg_header_t msg;
   mach_msg_timeout_t timeout;
-  struct timeval now;
+  struct timespec now;
 
   /* We have an absolute time and now we have to convert it to a
      relative time.  Arg.  */
 
-  err = gettimeofday(&now, NULL);
+  err = clock_gettime (clock_id, &now);
   assert (! err);
 
   if (now.tv_sec > abstime->tv_sec
       || (now.tv_sec == abstime->tv_sec
-	  && now.tv_usec > ((abstime->tv_nsec + 999) / 1000)))
+	  && now.tv_nsec > abstime->tv_nsec))
     return ETIMEDOUT;
 
   timeout = (abstime->tv_sec - now.tv_sec) * 1000;
 
-  if (((abstime->tv_nsec + 999) / 1000) >= now.tv_usec)
-    timeout += (((abstime->tv_nsec + 999) / 1000) - now.tv_usec + 999) / 1000;
+  if (abstime->tv_nsec >= now.tv_nsec)
+    timeout += (abstime->tv_nsec - now.tv_nsec + 999999) / 1000000;
   else
     /* Need to do a carry.  */
-    timeout -= (now.tv_usec + 999) / 1000 -
-      ((abstime->tv_nsec + 999999) / 1000000);
+    timeout -= (now.tv_nsec - abstime->tv_nsec + 999999) / 1000000;
 
   err = __mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
 		    sizeof msg, thread->wakeupmsg.msgh_remote_port,
-- 
1.7.9.5

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to