From 2a5921b9c98a7ebf3b086ef11d836cf188ea1f42 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 21 Apr 2025 19:53:38 +0300 Subject: [PATCH] LibC: Implement pthread_barrier This is not fully working but should be fine for most cases --- .../LibC/include/bits/pthread_types.h | 4 +- userspace/libraries/LibC/include/pthread.h | 3 +- userspace/libraries/LibC/pthread.cpp | 76 +++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/userspace/libraries/LibC/include/bits/pthread_types.h b/userspace/libraries/LibC/include/bits/pthread_types.h index 084a847c..8d1dfa4d 100644 --- a/userspace/libraries/LibC/include/bits/pthread_types.h +++ b/userspace/libraries/LibC/include/bits/pthread_types.h @@ -28,8 +28,8 @@ typedef pthread_t pthread_spinlock_t; typedef struct { int type; int shared; } pthread_mutexattr_t; typedef struct { pthread_mutexattr_t attr; pthread_t locker; unsigned lock_depth; } pthread_mutex_t; -typedef int pthread_barrierattr_t; -typedef int pthread_barrier_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; int shared; } pthread_condattr_t; struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; }; diff --git a/userspace/libraries/LibC/include/pthread.h b/userspace/libraries/LibC/include/pthread.h index ae8ebcfc..c4801805 100644 --- a/userspace/libraries/LibC/include/pthread.h +++ b/userspace/libraries/LibC/include/pthread.h @@ -24,7 +24,6 @@ struct uthread uintptr_t dtv[]; }; -#define PTHREAD_BARRIER_SERIAL_THREAD 1 #define PTHREAD_CANCEL_ASYNCHRONOUS 2 #define PTHREAD_CANCEL_ENABLE 3 #define PTHREAD_CANCEL_DEFERRED 4 @@ -40,6 +39,8 @@ struct uthread #define PTHREAD_SCOPE_PROCESS 23 #define PTHREAD_SCOPE_SYSTEM 24 +#define PTHREAD_BARRIER_SERIAL_THREAD 1 + #define PTHREAD_ONCE_INIT 0 #define PTHREAD_PROCESS_SHARED 0 diff --git a/userspace/libraries/LibC/pthread.cpp b/userspace/libraries/LibC/pthread.cpp index 4899c964..87b6125d 100644 --- a/userspace/libraries/LibC/pthread.cpp +++ b/userspace/libraries/LibC/pthread.cpp @@ -818,6 +818,82 @@ int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __r return 0; } +int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) +{ + (void)attr; + return 0; +} + +int pthread_barrierattr_init(pthread_barrierattr_t* attr) +{ + *attr = { + .shared = false, + }; + return 0; +} + +int pthread_barrierattr_getpshared(const pthread_barrierattr_t* __restrict attr, int* __restrict pshared) +{ + *pshared = attr->shared ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) +{ + switch (pshared) + { + case PTHREAD_PROCESS_PRIVATE: + attr->shared = false; + return 0; + case PTHREAD_PROCESS_SHARED: + attr->shared = true; + return 0; + } + return EINVAL; +} + +int pthread_barrier_destroy(pthread_barrier_t* barrier) +{ + (void)barrier; + return 0; +} + +int pthread_barrier_init(pthread_barrier_t* __restrict barrier, const pthread_barrierattr_t* __restrict attr, unsigned count) +{ + if (count == 0) + return EINVAL; + const pthread_barrierattr_t default_attr = { + .shared = false, + }; + if (attr == nullptr) + attr = &default_attr; + *barrier = { + .attr = *attr, + .target = count, + .waiting = 0, + }; + return 0; +} + +int pthread_barrier_wait(pthread_barrier_t* barrier) +{ + const unsigned index = BAN::atomic_add_fetch(barrier->waiting, 1); + + // FIXME: this case should be handled, but should be relatively uncommon + // so i'll just roll with the easy implementation + ASSERT(index <= barrier->target); + + if (index == barrier->target) + { + BAN::atomic_store(barrier->waiting, 0); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + + while (BAN::atomic_load(barrier->waiting)) + sched_yield(); + return 0; +} + #if not __disable_thread_local_storage struct tls_index {