#include "src/__support/threads/linux/barrier.h"
#include "hdr/errno_macros.h"
#include "src/__support/threads/CndVar.h"
#include "src/__support/threads/mutex.h"
namespace LIBC_NAMESPACE_DECL {
int Barrier::init(Barrier *b,
[[maybe_unused]] const pthread_barrierattr_t *attr,
unsigned count) {
LIBC_ASSERT(attr == nullptr);
if (count == 0)
return EINVAL;
b->expected = count;
b->waiting = 0;
b->blocking = true;
int err;
err = CndVar::init(&b->entering);
if (err != 0)
return err;
err = CndVar::init(&b->exiting);
if (err != 0)
return err;
auto mutex_err = Mutex::init(&b->m, false, false, false, false);
if (mutex_err != MutexError::NONE)
return EAGAIN;
return 0;
}
int Barrier::wait() {
m.lock();
while (!blocking)
entering.wait(&m);
waiting++;
if (waiting < expected) {
while (blocking)
exiting.wait(&m);
} else {
blocking = false;
exiting.broadcast();
}
waiting--;
if (waiting == 0) {
blocking = true;
entering.broadcast();
m.unlock();
return PTHREAD_BARRIER_SERIAL_THREAD;
}
m.unlock();
return 0;
}
int Barrier::destroy(Barrier *b) {
CndVar::destroy(&b->entering);
CndVar::destroy(&b->exiting);
Mutex::destroy(&b->m);
return 0;
}
}