brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.1 KiB · cf7207b Raw
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