LibC: Implement pthread_barrier

This is not fully working but should be fine for most cases
This commit is contained in:
Bananymous 2025-04-21 19:53:38 +03:00
parent 60cb392e97
commit 2a5921b9c9
3 changed files with 80 additions and 3 deletions

View File

@ -28,8 +28,8 @@ typedef pthread_t pthread_spinlock_t;
typedef struct { int type; int shared; } pthread_mutexattr_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 struct { pthread_mutexattr_t attr; pthread_t locker; unsigned lock_depth; } pthread_mutex_t;
typedef int pthread_barrierattr_t; typedef struct { int shared; } pthread_barrierattr_t;
typedef int pthread_barrier_t; typedef struct { pthread_barrierattr_t attr; unsigned target; unsigned waiting; } pthread_barrier_t;
typedef struct { int clock; int shared; } pthread_condattr_t; typedef struct { int clock; int shared; } pthread_condattr_t;
struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; }; struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; };

View File

@ -24,7 +24,6 @@ struct uthread
uintptr_t dtv[]; uintptr_t dtv[];
}; };
#define PTHREAD_BARRIER_SERIAL_THREAD 1
#define PTHREAD_CANCEL_ASYNCHRONOUS 2 #define PTHREAD_CANCEL_ASYNCHRONOUS 2
#define PTHREAD_CANCEL_ENABLE 3 #define PTHREAD_CANCEL_ENABLE 3
#define PTHREAD_CANCEL_DEFERRED 4 #define PTHREAD_CANCEL_DEFERRED 4
@ -40,6 +39,8 @@ struct uthread
#define PTHREAD_SCOPE_PROCESS 23 #define PTHREAD_SCOPE_PROCESS 23
#define PTHREAD_SCOPE_SYSTEM 24 #define PTHREAD_SCOPE_SYSTEM 24
#define PTHREAD_BARRIER_SERIAL_THREAD 1
#define PTHREAD_ONCE_INIT 0 #define PTHREAD_ONCE_INIT 0
#define PTHREAD_PROCESS_SHARED 0 #define PTHREAD_PROCESS_SHARED 0

View File

@ -818,6 +818,82 @@ int pthread_cond_timedwait(pthread_cond_t* __restrict cond, pthread_mutex_t* __r
return 0; 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 #if not __disable_thread_local_storage
struct tls_index struct tls_index
{ {