#include "namespace.h"
#include <machine/tls.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include "un-namespace.h"
#include "thr_private.h"
int
_pthread_barrier_destroy(pthread_barrier_t *barrier)
{
pthread_barrier_t bar;
if (barrier == NULL || *barrier == NULL)
return (EINVAL);
bar = *barrier;
if (bar->b_waiters > 0)
return (EBUSY);
*barrier = NULL;
__free(bar);
return (0);
}
int
_pthread_barrier_init(pthread_barrier_t * __restrict barrier,
const pthread_barrierattr_t * __restrict attr __unused,
unsigned count)
{
pthread_barrier_t bar;
if (barrier == NULL || count == 0 || count > INT_MAX)
return (EINVAL);
bar = __malloc(sizeof(struct __pthread_barrier_s));
if (bar == NULL)
return (ENOMEM);
_thr_umtx_init(&bar->b_lock);
bar->b_cycle = 0;
bar->b_waiters = 0;
bar->b_count = count;
*barrier = bar;
return (0);
}
int
_pthread_barrier_wait(pthread_barrier_t *barrier)
{
pthread_t curthread;
pthread_barrier_t bar;
int64_t cycle;
int ret;
if (barrier == NULL || *barrier == NULL)
return (EINVAL);
bar = *barrier;
curthread = tls_get_curthread();
THR_UMTX_LOCK(curthread, &bar->b_lock);
if (++bar->b_waiters == bar->b_count) {
bar->b_waiters = 0;
bar->b_cycle++;
_thr_umtx_wake(&bar->b_cycle, 0);
THR_UMTX_UNLOCK(curthread, &bar->b_lock);
ret = PTHREAD_BARRIER_SERIAL_THREAD;
} else {
cycle = bar->b_cycle;
THR_UMTX_UNLOCK(curthread, &bar->b_lock);
do {
_thr_umtx_wait(&bar->b_cycle, cycle, NULL, 0);
} while (cycle == bar->b_cycle);
ret = 0;
}
return (ret);
}
__strong_reference(_pthread_barrier_init, pthread_barrier_init);
__strong_reference(_pthread_barrier_wait, pthread_barrier_wait);
__strong_reference(_pthread_barrier_destroy, pthread_barrier_destroy);