summaryrefslogtreecommitdiff
path: root/barrier.c
diff options
context:
space:
mode:
Diffstat (limited to 'barrier.c')
-rw-r--r--barrier.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/barrier.c b/barrier.c
index 41bcf07..6a18f25 100644
--- a/barrier.c
+++ b/barrier.c
@@ -59,23 +59,26 @@ pthread_barrier_init(pthread_barrier_t * barrier,
result = pthread_mutex_init(&(b->mtxExclusiveAccess), NULL);
if (0 != result)
{
- goto FAIL0;
- }
-
- result = sem_init(&(b->semBarrierBreeched), pshared, 0);
- if (0 != result)
- {
goto FAIL1;
}
- goto DONE;
+ b->eventBarrierBreeched = CreateEvent(NULL, /* Security attributes */
+ TRUE, /* Manual reset */
+ FALSE, /* Initially signaled */
+ NULL); /* Name */
- FAIL1:
+ if (NULL != b->eventBarrierBreeched)
+ {
+ goto DONE;
+ }
(void) pthread_mutex_destroy(&(b->mtxExclusiveAccess));
+ result = ENOMEM;
- FAIL0:
+ FAIL1:
(void) free(b);
+ b = NULL;
+ FAIL0:
DONE:
*barrier = b;
return(result);
@@ -94,7 +97,9 @@ pthread_barrier_destroy(pthread_barrier_t *barrier)
b = *barrier;
- if (0 == pthread_mutex_trylock(&(b->mtxExclusiveAccess)))
+ result = pthread_mutex_trylock(&(b->mtxExclusiveAccess));
+
+ if (0 == result)
{
/*
* FIXME!!!
@@ -105,16 +110,24 @@ pthread_barrier_destroy(pthread_barrier_t *barrier)
*/
*barrier = NULL;
- (void) sem_destroy(&(b->semBarrierBreeched));
+ result = CloseHandle(b->eventBarrierBreeched);
(void) pthread_mutex_unlock(&(b->mtxExclusiveAccess));
- (void) pthread_mutex_destroy(&(b->mtxExclusiveAccess));
- (void) free(b);
+ if (result == TRUE)
+ {
+ (void) pthread_mutex_destroy(&(b->mtxExclusiveAccess));
+ (void) free(b);
+ result = 0;
+ }
+ else
+ {
+ *barrier = b;
+ result = EINVAL;
+ }
}
return(result);
}
-
int
pthread_barrier_wait(pthread_barrier_t *barrier)
{
@@ -136,8 +149,14 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
{
b->nCurrentBarrierHeight = b->nInitialBarrierHeight;
(void) pthread_mutex_unlock(&(b->mtxExclusiveAccess));
- (void) sem_post_multiple(&(b->semBarrierBreeched),
- b->nInitialBarrierHeight);
+ /*
+ * This is a work-around for the FIXME below. We
+ * give any threads that didn't quite get to register
+ * their wait another quantum. This is temporary
+ * - there is a better way to do this.
+ */
+ Sleep(0);
+ (void) PulseEvent(b->eventBarrierBreeched);
/*
* Would be better if the first thread to return
* from this routine got this value. On a single
@@ -151,23 +170,25 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
pthread_t self;
int oldCancelState;
- (void) pthread_mutex_unlock(&(b->mtxExclusiveAccess));
-
self = pthread_self();
-
+
/*
* pthread_barrier_wait() is not a cancelation point
- * so temporarily prevent sem_wait() from being one.
+ * so temporarily prevent pthreadCancelableWait() from being one.
*/
if (self->cancelType == PTHREAD_CANCEL_DEFERRED)
{
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldCancelState);
}
- if (0 != sem_wait(&(b->semBarrierBreeched)))
- {
- result = errno;
- }
+ (void) pthread_mutex_unlock(&(b->mtxExclusiveAccess));
+
+ /* FIXME!!! It's possible for a thread to be left behind at a
+ * barrier because of the time gap between the unlock
+ * and the registration that the thread is waiting on the
+ * event.
+ */
+ result = pthreadCancelableWait(b->eventBarrierBreeched);
if (self->cancelType == PTHREAD_CANCEL_DEFERRED)
{