diff options
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | NEWS | 6 | ||||
| -rw-r--r-- | global.c | 5 | ||||
| -rw-r--r-- | implement.h | 1 | ||||
| -rw-r--r-- | pthread_once.c | 15 | ||||
| -rw-r--r-- | ptw32_processInitialize.c | 1 | ||||
| -rw-r--r-- | ptw32_processTerminate.c | 1 | ||||
| -rw-r--r-- | sem_timedwait.c | 2 | ||||
| -rw-r--r-- | sem_wait.c | 28 | ||||
| -rw-r--r-- | tests/test.h | 9 | 
10 files changed, 41 insertions, 35 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 Stefan Mueller.  	* Makefile: Add ptw32_relmillisecs.c module; remove  	ptw32_{in,de}crease_semaphore.c modules.  	* GNUmakefile: Likewise. @@ -26,8 +26,8 @@ All tests passed.  Some minor speed improvements were also done.  * Fix integer overrun error in pthread_mutex_timedlock() - missed when -sem_timedwait() was fixed in release 2.2.0. This rouitne no longer returns -ENOSUP when NEED_SEM is defined - it is supported (NEED_SEM is only +sem_timedwait() was fixed in release 2.2.0. This routine no longer returns +ENOTSUP when NEED_SEM is defined - it is supported (NEED_SEM is only  required for WinCE versions prior to 3.0).  * Fix timeout bug in sem_timedwait(). @@ -61,7 +61,7 @@ Known issues in this release  determine..  * The Borland version of the dll fails some of the tests with a memory read -exception. The cause is not yet known but a compiler bug has not been rules +exception. The cause is not yet known but a compiler bug has not been ruled  out. @@ -107,11 +107,6 @@ CRITICAL_SECTION ptw32_spinlock_test_init_lock;   */  CRITICAL_SECTION ptw32_cond_list_lock; -/* - * Global lock to serialise once_control event management. - */ -CRITICAL_SECTION ptw32_once_event_lock; -  #ifdef _UWIN  /*   * Keep a count of the number of threads. diff --git a/implement.h b/implement.h index 7504dd0..b723ef3 100644 --- a/implement.h +++ b/implement.h @@ -488,7 +488,6 @@ extern CRITICAL_SECTION ptw32_cond_list_lock;  extern CRITICAL_SECTION ptw32_cond_test_init_lock;  extern CRITICAL_SECTION ptw32_rwlock_test_init_lock;  extern CRITICAL_SECTION ptw32_spinlock_test_init_lock; -extern CRITICAL_SECTION ptw32_once_event_lock;  #ifdef _UWIN  extern int pthread_count; diff --git a/pthread_once.c b/pthread_once.c index eb355dd..0ee063a 100644 --- a/pthread_once.c +++ b/pthread_once.c @@ -69,10 +69,9 @@   * to be a cancelation point. A cancelation meant that at least some waiting threads   * if any had to be woken so that one might become the new initter thread.   * Waiters could no longer simply assume that, if the event was not null, it did - * not need to create an event. Some real critical sections were needed, and in the - * current library, a global CRITICAL_SECTION is probably more efficient than a per - * once_control PTHREAD_MUTEX_INITIALIZER that should be somehow destroyed on exit from - * pthread_once(). Also, the cancelled init thread needed to set the event, and the + * not need to create an event. + * + * Also, the cancelled init thread needed to set the event, and the   * new init thread (the winner of the race between any newly arriving threads and   * waking waiters) would need to reset it again. In the meantime, threads could be   * happily looping around until they either suspended on the reset event, or exited @@ -114,7 +113,6 @@ ptw32_once_init_routine_cleanup(void * arg)    (void) PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->state, (LONG)PTW32_ONCE_CANCELLED);    (void) PTW32_INTERLOCKED_EXCHANGE((LPLONG)&once_control->started, (LONG)PTW32_FALSE); -//  EnterCriticalSection(&ptw32_once_event_lock);    if (InterlockedExchangeAdd((LPLONG)&once_control->event, 0L)) /* MBR fence */      {        int lasterror = GetLastError (); @@ -129,7 +127,6 @@ ptw32_once_init_routine_cleanup(void * arg)  	  WSASetLastError (lastWSAerror);  	}      } -//  LeaveCriticalSection(&ptw32_once_event_lock);  } @@ -228,7 +225,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  	       * so we will not be starved by any other threads that may now be looping  	       * around.  	       */ -//	      EnterCriticalSection(&ptw32_once_event_lock);  	      if (InterlockedExchangeAdd((LPLONG)&once_control->event, 0L)) /* MBR fence */  		{  		  if (!ResetEvent(once_control->event)) @@ -236,7 +232,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  		      restoreLastError = PTW32_TRUE;  		    }  		} -//	      LeaveCriticalSection(&ptw32_once_event_lock);  	      /*  	       * Any threads entering the wait section and getting out again before @@ -302,7 +297,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  	   * while waiting, create an event to wait on  	   */ -//	  EnterCriticalSection(&ptw32_once_event_lock);  	  if (1 == InterlockedIncrement((LPLONG)&once_control->eventUsers))  	    {  	      /* @@ -332,7 +326,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  		  CloseHandle(tmpEvent);  		}  	    } -//	  LeaveCriticalSection(&ptw32_once_event_lock);  	  /*  	   * Check 'state' again in case the initting thread has finished or cancelled @@ -371,7 +364,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  	    }  	  /* last one out shut off the lights */ -//	  EnterCriticalSection(&ptw32_once_event_lock);  	  if (0 == InterlockedDecrement((LPLONG)&once_control->eventUsers))  	    {  	      /* we were last */ @@ -382,7 +374,6 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  		  CloseHandle(tmpEvent);  		}  	    } -//	  LeaveCriticalSection(&ptw32_once_event_lock);  	}      } diff --git a/ptw32_processInitialize.c b/ptw32_processInitialize.c index d56cd66..d13b022 100644 --- a/ptw32_processInitialize.c +++ b/ptw32_processInitialize.c @@ -96,7 +96,6 @@ ptw32_processInitialize (void)    InitializeCriticalSection (&ptw32_cond_test_init_lock);    InitializeCriticalSection (&ptw32_rwlock_test_init_lock);    InitializeCriticalSection (&ptw32_spinlock_test_init_lock); -  InitializeCriticalSection (&ptw32_once_event_lock);    return (ptw32_processInitialized); diff --git a/ptw32_processTerminate.c b/ptw32_processTerminate.c index f80b99b..d2dfa7a 100644 --- a/ptw32_processTerminate.c +++ b/ptw32_processTerminate.c @@ -101,7 +101,6 @@ ptw32_processTerminate (void)        /*          * Destroy the global locks and other objects.         */ -      DeleteCriticalSection (&ptw32_once_event_lock);        DeleteCriticalSection (&ptw32_spinlock_test_init_lock);        DeleteCriticalSection (&ptw32_rwlock_test_init_lock);        DeleteCriticalSection (&ptw32_cond_test_init_lock); 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);      }  } diff --git a/tests/test.h b/tests/test.h index a664bb6..3132c69 100644 --- a/tests/test.h +++ b/tests/test.h @@ -47,6 +47,15 @@  #define PTW32_THREAD_NULL_ID {NULL,0} +#if defined(__MINGW32__) +#include <stdint.h> +#elif defined(__BORLANDC__) +#define int64_t ULONGLONG +#else +#define int64_t _int64 +#endif + +  char * error_string[] = {    "ZERO_or_EOK",    "EPERM",  | 
