diff options
Diffstat (limited to 'barrier.c')
-rw-r--r-- | barrier.c | 69 |
1 files changed, 45 insertions, 24 deletions
@@ -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) { |