/*
 * Copyright (C) 2015 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>

#include "private/bionic_futex.h"

int pthread_barrierattr_init(pthread_barrierattr_t* attr) {
  *attr = 0;
  return 0;
}

int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) {
  *attr = 0;
  return 0;
}

int pthread_barrierattr_getpshared(const pthread_barrierattr_t* attr, int* pshared) {
  *pshared = (*attr & 1) ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE;
  return 0;
}

int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) {
  if (pshared == PTHREAD_PROCESS_SHARED) {
    *attr |= 1;
  } else {
    *attr &= ~1;
  }
  return 0;
}

enum BarrierState {
  WAIT,
  RELEASE,
};

struct pthread_barrier_internal_t {
  // One barrier can be used for unlimited number of cycles. In each cycle, [init_count]
  // threads must call pthread_barrier_wait() before any of them successfully return from
  // the call. It is undefined behavior if there are more than [init_count] threads call
  // pthread_barrier_wait() in one cycle.
  uint32_t init_count;
  // Barrier state. It is WAIT if waiting for more threads to enter the barrier in this cycle,
  // otherwise threads are leaving the barrier.
  _Atomic(BarrierState) state;
  // Number of threads having entered but not left the barrier in this cycle.
  atomic_uint wait_count;
  // Whether the barrier is shared across processes.
  bool pshared;
  uint32_t __reserved[4];
};

static_assert(sizeof(pthread_barrier_t) == sizeof(pthread_barrier_internal_t),
              "pthread_barrier_t should actually be pthread_barrier_internal_t in implementation."
              );

static_assert(alignof(pthread_barrier_t) >= 4,
              "pthread_barrier_t should fulfill the alignment of pthread_barrier_internal_t.");

static inline pthread_barrier_internal_t* __get_internal_barrier(pthread_barrier_t* barrier) {
  return reinterpret_cast<pthread_barrier_internal_t*>(barrier);
}

int pthread_barrier_init(pthread_barrier_t* barrier_interface, const pthread_barrierattr_t* attr,
                         unsigned count) {
  pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
  if (count == 0) {
    return EINVAL;
  }
  barrier->init_count = count;
  atomic_init(&barrier->state, WAIT);
  atomic_init(&barrier->wait_count, 0);
  barrier->pshared = false;
  if (attr != nullptr && (*attr & 1)) {
    barrier->pshared = true;
  }
  return 0;
}

// According to POSIX standard, pthread_barrier_wait() synchronizes memory between participating
// threads. It means all memory operations made by participating threads before calling
// pthread_barrier_wait() can be seen by all participating threads after the function call.
// We establish this by making a happens-before relation between all threads entering the barrier
// with the last thread entering the barrier, and a happens-before relation between the last
// thread entering the barrier with all threads leaving the barrier.
int pthread_barrier_wait(pthread_barrier_t* barrier_interface) {
  pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);

  // Wait until all threads for the previous cycle have left the barrier. This is needed
  // as a participating thread can call pthread_barrier_wait() again before other
  // threads have left the barrier. Use acquire operation here to synchronize with
  // the last thread leaving the previous cycle, so we can read correct wait_count below.
  while(atomic_load_explicit(&barrier->state, memory_order_acquire) == RELEASE) {
    __futex_wait_ex(&barrier->state, barrier->pshared, RELEASE, false, nullptr);
  }

  uint32_t prev_wait_count = atomic_load_explicit(&barrier->wait_count, memory_order_relaxed);
  while (true) {
    // It happens when there are more than [init_count] threads trying to enter the barrier
    // at one cycle. We read the POSIX standard as disallowing this, since additional arriving
    // threads are not synchronized with respect to the barrier reset. We also don't know of
    // any reasonable cases in which this would be intentional.
    if (prev_wait_count >= barrier->init_count) {
      return EINVAL;
    }
    // Use memory_order_acq_rel operation here to synchronize between all threads entering
    // the barrier with the last thread entering the barrier.
    if (atomic_compare_exchange_weak_explicit(&barrier->wait_count, &prev_wait_count,
                                              prev_wait_count + 1u, memory_order_acq_rel,
                                              memory_order_relaxed)) {
      break;
    }
  }

  int result = 0;
  if (prev_wait_count + 1 == barrier->init_count) {
    result = PTHREAD_BARRIER_SERIAL_THREAD;
    if (prev_wait_count != 0) {
      // Use release operation here to synchronize between the last thread entering the
      // barrier with all threads leaving the barrier.
      atomic_store_explicit(&barrier->state, RELEASE, memory_order_release);
      __futex_wake_ex(&barrier->state, barrier->pshared, prev_wait_count);
    }
  } else {
    // Use acquire operation here to synchronize between the last thread entering the
    // barrier with all threads leaving the barrier.
    while (atomic_load_explicit(&barrier->state, memory_order_acquire) == WAIT) {
      __futex_wait_ex(&barrier->state, barrier->pshared, WAIT, false, nullptr);
    }
  }
  // Use release operation here to make it not reordered with previous operations.
  if (atomic_fetch_sub_explicit(&barrier->wait_count, 1, memory_order_release) == 1) {
    // Use release operation here to synchronize with threads entering the barrier for
    // the next cycle, or the thread calling pthread_barrier_destroy().
    atomic_store_explicit(&barrier->state, WAIT, memory_order_release);
    __futex_wake_ex(&barrier->state, barrier->pshared, barrier->init_count);
  }
  return result;
}

int pthread_barrier_destroy(pthread_barrier_t* barrier_interface) {
  pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
  if (barrier->init_count == 0) {
    return EINVAL;
  }
  // Use acquire operation here to synchronize with the last thread leaving the barrier.
  // So we can read correct wait_count below.
  while (atomic_load_explicit(&barrier->state, memory_order_acquire) == RELEASE) {
    __futex_wait_ex(&barrier->state, barrier->pshared, RELEASE, false, nullptr);
  }
  if (atomic_load_explicit(&barrier->wait_count, memory_order_relaxed) != 0) {
    return EBUSY;
  }
  barrier->init_count = 0;
  return 0;
}
