LibC: Implement pthread_barrier
This is not fully working but should be fine for most cases
This commit is contained in:
parent
60cb392e97
commit
2a5921b9c9
|
@ -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; };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue