From 1abb2a28b3947feaf38a85b59e3f3a8c03804ceb Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 28 Apr 2005 04:41:25 +0000 Subject: '' --- ChangeLog | 8 +++++++- NEWS | 6 +++--- global.c | 5 ----- implement.h | 1 - pthread_once.c | 15 +++------------ ptw32_processInitialize.c | 1 - ptw32_processTerminate.c | 1 - sem_timedwait.c | 2 +- sem_wait.c | 28 ++++++++++++++++++---------- tests/test.h | 9 +++++++++ 10 files changed, 41 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80230a7..baa6a14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-04-27 Ross Johnson + + * 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 * 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. diff --git a/NEWS b/NEWS index ee10e9b..1f8be3a 100644 --- a/NEWS +++ b/NEWS @@ -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. diff --git a/global.c b/global.c index 59cb56f..2b55422 100644 --- a/global.c +++ b/global.c @@ -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) diff --git a/sem_wait.c b/sem_wait.c index bcb17e8..05d7326 100644 --- a/sem_wait.c +++ b/sem_wait.c @@ -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 +#elif defined(__BORLANDC__) +#define int64_t ULONGLONG +#else +#define int64_t _int64 +#endif + + char * error_string[] = { "ZERO_or_EOK", "EPERM", -- cgit v1.2.3