Home | History | Annotate | Line # | Download | only in sanitizer_common
sanitizer_mutex.h revision 1.1
      1 //===-- sanitizer_mutex.h ---------------------------------------*- C++ -*-===//
      2 //
      3 // This file is distributed under the University of Illinois Open Source
      4 // License. See LICENSE.TXT for details.
      5 //
      6 //===----------------------------------------------------------------------===//
      7 //
      8 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
      9 //
     10 //===----------------------------------------------------------------------===//
     11 
     12 #ifndef SANITIZER_MUTEX_H
     13 #define SANITIZER_MUTEX_H
     14 
     15 #include "sanitizer_atomic.h"
     16 #include "sanitizer_internal_defs.h"
     17 #include "sanitizer_libc.h"
     18 
     19 namespace __sanitizer {
     20 
     21 class StaticSpinMutex {
     22  public:
     23   void Init() {
     24     atomic_store(&state_, 0, memory_order_relaxed);
     25   }
     26 
     27   void Lock() {
     28     if (TryLock())
     29       return;
     30     LockSlow();
     31   }
     32 
     33   bool TryLock() {
     34     return atomic_exchange(&state_, 1, memory_order_acquire) == 0;
     35   }
     36 
     37   void Unlock() {
     38     atomic_store(&state_, 0, memory_order_release);
     39   }
     40 
     41  private:
     42   atomic_uint8_t state_;
     43 
     44   void NOINLINE LockSlow() {
     45     for (int i = 0;; i++) {
     46       if (i < 10)
     47         proc_yield(10);
     48       else
     49         internal_sched_yield();
     50       if (atomic_load(&state_, memory_order_relaxed) == 0
     51           && atomic_exchange(&state_, 1, memory_order_acquire) == 0)
     52         return;
     53     }
     54   }
     55 };
     56 
     57 class SpinMutex : public StaticSpinMutex {
     58  public:
     59   SpinMutex() {
     60     Init();
     61   }
     62 
     63  private:
     64   SpinMutex(const SpinMutex&);
     65   void operator=(const SpinMutex&);
     66 };
     67 
     68 class BlockingMutex {
     69  public:
     70   explicit BlockingMutex(LinkerInitialized);
     71   void Lock();
     72   void Unlock();
     73  private:
     74   uptr opaque_storage_[10];
     75   uptr owner_;  // for debugging
     76 };
     77 
     78 template<typename MutexType>
     79 class GenericScopedLock {
     80  public:
     81   explicit GenericScopedLock(MutexType *mu)
     82       : mu_(mu) {
     83     mu_->Lock();
     84   }
     85 
     86   ~GenericScopedLock() {
     87     mu_->Unlock();
     88   }
     89 
     90  private:
     91   MutexType *mu_;
     92 
     93   GenericScopedLock(const GenericScopedLock&);
     94   void operator=(const GenericScopedLock&);
     95 };
     96 
     97 template<typename MutexType>
     98 class GenericScopedReadLock {
     99  public:
    100   explicit GenericScopedReadLock(MutexType *mu)
    101       : mu_(mu) {
    102     mu_->ReadLock();
    103   }
    104 
    105   ~GenericScopedReadLock() {
    106     mu_->ReadUnlock();
    107   }
    108 
    109  private:
    110   MutexType *mu_;
    111 
    112   GenericScopedReadLock(const GenericScopedReadLock&);
    113   void operator=(const GenericScopedReadLock&);
    114 };
    115 
    116 typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
    117 typedef GenericScopedLock<BlockingMutex> BlockingMutexLock;
    118 
    119 }  // namespace __sanitizer
    120 
    121 #endif  // SANITIZER_MUTEX_H
    122