instrumented_mutex.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #pragma once
  6. #include "monitoring/statistics_impl.h"
  7. #include "port/port.h"
  8. #include "rocksdb/statistics.h"
  9. #include "rocksdb/system_clock.h"
  10. #include "rocksdb/thread_status.h"
  11. #include "util/stop_watch.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. class InstrumentedCondVar;
  14. // A wrapper class for port::Mutex that provides additional layer
  15. // for collecting stats and instrumentation.
  16. class InstrumentedMutex {
  17. public:
  18. explicit InstrumentedMutex(bool adaptive = false)
  19. : mutex_(adaptive), stats_(nullptr), clock_(nullptr), stats_code_(0) {}
  20. explicit InstrumentedMutex(SystemClock* clock, bool adaptive = false)
  21. : mutex_(adaptive), stats_(nullptr), clock_(clock), stats_code_(0) {}
  22. InstrumentedMutex(Statistics* stats, SystemClock* clock, int stats_code,
  23. bool adaptive = false)
  24. : mutex_(adaptive),
  25. stats_(stats),
  26. clock_(clock),
  27. stats_code_(stats_code) {}
  28. #ifdef COERCE_CONTEXT_SWITCH
  29. InstrumentedMutex(Statistics* stats, SystemClock* clock, int stats_code,
  30. InstrumentedCondVar* bg_cv, bool adaptive = false)
  31. : mutex_(adaptive),
  32. stats_(stats),
  33. clock_(clock),
  34. stats_code_(stats_code),
  35. bg_cv_(bg_cv) {}
  36. #endif
  37. void Lock();
  38. void Unlock() { mutex_.Unlock(); }
  39. void AssertHeld() const { mutex_.AssertHeld(); }
  40. private:
  41. void LockInternal();
  42. friend class InstrumentedCondVar;
  43. port::Mutex mutex_;
  44. Statistics* stats_;
  45. SystemClock* clock_;
  46. int stats_code_;
  47. #ifdef COERCE_CONTEXT_SWITCH
  48. InstrumentedCondVar* bg_cv_ = nullptr;
  49. #endif
  50. };
  51. class ALIGN_AS(CACHE_LINE_SIZE) CacheAlignedInstrumentedMutex
  52. : public InstrumentedMutex {
  53. using InstrumentedMutex::InstrumentedMutex;
  54. };
  55. static_assert(alignof(CacheAlignedInstrumentedMutex) != CACHE_LINE_SIZE ||
  56. sizeof(CacheAlignedInstrumentedMutex) % CACHE_LINE_SIZE == 0);
  57. // RAII wrapper for InstrumentedMutex
  58. class InstrumentedMutexLock {
  59. public:
  60. explicit InstrumentedMutexLock(InstrumentedMutex* mutex) : mutex_(mutex) {
  61. mutex_->Lock();
  62. }
  63. ~InstrumentedMutexLock() { mutex_->Unlock(); }
  64. private:
  65. InstrumentedMutex* const mutex_;
  66. InstrumentedMutexLock(const InstrumentedMutexLock&) = delete;
  67. void operator=(const InstrumentedMutexLock&) = delete;
  68. };
  69. // RAII wrapper for temporary releasing InstrumentedMutex inside
  70. // InstrumentedMutexLock
  71. class InstrumentedMutexUnlock {
  72. public:
  73. explicit InstrumentedMutexUnlock(InstrumentedMutex* mutex) : mutex_(mutex) {
  74. mutex_->Unlock();
  75. }
  76. ~InstrumentedMutexUnlock() { mutex_->Lock(); }
  77. private:
  78. InstrumentedMutex* const mutex_;
  79. InstrumentedMutexUnlock(const InstrumentedMutexUnlock&) = delete;
  80. void operator=(const InstrumentedMutexUnlock&) = delete;
  81. };
  82. class InstrumentedCondVar {
  83. public:
  84. explicit InstrumentedCondVar(InstrumentedMutex* instrumented_mutex)
  85. : cond_(&(instrumented_mutex->mutex_)),
  86. stats_(instrumented_mutex->stats_),
  87. clock_(instrumented_mutex->clock_),
  88. stats_code_(instrumented_mutex->stats_code_) {}
  89. void Wait();
  90. bool TimedWait(uint64_t abs_time_us);
  91. void Signal() { cond_.Signal(); }
  92. void SignalAll() { cond_.SignalAll(); }
  93. private:
  94. void WaitInternal();
  95. bool TimedWaitInternal(uint64_t abs_time_us);
  96. port::CondVar cond_;
  97. Statistics* stats_;
  98. SystemClock* clock_;
  99. int stats_code_;
  100. };
  101. } // namespace ROCKSDB_NAMESPACE