/*
 * Copyright (C) 2011 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 "mutex.h"

#include <errno.h>

#include "logging.h"
#include "runtime.h"
#include "thread.h"
#include "utils.h"

#if defined(__APPLE__)
#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
#endif

#define CHECK_MUTEX_CALL(call, args) CHECK_PTHREAD_CALL(call, args, name_)

extern int pthread_mutex_lock(pthread_mutex_t* mutex) EXCLUSIVE_LOCK_FUNCTION(mutex);
extern int pthread_mutex_unlock(pthread_mutex_t* mutex) UNLOCK_FUNCTION(1);
extern int pthread_mutex_trylock(pthread_mutex_t* mutex) EXCLUSIVE_TRYLOCK_FUNCTION(0, mutex);

namespace art {

// This works on Mac OS 10.7, but hasn't been tested on older releases.
struct __attribute__((__may_alias__)) darwin_pthread_mutex_t {
  uint32_t padding0[2];
  uint32_t value;
  uint32_t padding1[5];
  uint64_t owner_tid;
  // ...other stuff we don't care about.
};

struct __attribute__((__may_alias__)) glibc_pthread_mutex_t {
  int lock;
  unsigned int count;
  int owner;
  // ...other stuff we don't care about.
};

static inline void CheckSafeToLockOrUnlock(MutexRank rank, bool is_locking) {
  if (!kIsDebugBuild) {
    return;
  }
  if (rank == -1) {
    return;
  }
  Thread::Current()->CheckSafeToLockOrUnlock(rank, is_locking);
}

static inline void CheckSafeToWait(MutexRank rank) {
  if (!kIsDebugBuild) {
    return;
  }
  Thread::Current()->CheckSafeToWait(rank);
}

Mutex::Mutex(const char* name, MutexRank rank) : name_(name), rank_(rank) {
  // Like Java, we use recursive mutexes.
  pthread_mutexattr_t attributes;
  CHECK_MUTEX_CALL(pthread_mutexattr_init, (&attributes));
  CHECK_MUTEX_CALL(pthread_mutexattr_settype, (&attributes, PTHREAD_MUTEX_RECURSIVE));
  CHECK_MUTEX_CALL(pthread_mutex_init, (&mutex_, &attributes));
  CHECK_MUTEX_CALL(pthread_mutexattr_destroy, (&attributes));
}

Mutex::~Mutex() {
  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
  // may still be using locks.
  int rc = pthread_mutex_destroy(&mutex_);
  if (rc != 0) {
    errno = rc;
    // TODO: should we just not log at all if shutting down? this could be the logging mutex!
    bool shutting_down = Runtime::Current()->IsShuttingDown();
    PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
  }
}

void Mutex::Lock() {
  CheckSafeToLockOrUnlock(rank_, true);
  CHECK_MUTEX_CALL(pthread_mutex_lock, (&mutex_));
  AssertHeld();
}

bool Mutex::TryLock() {
  int result = pthread_mutex_trylock(&mutex_);
  if (result == EBUSY) {
    return false;
  }
  if (result != 0) {
    errno = result;
    PLOG(FATAL) << "pthread_mutex_trylock failed for " << name_;
  }
  CheckSafeToLockOrUnlock(rank_, true);
  AssertHeld();
  return true;
}

void Mutex::Unlock() {
  AssertHeld();
  CheckSafeToLockOrUnlock(rank_, false);
  CHECK_MUTEX_CALL(pthread_mutex_unlock, (&mutex_));
}

#if !defined(NDEBUG)
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1060
// Mac OS 10.5 didn't have anything we could implement GetTid() with. One thing we could try would
// be using pthread_t instead of the actual tid; this would be acceptable in most places, and more
// portable. 10.5 is already obsolete, though, so doing so would probably be all pain for no gain.
void Mutex::AssertHeld() {}
void Mutex::AssertNotHeld() {}
#else
void Mutex::AssertHeld() {
  DCHECK_EQ(GetOwner(), static_cast<uint64_t>(GetTid()));
}

void Mutex::AssertNotHeld() {
  DCHECK_NE(GetOwner(), static_cast<uint64_t>(GetTid()));
}
#endif
#endif

uint64_t Mutex::GetOwner() {
#if defined(__BIONIC__)
  return static_cast<uint64_t>((mutex_.value >> 16) & 0xffff);
#elif defined(__GLIBC__)
  return reinterpret_cast<glibc_pthread_mutex_t*>(&mutex_)->owner;
#elif defined(__APPLE__)
  return reinterpret_cast<darwin_pthread_mutex_t*>(&mutex_)->owner_tid;
#else
#error unsupported C library
#endif
}

uint32_t Mutex::GetDepth() {
  bool held = (GetOwner() == static_cast<uint64_t>(GetTid()));
  if (!held) {
    return 0;
  }
  uint32_t depth;
#if defined(__BIONIC__)
  depth = static_cast<uint32_t>((mutex_.value >> 2) & 0x7ff) + 1;
#elif defined(__GLIBC__)
  depth = reinterpret_cast<glibc_pthread_mutex_t*>(&mutex_)->count;
#elif defined(__APPLE__)
  darwin_pthread_mutex_t* darwin_mutex = reinterpret_cast<darwin_pthread_mutex_t*>(&mutex_);
  depth = ((darwin_mutex->value >> 16) & 0xffff);
#else
#error unsupported C library
#endif
  CHECK_NE(depth, 0U) << "owner=" << GetOwner() << " tid=" << GetTid();
  return depth;
}

ConditionVariable::ConditionVariable(const std::string& name) : name_(name) {
  CHECK_MUTEX_CALL(pthread_cond_init, (&cond_, NULL));
}

ConditionVariable::~ConditionVariable() {
  // We can't use CHECK_MUTEX_CALL here because on shutdown a suspended daemon thread
  // may still be using condition variables.
  int rc = pthread_cond_destroy(&cond_);
  if (rc != 0) {
    errno = rc;
    bool shutting_down = Runtime::Current()->IsShuttingDown();
    PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_;
  }
}

void ConditionVariable::Broadcast() {
  CHECK_MUTEX_CALL(pthread_cond_broadcast, (&cond_));
}

void ConditionVariable::Signal() {
  CHECK_MUTEX_CALL(pthread_cond_signal, (&cond_));
}

void ConditionVariable::Wait(Mutex& mutex) {
  CheckSafeToWait(mutex.rank_);
  uint unlock_depth = UnlockBeforeWait(mutex);
  CHECK_MUTEX_CALL(pthread_cond_wait, (&cond_, &mutex.mutex_));
  RelockAfterWait(mutex, unlock_depth);
}

void ConditionVariable::TimedWait(Mutex& mutex, const timespec& ts) {
#ifdef HAVE_TIMEDWAIT_MONOTONIC
#define TIMEDWAIT pthread_cond_timedwait_monotonic
#else
#define TIMEDWAIT pthread_cond_timedwait
#endif
  CheckSafeToWait(mutex.rank_);
  uint unlock_depth = UnlockBeforeWait(mutex);
  int rc = TIMEDWAIT(&cond_, &mutex.mutex_, &ts);
  RelockAfterWait(mutex, unlock_depth);
  if (rc != 0 && rc != ETIMEDOUT) {
    errno = rc;
    PLOG(FATAL) << "TimedWait failed for " << name_;
  }
}

// Unlock a mutex down to depth == 1 so pthread conditional waiting can be used.
// After waiting, use RelockAfterWait to restore the lock depth.
uint32_t ConditionVariable::UnlockBeforeWait(Mutex& mutex) {
  uint32_t unlock_count = 0;
  CHECK_GT(mutex.GetDepth(), 0U);
  while (mutex.GetDepth() != 1) {
    mutex.Unlock();
    unlock_count++;
  }
  return unlock_count;
}

void ConditionVariable::RelockAfterWait(Mutex& mutex, uint32_t unlock_count) {
  for (uint32_t i = 0; i < unlock_count; i++) {
    mutex.Lock();
  }
}

}  // namespace art
