// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). #include "monitoring/instrumented_mutex.h" #include "monitoring/perf_context_imp.h" #include "monitoring/thread_status_util.h" #include "util/sync_point.h" namespace rocksdb { namespace { bool ShouldReportToStats(Env* env, Statistics* stats) { return env != nullptr && stats != nullptr && stats->stats_level_ > kExceptTimeForMutex; } } // namespace void InstrumentedMutex::Lock() { PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_mutex_lock_nanos, stats_code_ == DB_MUTEX_WAIT_MICROS); uint64_t wait_time_micros = 0; if (ShouldReportToStats(env_, stats_)) { { StopWatch sw(env_, nullptr, 0, &wait_time_micros); LockInternal(); } RecordTick(stats_, stats_code_, wait_time_micros); } else { LockInternal(); } } void InstrumentedMutex::LockInternal() { #ifndef NDEBUG ThreadStatusUtil::TEST_StateDelay(ThreadStatus::STATE_MUTEX_WAIT); #endif mutex_.Lock(); } void InstrumentedCondVar::Wait() { PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_condition_wait_nanos, stats_code_ == DB_MUTEX_WAIT_MICROS); uint64_t wait_time_micros = 0; if (ShouldReportToStats(env_, stats_)) { { StopWatch sw(env_, nullptr, 0, &wait_time_micros); WaitInternal(); } RecordTick(stats_, stats_code_, wait_time_micros); } else { WaitInternal(); } } void InstrumentedCondVar::WaitInternal() { #ifndef NDEBUG ThreadStatusUtil::TEST_StateDelay(ThreadStatus::STATE_MUTEX_WAIT); #endif cond_.Wait(); } bool InstrumentedCondVar::TimedWait(uint64_t abs_time_us) { PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_condition_wait_nanos, stats_code_ == DB_MUTEX_WAIT_MICROS); uint64_t wait_time_micros = 0; bool result = false; if (ShouldReportToStats(env_, stats_)) { { StopWatch sw(env_, nullptr, 0, &wait_time_micros); result = TimedWaitInternal(abs_time_us); } RecordTick(stats_, stats_code_, wait_time_micros); } else { result = TimedWaitInternal(abs_time_us); } return result; } bool InstrumentedCondVar::TimedWaitInternal(uint64_t abs_time_us) { #ifndef NDEBUG ThreadStatusUtil::TEST_StateDelay(ThreadStatus::STATE_MUTEX_WAIT); #endif TEST_SYNC_POINT_CALLBACK("InstrumentedCondVar::TimedWaitInternal", &abs_time_us); return cond_.TimedWait(abs_time_us); } } // namespace rocksdb