diff options
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | sem_timedwait.c | 2 | ||||
| -rw-r--r-- | sem_wait.c | 28 | 
3 files changed, 26 insertions, 12 deletions
| @@ -1,3 +1,9 @@ +2005-04-27  Ross Johnson  <ross at callisto.canberra.edu.au> + +	* sem_wait.c (ptw32_sem_wait_cleanup): after cancellation re-attempt +	to acquire the semaphore to avoid a race with a late sem_post. +	* sem_timedwait.c: Modify comments. +  2005-04-25  Ross Johnson  <ross at callisto.canberra.edu.au>  	* ptw32_relmillisecs.c: New module; converts future abstime to  @@ -7,7 +13,7 @@  	implemented for builds that define NEED_SEM (WinCE etc)  	* sem_timedwait.c: Likewise; after timeout or cancellation,  	re-attempt to acquire the semaphore in case one has been posted since -	the timeout/cancel occurred. Thanks to  +	the timeout/cancel occurred. Thanks to Stephan Mueller.  	* Makefile: Add ptw32_relmillisecs.c module; remove  	ptw32_{in,de}crease_semaphore.c modules.  	* GNUmakefile: Likewise. diff --git a/sem_timedwait.c b/sem_timedwait.c index 186c123..deefa6e 100644 --- a/sem_timedwait.c +++ b/sem_timedwait.c @@ -62,7 +62,7 @@ ptw32_sem_timedwait_cleanup (void * args)      {        /*         * We either timed out or were cancelled. -       * If someone posted since then we try to take the semaphore. +       * If someone has posted between then and now we try to take the semaphore.         * Otherwise the semaphore count may be wrong after we         * return. In the case of a cancellation, it is as if we         * were cancelled just before we return (after taking the semaphore) @@ -53,19 +53,27 @@ ptw32_sem_wait_cleanup(void * sem)    if (pthread_mutex_lock (&s->lock) == 0)      { -      ++s->value; -#ifdef NEED_SEM -           -      if (s->value > 0) -	{ -	  s->leftToUnblock = 0; -	}    -#else         /* -       * Don't release the W32 sema, it doesn't need adjustment -       * because it doesn't record the number of waiters. +       * If the sema is posted between us being cancelled and us locking +       * the sema again above then we need to consume that post but cancel +       * anyway. If we don't get the semaphore we indicate that we're no +       * longer waiting.         */ +      if (!(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)) +	{ +	  ++s->value; +#ifdef NEED_SEM +	  if (s->value > 0) +	    { +	      s->leftToUnblock = 0; +	    } +#else +	  /* +	   * Don't release the W32 sema, it doesn't need adjustment +	   * because it doesn't record the number of waiters. +	   */  #endif /* NEED_SEM */ +	}        (void) pthread_mutex_unlock (&s->lock);      }  } | 
