diff --git a/include/uv.h b/include/uv.h index dd542140..8a2001b7 100644 --- a/include/uv.h +++ b/include/uv.h @@ -2219,7 +2219,7 @@ UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count); UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier); -UV_EXTERN void uv_barrier_wait(uv_barrier_t* barrier); +UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier); /* Runs a function once and only once. Concurrent calls to uv_once() with the * same guard will block all callers except one (it's unspecified which one). diff --git a/src/unix/thread.c b/src/unix/thread.c index f2ce0828..522426f6 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -399,7 +399,9 @@ void uv_barrier_destroy(uv_barrier_t* barrier) { } -void uv_barrier_wait(uv_barrier_t* barrier) { +int uv_barrier_wait(uv_barrier_t* barrier) { + int serial_thread; + uv_mutex_lock(&barrier->mutex); if (++barrier->count == barrier->n) { uv_sem_wait(&barrier->turnstile2); @@ -411,7 +413,8 @@ void uv_barrier_wait(uv_barrier_t* barrier) { uv_sem_post(&barrier->turnstile1); uv_mutex_lock(&barrier->mutex); - if (--barrier->count == 0) { + serial_thread = (--barrier->count == 0); + if (serial_thread) { uv_sem_wait(&barrier->turnstile1); uv_sem_post(&barrier->turnstile2); } @@ -419,6 +422,7 @@ void uv_barrier_wait(uv_barrier_t* barrier) { uv_sem_wait(&barrier->turnstile2); uv_sem_post(&barrier->turnstile2); + return serial_thread; } #else /* !(defined(__APPLE__) && defined(__MACH__)) */ @@ -434,10 +438,11 @@ void uv_barrier_destroy(uv_barrier_t* barrier) { } -void uv_barrier_wait(uv_barrier_t* barrier) { +int uv_barrier_wait(uv_barrier_t* barrier) { int r = pthread_barrier_wait(barrier); if (r && r != PTHREAD_BARRIER_SERIAL_THREAD) abort(); + return r == PTHREAD_BARRIER_SERIAL_THREAD; } #endif /* defined(__APPLE__) && defined(__MACH__) */ diff --git a/src/win/thread.c b/src/win/thread.c index 5178f8f9..ccc5579f 100644 --- a/src/win/thread.c +++ b/src/win/thread.c @@ -660,7 +660,9 @@ void uv_barrier_destroy(uv_barrier_t* barrier) { } -void uv_barrier_wait(uv_barrier_t* barrier) { +int uv_barrier_wait(uv_barrier_t* barrier) { + int serial_thread; + uv_mutex_lock(&barrier->mutex); if (++barrier->count == barrier->n) { uv_sem_wait(&barrier->turnstile2); @@ -672,7 +674,8 @@ void uv_barrier_wait(uv_barrier_t* barrier) { uv_sem_post(&barrier->turnstile1); uv_mutex_lock(&barrier->mutex); - if (--barrier->count == 0) { + serial_thread = (--barrier->count == 0); + if (serial_thread) { uv_sem_wait(&barrier->turnstile1); uv_sem_post(&barrier->turnstile2); } @@ -680,6 +683,7 @@ void uv_barrier_wait(uv_barrier_t* barrier) { uv_sem_wait(&barrier->turnstile2); uv_sem_post(&barrier->turnstile2); + return serial_thread; } diff --git a/test/test-barrier.c b/test/test-barrier.c index 97df704c..dfd2dbde 100644 --- a/test/test-barrier.c +++ b/test/test-barrier.c @@ -29,6 +29,8 @@ typedef struct { uv_barrier_t barrier; int delay; volatile int posted; + int main_barrier_wait_rval; + int worker_barrier_wait_rval; } worker_config; @@ -38,7 +40,7 @@ static void worker(void* arg) { if (c->delay) uv_sleep(c->delay); - uv_barrier_wait(&c->barrier); + c->worker_barrier_wait_rval = uv_barrier_wait(&c->barrier); } @@ -52,11 +54,13 @@ TEST_IMPL(barrier_1) { ASSERT(0 == uv_thread_create(&thread, worker, &wc)); uv_sleep(100); - uv_barrier_wait(&wc.barrier); + wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier); ASSERT(0 == uv_thread_join(&thread)); uv_barrier_destroy(&wc.barrier); + ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval)); + return 0; } @@ -71,11 +75,13 @@ TEST_IMPL(barrier_2) { ASSERT(0 == uv_barrier_init(&wc.barrier, 2)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_barrier_wait(&wc.barrier); + wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier); ASSERT(0 == uv_thread_join(&thread)); uv_barrier_destroy(&wc.barrier); + ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval)); + return 0; } @@ -89,10 +95,12 @@ TEST_IMPL(barrier_3) { ASSERT(0 == uv_barrier_init(&wc.barrier, 2)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_barrier_wait(&wc.barrier); + wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier); ASSERT(0 == uv_thread_join(&thread)); uv_barrier_destroy(&wc.barrier); + ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval)); + return 0; }