[newlib-cygwin] cygwin: simplify pthread timedwait handling

Corinna Vinschen corinna@sourceware.org
Thu Aug 3 17:18:00 GMT 2017


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=68217c3178dc897a6fce97ff99c3c3b07e638c65

commit 68217c3178dc897a6fce97ff99c3c3b07e638c65
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Thu Aug 3 19:08:31 2017 +0200

    cygwin: simplify pthread timedwait handling
    
    - Introduce inline helper pthread_convert_abstime.  It converts
      an absolute timespec to a Windows LARGE_INTEGER timestamp,
      depending on the used clock.
    
    - Use this function from pthread_cond_timedwait and semaphore::timedwait
    
    - Merge semaphore::_wait and semaphore::_timedwait into single _wait
      method, taking a LARGER_INTEGER timestamp.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/thread.cc | 123 +++++++++++++++++++++++-------------------------
 winsup/cygwin/thread.h  |   3 +-
 2 files changed, 60 insertions(+), 66 deletions(-)

diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 5076014..c604853 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -2515,6 +2515,41 @@ pthread::resume (pthread_t *thread)
   return 0;
 }
 
+static inline int
+pthread_convert_abstime (clockid_t clock_id, const struct timespec *abstime,
+			 PLARGE_INTEGER timeout)
+{
+  struct timespec tp;
+
+  /* According to SUSv3, the abstime value must be checked for validity. */
+  if (abstime->tv_sec < 0
+      || abstime->tv_nsec < 0
+      || abstime->tv_nsec > 999999999)
+    return EINVAL;
+
+  /* Check for immediate timeout before converting */
+  clock_gettime (clock_id, &tp);
+  if (tp.tv_sec > abstime->tv_sec
+      || (tp.tv_sec == abstime->tv_sec
+	  && tp.tv_nsec > abstime->tv_nsec))
+    return ETIMEDOUT;
+
+  timeout->QuadPart = abstime->tv_sec * NSPERSEC
+		     + (abstime->tv_nsec + 99LL) / 100LL;
+  switch (clock_id)
+    {
+    case CLOCK_REALTIME:
+      timeout->QuadPart += FACTOR;
+      break;
+    default:
+      /* other clocks must be handled as relative timeout */
+      timeout->QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL;
+      timeout->QuadPart *= -1LL;
+      break;
+    }
+  return 0;
+}
+
 extern "C" int
 pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
 {
@@ -2841,7 +2876,6 @@ extern "C" int
 pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
 			const struct timespec *abstime)
 {
-  struct timespec tp;
   LARGE_INTEGER timeout;
 
   pthread_testcancel ();
@@ -2852,34 +2886,10 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
       if (err)
 	return err;
 
-      /* According to SUSv3, the abstime value must be checked for validity. */
-      if (abstime->tv_sec < 0
-	  || abstime->tv_nsec < 0
-	  || abstime->tv_nsec > 999999999)
-	__leave;
-
-      clock_gettime ((*cond)->clock_id, &tp);
-
-      /* Check for immediate timeout before converting */
-      if (tp.tv_sec > abstime->tv_sec
-	  || (tp.tv_sec == abstime->tv_sec
-	      && tp.tv_nsec > abstime->tv_nsec))
-	return ETIMEDOUT;
-
-      timeout.QuadPart = abstime->tv_sec * NSPERSEC
-			  + (abstime->tv_nsec + 99LL) / 100LL;
+      err = pthread_convert_abstime ((*cond)->clock_id, abstime, &timeout);
+      if (err)
+	return err;
 
-      switch ((*cond)->clock_id)
-	{
-	case CLOCK_REALTIME:
-	  timeout.QuadPart += FACTOR;
-	  break;
-	default:
-	  /* other clocks must be handled as relative timeout */
-	  timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL;
-	  timeout.QuadPart *= -1LL;
-	  break;
-	}
       return (*cond)->wait (*mutex, &timeout);
     }
   __except (NO_ERROR) {}
@@ -3597,16 +3607,11 @@ semaphore::_trywait ()
 }
 
 int
-semaphore::_timedwait (const struct timespec *abstime)
+semaphore::_wait (PLARGE_INTEGER timeout)
 {
-  LARGE_INTEGER timeout;
-
   __try
     {
-      timeout.QuadPart = abstime->tv_sec * NSPERSEC
-			 + (abstime->tv_nsec + 99) / 100 + FACTOR;
-
-      switch (cygwait (win32_obj_id, &timeout,
+      switch (cygwait (win32_obj_id, timeout,
 		       cw_cancel | cw_cancel_self | cw_sig_eintr))
 	{
 	case WAIT_OBJECT_0:
@@ -3623,38 +3628,11 @@ semaphore::_timedwait (const struct timespec *abstime)
 	  return -1;
 	}
     }
-  __except (NO_ERROR)
-    {
-      /* According to SUSv3, abstime need not be checked for validity,
-	 if the semaphore can be locked immediately. */
-      if (_trywait ())
-	{
-	  set_errno (EINVAL);
-	  return -1;
-	}
-    }
+  __except (NO_ERROR) {}
   __endtry
   return 0;
 }
 
-int
-semaphore::_wait ()
-{
-  switch (cygwait (win32_obj_id, cw_infinite,
-		   cw_cancel | cw_cancel_self | cw_sig_eintr))
-    {
-    case WAIT_OBJECT_0:
-      break;
-    case WAIT_SIGNALED:
-      set_errno (EINTR);
-      return -1;
-    default:
-      pthread_printf ("cygwait failed. %E");
-      break;
-    }
-  return 0;
-}
-
 void
 semaphore::_fixup_before_fork ()
 {
@@ -3840,13 +3818,30 @@ semaphore::trywait (sem_t *sem)
 int
 semaphore::timedwait (sem_t *sem, const struct timespec *abstime)
 {
+  LARGE_INTEGER timeout;
+
   if (!is_good_object (sem))
     {
       set_errno (EINVAL);
       return -1;
     }
 
-  return (*sem)->_timedwait (abstime);
+  /* According to SUSv3, abstime need not be checked for validity,
+     if the semaphore can be locked immediately. */
+  if (!(*sem)->_trywait ())
+    return 0;
+
+  __try
+    {
+      int err = pthread_convert_abstime (CLOCK_REALTIME, abstime, &timeout);
+      if (err)
+	return err;
+
+      return (*sem)->_wait (&timeout);
+    }
+  __except (NO_ERROR) {}
+  __endtry
+  return EINVAL;
 }
 
 int
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 48fb6fb..9bb8618 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -693,11 +693,10 @@ public:
   }
 
 private:
-  int _wait ();
   void _post ();
   int _getvalue (int *sval);
   int _trywait ();
-  int _timedwait (const struct timespec *abstime);
+  int _wait (PLARGE_INTEGER timeout = NULL);
 
   void _fixup_before_fork ();
   void _fixup_after_fork ();



More information about the Cygwin-cvs mailing list