sync.h raw

   1  // Copyright (c) 2009-2010 Satoshi Nakamoto
   2  // Copyright (c) 2009-present The Bitcoin Core developers
   3  // Distributed under the MIT software license, see the accompanying
   4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  #ifndef BITCOIN_SYNC_H
   7  #define BITCOIN_SYNC_H
   8  
   9  // This header declares threading primitives compatible with Clang
  10  // Thread Safety Analysis and provides appropriate annotation macros.
  11  #include <threadsafety.h> // IWYU pragma: export
  12  #include <util/macros.h>
  13  
  14  #include <cassert>
  15  #include <condition_variable>
  16  #include <mutex>
  17  #include <string>
  18  #include <thread>
  19  
  20  ////////////////////////////////////////////////
  21  //                                            //
  22  // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
  23  //                                            //
  24  ////////////////////////////////////////////////
  25  
  26  /*
  27  RecursiveMutex mutex;
  28      std::recursive_mutex mutex;
  29  
  30  LOCK(mutex);
  31      std::unique_lock<std::recursive_mutex> criticalblock(mutex);
  32  
  33  LOCK2(mutex1, mutex2);
  34      std::unique_lock<std::recursive_mutex> criticalblock1(mutex1);
  35      std::unique_lock<std::recursive_mutex> criticalblock2(mutex2);
  36  
  37  TRY_LOCK(mutex, name);
  38      std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t);
  39   */
  40  
  41  ///////////////////////////////
  42  //                           //
  43  // THE ACTUAL IMPLEMENTATION //
  44  //                           //
  45  ///////////////////////////////
  46  
  47  #ifdef DEBUG_LOCKORDER
  48  template <typename MutexType>
  49  void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false);
  50  void LeaveCritical();
  51  void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
  52  template <typename MutexType>
  53  void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
  54  template <typename MutexType>
  55  void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);
  56  void DeleteLock(void* cs);
  57  bool LockStackEmpty();
  58  
  59  /**
  60   * Call abort() if a potential lock order deadlock bug is detected, instead of
  61   * just logging information and throwing a logic_error. Defaults to true, and
  62   * set to false in DEBUG_LOCKORDER unit tests.
  63   */
  64  extern bool g_debug_lockorder_abort;
  65  #else
  66  template <typename MutexType>
  67  inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
  68  inline void LeaveCritical() {}
  69  inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
  70  template <typename MutexType>
  71  inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
  72  template <typename MutexType>
  73  void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
  74  inline void DeleteLock(void* cs) {}
  75  inline bool LockStackEmpty() { return true; }
  76  #endif
  77  
  78  /*
  79   * Called when a mutex fails to lock immediately because it is held by another
  80   * thread, or spuriously. Responsible for locking the lock before returning.
  81   */
  82  #ifdef DEBUG_LOCKCONTENTION
  83  
  84  template <typename LockType>
  85  void ContendedLock(std::string_view name, std::string_view file, int nLine, LockType& lock);
  86  #endif
  87  
  88  /**
  89   * Template mixin that adds -Wthread-safety locking annotations and lock order
  90   * checking to a subset of the mutex API.
  91   */
  92  template <typename PARENT>
  93  class LOCKABLE AnnotatedMixin : public PARENT
  94  {
  95  public:
  96      ~AnnotatedMixin() {
  97          DeleteLock((void*)this);
  98      }
  99  
 100      void lock() EXCLUSIVE_LOCK_FUNCTION()
 101      {
 102          PARENT::lock();
 103      }
 104  
 105      void unlock() UNLOCK_FUNCTION()
 106      {
 107          PARENT::unlock();
 108      }
 109  
 110      bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
 111      {
 112          return PARENT::try_lock();
 113      }
 114  
 115      using unique_lock = std::unique_lock<PARENT>;
 116  #ifdef __clang__
 117      //! For negative capabilities in the Clang Thread Safety Analysis.
 118      //! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
 119      //! with the ! operator, to indicate that a mutex should not be held.
 120      const AnnotatedMixin& operator!() const { return *this; }
 121  #endif // __clang__
 122  };
 123  
 124  /**
 125   * Wrapped mutex: supports recursive locking, but no waiting
 126   * TODO: We should move away from using the recursive lock by default.
 127   */
 128  using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
 129  
 130  /** Wrapped mutex: supports waiting but not recursive locking */
 131  using Mutex = AnnotatedMixin<std::mutex>;
 132  
 133  /** Different type to mark Mutex at global scope
 134   *
 135   * Thread safety analysis can't handle negative assertions about mutexes
 136   * with global scope well, so mark them with a separate type, and
 137   * eventually move all the mutexes into classes so they are not globally
 138   * visible.
 139   *
 140   * See: https://github.com/bitcoin/bitcoin/pull/20272#issuecomment-720755781
 141   */
 142  class GlobalMutex : public Mutex { };
 143  
 144  #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
 145  
 146  inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); }
 147  inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
 148  inline void AssertLockNotHeldInline(const char* name, const char* file, int line, GlobalMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
 149  #define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
 150  
 151  /** Wrapper around std::unique_lock style lock for MutexType. */
 152  template <typename MutexType>
 153  class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock
 154  {
 155  private:
 156      using Base = typename MutexType::unique_lock;
 157  
 158      void Enter(const char* pszName, const char* pszFile, int nLine)
 159      {
 160          EnterCritical(pszName, pszFile, nLine, Base::mutex());
 161  #ifdef DEBUG_LOCKCONTENTION
 162          if (!Base::try_lock()) {
 163              ContendedLock(pszName, pszFile, nLine, static_cast<Base&>(*this));
 164          }
 165  #else
 166          Base::lock();
 167  #endif
 168      }
 169  
 170      bool TryEnter(const char* pszName, const char* pszFile, int nLine)
 171      {
 172          EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
 173          if (Base::try_lock()) {
 174              return true;
 175          }
 176          LeaveCritical();
 177          return false;
 178      }
 179  
 180  public:
 181      UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
 182      {
 183          if (fTry)
 184              TryEnter(pszName, pszFile, nLine);
 185          else
 186              Enter(pszName, pszFile, nLine);
 187      }
 188  
 189      UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
 190      {
 191          if (!pmutexIn) return;
 192  
 193          *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
 194          if (fTry)
 195              TryEnter(pszName, pszFile, nLine);
 196          else
 197              Enter(pszName, pszFile, nLine);
 198      }
 199  
 200      ~UniqueLock() UNLOCK_FUNCTION()
 201      {
 202          if (Base::owns_lock())
 203              LeaveCritical();
 204      }
 205  
 206      operator bool()
 207      {
 208          return Base::owns_lock();
 209      }
 210  
 211  protected:
 212      // needed for reverse_lock
 213      UniqueLock() = default;
 214  
 215  public:
 216      /**
 217       * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
 218       */
 219      class SCOPED_LOCKABLE reverse_lock {
 220      public:
 221          explicit reverse_lock(UniqueLock& _lock, const MutexType& mutex, const char* _guardname, const char* _file, int _line) UNLOCK_FUNCTION(mutex) : lock(_lock), file(_file), line(_line) {
 222              // Ensure that mutex passed back for thread-safety analysis is indeed the original
 223              assert(std::addressof(mutex) == lock.mutex());
 224  
 225              CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
 226              lock.unlock();
 227              LeaveCritical();
 228              lock.swap(templock);
 229          }
 230  
 231          ~reverse_lock() UNLOCK_FUNCTION() {
 232              templock.swap(lock);
 233              EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
 234              lock.lock();
 235          }
 236  
 237       private:
 238          reverse_lock(reverse_lock const&);
 239          reverse_lock& operator=(reverse_lock const&);
 240  
 241          UniqueLock& lock;
 242          UniqueLock templock;
 243          std::string lockname;
 244          const std::string file;
 245          const int line;
 246       };
 247       friend class reverse_lock;
 248  };
 249  
 250  // clang's thread-safety analyzer is unable to deal with aliases of mutexes, so
 251  // it is not possible to use the lock's copy of the mutex for that purpose.
 252  // Instead, the original mutex needs to be passed back to the reverse_lock for
 253  // the sake of thread-safety analysis, but it is not actually used otherwise.
 254  #define REVERSE_LOCK(g, cs) typename std::decay<decltype(g)>::type::reverse_lock BITCOIN_UNIQUE_NAME(revlock)(g, cs, #cs, __FILE__, __LINE__)
 255  
 256  // When locking a Mutex, require negative capability to ensure the lock
 257  // is not already held
 258  inline Mutex& MaybeCheckNotHeld(Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
 259  inline Mutex* MaybeCheckNotHeld(Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
 260  
 261  // When locking a GlobalMutex or RecursiveMutex, just check it is not
 262  // locked in the surrounding scope.
 263  template <typename MutexType>
 264  inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
 265  template <typename MutexType>
 266  inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
 267  
 268  #define LOCK(cs) UniqueLock BITCOIN_UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
 269  #define LOCK2(cs1, cs2)                                               \
 270      UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
 271      UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__)
 272  #define LOCK_ARGS(cs) MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__
 273  #define TRY_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs), true)
 274  #define WAIT_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs))
 275  
 276  //! Run code while locking a mutex.
 277  //!
 278  //! Examples:
 279  //!
 280  //!   WITH_LOCK(cs, shared_val = shared_val + 1);
 281  //!
 282  //!   int val = WITH_LOCK(cs, return shared_val);
 283  //!
 284  //! Note:
 285  //!
 286  //! Since the return type deduction follows that of decltype(auto), while the
 287  //! deduced type of:
 288  //!
 289  //!   WITH_LOCK(cs, int i = 1; return i);
 290  //!
 291  //! is int, the deduced type of:
 292  //!
 293  //!   WITH_LOCK(cs, int j = 1; return (j));
 294  //!
 295  //! is &int, a reference to a local variable
 296  //!
 297  //! The above is detectable at compile-time with the -Wreturn-local-addr flag in
 298  //! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
 299  #define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
 300  
 301  #endif // BITCOIN_SYNC_H
 302