// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/lockers.h"
#include "platform/assert.h"
#include "vm/heap/safepoint.h"
#include "vm/isolate.h"

namespace dart {

Monitor::WaitResult MonitorLocker::WaitWithSafepointCheck(Thread* thread,
                                                          int64_t millis) {
  ASSERT(thread == Thread::Current());
  ASSERT(thread->execution_state() == Thread::kThreadInVM);
#if defined(DEBUG)
  if (no_safepoint_scope_) {
    thread->DecrementNoSafepointScopeDepth();
  }
#endif
  thread->set_execution_state(Thread::kThreadInBlockedState);
  thread->EnterSafepoint();
  Monitor::WaitResult result = monitor_->Wait(millis);
  // First try a fast update of the thread state to indicate it is not at a
  // safepoint anymore.
  if (!thread->TryExitSafepoint()) {
    // Fast update failed which means we could potentially be in the middle
    // of a safepoint operation and need to block for it.
    monitor_->Exit();
    SafepointHandler* handler = thread->isolate_group()->safepoint_handler();
    handler->ExitSafepointUsingLock(thread);
    monitor_->Enter();
  }
  thread->set_execution_state(Thread::kThreadInVM);
#if defined(DEBUG)
  if (no_safepoint_scope_) {
    thread->IncrementNoSafepointScopeDepth();
  }
#endif
  return result;
}

SafepointMutexLocker::SafepointMutexLocker(ThreadState* thread, Mutex* mutex)
    : StackResource(thread), mutex_(mutex) {
  ASSERT(mutex != NULL);
  if (!mutex_->TryLock()) {
    // We did not get the lock and could potentially block, so transition
    // accordingly.
    Thread* thread = Thread::Current();
    if (thread != NULL) {
      TransitionVMToBlocked transition(thread);
      mutex->Lock();
    } else {
      mutex->Lock();
    }
  }
}

SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
    : monitor_(monitor) {
  ASSERT(monitor_ != NULL);
  if (!monitor_->TryEnter()) {
    // We did not get the lock and could potentially block, so transition
    // accordingly.
    Thread* thread = Thread::Current();
    if (thread != NULL) {
      TransitionVMToBlocked transition(thread);
      monitor_->Enter();
    } else {
      monitor_->Enter();
    }
  }
}

Monitor::WaitResult SafepointMonitorLocker::Wait(int64_t millis) {
  Thread* thread = Thread::Current();
  if (thread != NULL) {
    Monitor::WaitResult result;
    {
      TransitionVMToBlocked transition(thread);
      result = monitor_->Wait(millis);
    }
    return result;
  } else {
    return monitor_->Wait(millis);
  }
}

#if defined(DEBUG)
bool SafepointRwLock::IsCurrentThreadReader() {
  ThreadId id = OSThread::GetCurrentThreadId();
  if (IsCurrentThreadWriter()) {
    return true;
  }
  MonitorLocker ml(&monitor_);
  for (intptr_t i = readers_ids_.length() - 1; i >= 0; i--) {
    if (readers_ids_.At(i) == id) {
      return true;
    }
  }
  return false;
}
#endif  // defined(DEBUG)

bool SafepointRwLock::EnterRead() {
  // No need to safepoint if the current thread is not attached.
  auto thread = Thread::Current();
  const bool can_block_without_safepoint = thread == nullptr;

  bool acquired_read_lock = false;
  if (!TryEnterRead(can_block_without_safepoint, &acquired_read_lock)) {
    // Important: must never hold monitor_ when blocking for safepoint.
    TransitionVMToBlocked transition(thread);
    const bool ok = TryEnterRead(/*can_block=*/true, &acquired_read_lock);
    RELEASE_ASSERT(ok);
    RELEASE_ASSERT(acquired_read_lock);
  }
  return acquired_read_lock;
}

bool SafepointRwLock::TryEnterRead(bool can_block, bool* acquired_read_lock) {
  MonitorLocker ml(&monitor_);
  if (IsCurrentThreadWriter()) {
    *acquired_read_lock = false;
    return true;
  }
  if (can_block) {
    while (state_ < 0) {
      ml.Wait();
    }
  }
  if (state_ >= 0) {
    ++state_;
    DEBUG_ONLY(readers_ids_.Add(OSThread::GetCurrentThreadId()));
    *acquired_read_lock = true;
    return true;
  }
  return false;
}

void SafepointRwLock::LeaveRead() {
  MonitorLocker ml(&monitor_);
  ASSERT(state_ > 0);
#if defined(DEBUG)
  {
    intptr_t i = readers_ids_.length() - 1;
    ThreadId id = OSThread::GetCurrentThreadId();
    while (i >= 0) {
      if (readers_ids_.At(i) == id) {
        readers_ids_.RemoveAt(i);
        break;
      }
      i--;
    }
    ASSERT(i >= 0);
  }
#endif
  if (--state_ == 0) {
    ml.NotifyAll();
  }
}

void SafepointRwLock::EnterWrite() {
  // No need to safepoint if the current thread is not attached.
  auto thread = Thread::Current();
  const bool can_block_without_safepoint = thread == nullptr;

  if (!TryEnterWrite(can_block_without_safepoint)) {
    // Important: must never hold monitor_ when blocking for safepoint.
    TransitionVMToBlocked transition(thread);
    const bool ok = TryEnterWrite(/*can_block=*/true);
    RELEASE_ASSERT(ok);
  }
}

bool SafepointRwLock::TryEnterWrite(bool can_block) {
  MonitorLocker ml(&monitor_);
  if (IsCurrentThreadWriter()) {
    state_--;
    return true;
  }
  if (can_block) {
    while (state_ != 0) {
      ml.Wait();
    }
  }
  if (state_ == 0) {
    writer_id_ = OSThread::GetCurrentThreadId();
    state_ = -1;
    return true;
  }
  return false;
}

void SafepointRwLock::LeaveWrite() {
  MonitorLocker ml(&monitor_);
  ASSERT(state_ < 0);
  if (++state_ < 0) {
    return;
  }
  writer_id_ = OSThread::kInvalidThreadId;
  ml.NotifyAll();
}

}  // namespace dart
