diff --git a/userspace/libraries/LibC/include/bits/types/pthread_types.h b/userspace/libraries/LibC/include/bits/types/pthread_types.h index e538b24c..f44dd298 100644 --- a/userspace/libraries/LibC/include/bits/types/pthread_types.h +++ b/userspace/libraries/LibC/include/bits/types/pthread_types.h @@ -28,17 +28,6 @@ typedef struct unsigned lock_depth; } pthread_mutex_t; -typedef struct -{ - int shared; -} pthread_barrierattr_t; -typedef struct -{ - pthread_barrierattr_t attr; - unsigned target; - unsigned waiting; -} pthread_barrier_t; - typedef struct { int clock; @@ -56,6 +45,20 @@ typedef struct struct _pthread_cond_block* block_list; } pthread_cond_t; +typedef struct +{ + int shared; +} pthread_barrierattr_t; +typedef struct +{ + pthread_barrierattr_t attr; + pthread_mutex_t lock; + pthread_cond_t cond; + unsigned target; + unsigned waiting; + unsigned generation; +} pthread_barrier_t; + typedef struct { int shared; diff --git a/userspace/libraries/LibC/pthread.cpp b/userspace/libraries/LibC/pthread.cpp index c60b758b..d89c1da6 100644 --- a/userspace/libraries/LibC/pthread.cpp +++ b/userspace/libraries/LibC/pthread.cpp @@ -1238,28 +1238,34 @@ int pthread_barrier_init(pthread_barrier_t* __restrict barrier, const pthread_ba attr = &default_attr; *barrier = { .attr = *attr, + .lock = PTHREAD_MUTEX_INITIALIZER, + .cond = PTHREAD_COND_INITIALIZER, .target = count, .waiting = 0, + .generation = 0, }; return 0; } int pthread_barrier_wait(pthread_barrier_t* barrier) { - const unsigned index = BAN::atomic_add_fetch(barrier->waiting, 1); + pthread_mutex_lock(&barrier->lock); - // FIXME: this case should be handled, but should be relatively uncommon - // so i'll just roll with the easy implementation - ASSERT(index <= barrier->target); + const auto gen = barrier->generation; + barrier->waiting++; - if (index == barrier->target) + if (barrier->waiting == barrier->target) { - BAN::atomic_store(barrier->waiting, 0); + barrier->waiting = 0; + barrier->generation++; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->lock); return PTHREAD_BARRIER_SERIAL_THREAD; } - while (BAN::atomic_load(barrier->waiting)) - sched_yield(); + while (barrier->generation == gen) + pthread_cond_wait(&barrier->cond, &barrier->lock); + pthread_mutex_unlock(&barrier->lock); return 0; }