86 lines · cpp
1//===-- Implementation of Barrier class ------------- ---------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/__support/threads/linux/barrier.h"10#include "hdr/errno_macros.h"11#include "src/__support/threads/CndVar.h"12#include "src/__support/threads/mutex.h"13 14namespace LIBC_NAMESPACE_DECL {15 16int Barrier::init(Barrier *b,17 [[maybe_unused]] const pthread_barrierattr_t *attr,18 unsigned count) {19 LIBC_ASSERT(attr == nullptr); // TODO implement barrierattr20 if (count == 0)21 return EINVAL;22 23 b->expected = count;24 b->waiting = 0;25 b->blocking = true;26 27 int err;28 err = CndVar::init(&b->entering);29 if (err != 0)30 return err;31 32 err = CndVar::init(&b->exiting);33 if (err != 0)34 return err;35 36 auto mutex_err = Mutex::init(&b->m, false, false, false, false);37 if (mutex_err != MutexError::NONE)38 return EAGAIN;39 40 return 0;41}42 43int Barrier::wait() {44 m.lock();45 46 // if the barrier is emptying out threads, wait until it finishes47 while (!blocking)48 entering.wait(&m);49 waiting++;50 51 if (waiting < expected) {52 // block threads until waiting = expected53 while (blocking)54 exiting.wait(&m);55 } else {56 // this is the last thread to call wait(), so lets wake everyone up57 blocking = false;58 exiting.broadcast();59 }60 waiting--;61 62 if (waiting == 0) {63 // all threads have exited the barrier, let's let the ones waiting to enter64 // continue65 blocking = true;66 entering.broadcast();67 m.unlock();68 69 // POSIX dictates that the barrier should return a special value to just one70 // thread, so we can arbitrarily choose this thread71 return PTHREAD_BARRIER_SERIAL_THREAD;72 }73 m.unlock();74 75 return 0;76}77 78int Barrier::destroy(Barrier *b) {79 CndVar::destroy(&b->entering);80 CndVar::destroy(&b->exiting);81 Mutex::destroy(&b->m);82 return 0;83}84 85} // namespace LIBC_NAMESPACE_DECL86