/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "barrier.h"

#include <android-base/logging.h>

#include "base/aborting.h"
#include "base/mutex.h"
#include "base/time_utils.h"
#include "thread.h"

namespace art {

Barrier::Barrier(int count, bool verify_count_on_shutdown)
    : count_(count),
      lock_(new Mutex("GC barrier lock", kThreadSuspendCountLock)),
      condition_(new ConditionVariable("GC barrier condition", *lock_)),
      verify_count_on_shutdown_(verify_count_on_shutdown) {
}

template void Barrier::Increment<Barrier::kAllowHoldingLocks>(Thread* self, int delta);
template void Barrier::Increment<Barrier::kDisallowHoldingLocks>(Thread* self, int delta);

void Barrier::Pass(Thread* self) {
  MutexLock mu(self, *GetLock());
  SetCountLocked(self, count_ - 1);
}

void Barrier::IncrementNoWait(Thread* self) {
  MutexLock mu(self, *GetLock());
  SetCountLocked(self, count_ + 1);
}

void Barrier::Wait(Thread* self) {
  Increment(self, -1);
}

void Barrier::Init(Thread* self, int count) {
  MutexLock mu(self, *GetLock());
  SetCountLocked(self, count);
}

template <Barrier::LockHandling locks>
void Barrier::Increment(Thread* self, int delta) {
  MutexLock mu(self, *GetLock());
  SetCountLocked(self, count_ + delta);

  // Increment the count.  If it becomes zero after the increment
  // then all the threads have already passed the barrier.  If
  // it is non-zero then there is still one or more threads
  // that have not yet called the Pass function.  When the
  // Pass function is called by the last thread, the count will
  // be decremented to zero and a Broadcast will be made on the
  // condition variable, thus waking this up.
  while (count_ != 0) {
    if (locks == kAllowHoldingLocks) {
      condition_->WaitHoldingLocks(self);
    } else {
      condition_->Wait(self);
    }
  }
}

bool Barrier::Increment(Thread* self, int delta, uint32_t timeout_ms) {
  MutexLock mu(self, *GetLock());
  SetCountLocked(self, count_ + delta);
  bool timed_out = false;
  if (count_ != 0) {
    uint32_t timeout_ns = 0;
    uint64_t abs_timeout = NanoTime() + MsToNs(timeout_ms);
    for (;;) {
      timed_out = condition_->TimedWait(self, timeout_ms, timeout_ns);
      if (timed_out || count_ == 0) return timed_out;
      // Compute time remaining on timeout.
      uint64_t now = NanoTime();
      int64_t time_left = abs_timeout - now;
      if (time_left <= 0) return true;
      timeout_ns = time_left % (1000*1000);
      timeout_ms = time_left / (1000*1000);
    }
  }
  return timed_out;
}

int Barrier::GetCount(Thread* self) {
  MutexLock mu(self, *GetLock());
  return count_;
}

void Barrier::SetCountLocked(Thread* self, int count) {
  count_ = count;
  if (count == 0) {
    condition_->Broadcast(self);
  }
}

Barrier::~Barrier() {
  if (count_ != 0) {
    // Only check when not aborting and if we verify the count on shutdown.
    LOG((gAborting == 0 && verify_count_on_shutdown_) ? FATAL : WARNING)
        << "Attempted to destroy barrier with non zero count " << count_;
  }
}

}  // namespace art
