// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
//
// Portions (c) 2011 The Chromium Authors.

#include "kudu/util/mutex.h"

#include <cerrno>
#include <cstdint>
#include <cstring>
#include <ostream>
#include <string>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "kudu/gutil/port.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/gutil/walltime.h"
#include "kudu/util/debug-util.h"
#include "kudu/util/env.h"
#include "kudu/util/flag_tags.h"
#include "kudu/util/trace.h"

using std::string;
using strings::Substitute;
using strings::SubstituteAndAppend;

#ifndef NDEBUG
DEFINE_bool(debug_mutex_collect_stacktrace, false,
            "Whether to collect a stacktrace on Mutex contention in a DEBUG build");
TAG_FLAG(debug_mutex_collect_stacktrace, advanced);
TAG_FLAG(debug_mutex_collect_stacktrace, hidden);
#endif

namespace kudu {

Mutex::Mutex()
#ifndef NDEBUG
  : owning_tid_(0),
    stack_trace_(new StackTrace())
#endif
{
#ifndef NDEBUG
  // In debug, setup attributes for lock error checking.
  pthread_mutexattr_t mta;
  int rv = pthread_mutexattr_init(&mta);
  DCHECK_EQ(0, rv) << ". " << strerror(rv);
  rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
  DCHECK_EQ(0, rv) << ". " << strerror(rv);
  rv = pthread_mutex_init(&native_handle_, &mta);
  DCHECK_EQ(0, rv) << ". " << strerror(rv);
  rv = pthread_mutexattr_destroy(&mta);
  DCHECK_EQ(0, rv) << ". " << strerror(rv);
#else
  // In release, go with the default lock attributes.
  pthread_mutex_init(&native_handle_, NULL);
#endif
}

Mutex::~Mutex() {
  int rv = pthread_mutex_destroy(&native_handle_);
  DCHECK_EQ(0, rv) << ". " << strerror(rv);
}

bool Mutex::TryAcquire() {
  int rv = pthread_mutex_trylock(&native_handle_);
#ifndef NDEBUG
  DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv) << ". " << GetOwnerThreadInfo();
  if (rv == 0) {
    CheckUnheldAndMark();
  }
#endif
  return rv == 0;
}

void Mutex::Acquire() {
  // Optimize for the case when mutexes are uncontended. If they
  // are contended, we'll have to go to sleep anyway, so the extra
  // cost of branch mispredictions is moot.
  //
  // TryAcquire() is implemented as a simple CompareAndSwap inside
  // pthreads so this does not require a system call.
  if (PREDICT_TRUE(TryAcquire())) {
    return;
  }

  // If we weren't able to acquire the mutex immediately, then it's
  // worth gathering timing information about the mutex acquisition.
  MicrosecondsInt64 start_time = GetMonoTimeMicros();
  int rv = pthread_mutex_lock(&native_handle_);
  DCHECK_EQ(0, rv) << ". " << strerror(rv)
#ifndef NDEBUG
                   << ". " << GetOwnerThreadInfo()
#endif
  ; // NOLINT(whitespace/semicolon)
  MicrosecondsInt64 end_time = GetMonoTimeMicros();

  int64_t wait_time = end_time - start_time;
  if (wait_time > 0) {
    TRACE_COUNTER_INCREMENT("mutex_wait_us", wait_time);
  }

#ifndef NDEBUG
  CheckUnheldAndMark();
#endif
}

void Mutex::Release() {
#ifndef NDEBUG
  CheckHeldAndUnmark();
#endif
  int rv = pthread_mutex_unlock(&native_handle_);
  DCHECK_EQ(0, rv) << ". " << strerror(rv);
}

#ifndef NDEBUG
void Mutex::AssertAcquired() const {
  DCHECK_EQ(Env::Default()->gettid(), owning_tid_);
}

void Mutex::CheckHeldAndUnmark() {
  AssertAcquired();
  owning_tid_ = 0;
  if (FLAGS_debug_mutex_collect_stacktrace) {
    stack_trace_->Reset();
  }
}

void Mutex::CheckUnheldAndMark() {
  DCHECK_EQ(0, owning_tid_);
  owning_tid_ = Env::Default()->gettid();
  if (FLAGS_debug_mutex_collect_stacktrace) {
    stack_trace_->Collect();
  }
}

string Mutex::GetOwnerThreadInfo() const {
  string str = Substitute("Owner tid: $0; Self tid: $1; ", owning_tid_, Env::Default()->gettid());
  if (FLAGS_debug_mutex_collect_stacktrace) {
    SubstituteAndAppend(&str, "Owner stack:\n$0", stack_trace_->Symbolize());
  } else {
    str += "To collect the owner stack trace, enable the flag --debug_mutex_collect_stacktrace";
  }
  return str;
}

#endif

} // namespace kudu
