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>
This commit is contained in:
		| @@ -2515,6 +2515,41 @@ pthread::resume (pthread_t *thread) | |||||||
|   return 0; |   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 | extern "C" int | ||||||
| pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) | 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, | pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, | ||||||
| 			const struct timespec *abstime) | 			const struct timespec *abstime) | ||||||
| { | { | ||||||
|   struct timespec tp; |  | ||||||
|   LARGE_INTEGER timeout; |   LARGE_INTEGER timeout; | ||||||
|  |  | ||||||
|   pthread_testcancel (); |   pthread_testcancel (); | ||||||
| @@ -2852,34 +2886,10 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, | |||||||
|       if (err) |       if (err) | ||||||
| 	return err; | 	return err; | ||||||
|  |  | ||||||
|       /* According to SUSv3, the abstime value must be checked for validity. */ |       err = pthread_convert_abstime ((*cond)->clock_id, abstime, &timeout); | ||||||
|       if (abstime->tv_sec < 0 |       if (err) | ||||||
| 	  || abstime->tv_nsec < 0 | 	return err; | ||||||
| 	  || 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; |  | ||||||
|  |  | ||||||
|       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); |       return (*cond)->wait (*mutex, &timeout); | ||||||
|     } |     } | ||||||
|   __except (NO_ERROR) {} |   __except (NO_ERROR) {} | ||||||
| @@ -3597,16 +3607,11 @@ semaphore::_trywait () | |||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| semaphore::_timedwait (const struct timespec *abstime) | semaphore::_wait (PLARGE_INTEGER timeout) | ||||||
| { | { | ||||||
|   LARGE_INTEGER timeout; |  | ||||||
|  |  | ||||||
|   __try |   __try | ||||||
|     { |     { | ||||||
|       timeout.QuadPart = abstime->tv_sec * NSPERSEC |       switch (cygwait (win32_obj_id, timeout, | ||||||
| 			 + (abstime->tv_nsec + 99) / 100 + FACTOR; |  | ||||||
|  |  | ||||||
|       switch (cygwait (win32_obj_id, &timeout, |  | ||||||
| 		       cw_cancel | cw_cancel_self | cw_sig_eintr)) | 		       cw_cancel | cw_cancel_self | cw_sig_eintr)) | ||||||
| 	{ | 	{ | ||||||
| 	case WAIT_OBJECT_0: | 	case WAIT_OBJECT_0: | ||||||
| @@ -3623,38 +3628,11 @@ semaphore::_timedwait (const struct timespec *abstime) | |||||||
| 	  return -1; | 	  return -1; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|   __except (NO_ERROR) |   __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; |  | ||||||
| 	} |  | ||||||
|     } |  | ||||||
|   __endtry |   __endtry | ||||||
|   return 0; |   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 | void | ||||||
| semaphore::_fixup_before_fork () | semaphore::_fixup_before_fork () | ||||||
| { | { | ||||||
| @@ -3840,13 +3818,30 @@ semaphore::trywait (sem_t *sem) | |||||||
| int | int | ||||||
| semaphore::timedwait (sem_t *sem, const struct timespec *abstime) | semaphore::timedwait (sem_t *sem, const struct timespec *abstime) | ||||||
| { | { | ||||||
|  |   LARGE_INTEGER timeout; | ||||||
|  |  | ||||||
|   if (!is_good_object (sem)) |   if (!is_good_object (sem)) | ||||||
|     { |     { | ||||||
|       set_errno (EINVAL); |       set_errno (EINVAL); | ||||||
|       return -1; |       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 | int | ||||||
|   | |||||||
| @@ -693,11 +693,10 @@ public: | |||||||
|   } |   } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   int _wait (); |  | ||||||
|   void _post (); |   void _post (); | ||||||
|   int _getvalue (int *sval); |   int _getvalue (int *sval); | ||||||
|   int _trywait (); |   int _trywait (); | ||||||
|   int _timedwait (const struct timespec *abstime); |   int _wait (PLARGE_INTEGER timeout = NULL); | ||||||
|  |  | ||||||
|   void _fixup_before_fork (); |   void _fixup_before_fork (); | ||||||
|   void _fixup_after_fork (); |   void _fixup_after_fork (); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user