summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--NEWS6
-rw-r--r--global.c5
-rw-r--r--implement.h1
-rw-r--r--pthread_once.c15
-rw-r--r--ptw32_processInitialize.c1
-rw-r--r--ptw32_processTerminate.c1
-rw-r--r--sem_timedwait.c2
-rw-r--r--sem_wait.c28
-rw-r--r--tests/test.h9
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 <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.
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 <stdint.h>
+#elif defined(__BORLANDC__)
+#define int64_t ULONGLONG
+#else
+#define int64_t _int64
+#endif
+
+
char * error_string[] = {
"ZERO_or_EOK",
"EPERM",