1*58b9f456SAndroid Build Coastguard Worker #ifndef BENCHMARK_MUTEX_H_ 2*58b9f456SAndroid Build Coastguard Worker #define BENCHMARK_MUTEX_H_ 3*58b9f456SAndroid Build Coastguard Worker 4*58b9f456SAndroid Build Coastguard Worker #include <condition_variable> 5*58b9f456SAndroid Build Coastguard Worker #include <mutex> 6*58b9f456SAndroid Build Coastguard Worker 7*58b9f456SAndroid Build Coastguard Worker #include "check.h" 8*58b9f456SAndroid Build Coastguard Worker 9*58b9f456SAndroid Build Coastguard Worker // Enable thread safety attributes only with clang. 10*58b9f456SAndroid Build Coastguard Worker // The attributes can be safely erased when compiling with other compilers. 11*58b9f456SAndroid Build Coastguard Worker #if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) 12*58b9f456SAndroid Build Coastguard Worker #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) 13*58b9f456SAndroid Build Coastguard Worker #else 14*58b9f456SAndroid Build Coastguard Worker #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op 15*58b9f456SAndroid Build Coastguard Worker #endif 16*58b9f456SAndroid Build Coastguard Worker 17*58b9f456SAndroid Build Coastguard Worker #define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) 18*58b9f456SAndroid Build Coastguard Worker 19*58b9f456SAndroid Build Coastguard Worker #define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) 20*58b9f456SAndroid Build Coastguard Worker 21*58b9f456SAndroid Build Coastguard Worker #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) 22*58b9f456SAndroid Build Coastguard Worker 23*58b9f456SAndroid Build Coastguard Worker #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) 24*58b9f456SAndroid Build Coastguard Worker 25*58b9f456SAndroid Build Coastguard Worker #define ACQUIRED_BEFORE(...) \ 26*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) 27*58b9f456SAndroid Build Coastguard Worker 28*58b9f456SAndroid Build Coastguard Worker #define ACQUIRED_AFTER(...) \ 29*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) 30*58b9f456SAndroid Build Coastguard Worker 31*58b9f456SAndroid Build Coastguard Worker #define REQUIRES(...) \ 32*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) 33*58b9f456SAndroid Build Coastguard Worker 34*58b9f456SAndroid Build Coastguard Worker #define REQUIRES_SHARED(...) \ 35*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) 36*58b9f456SAndroid Build Coastguard Worker 37*58b9f456SAndroid Build Coastguard Worker #define ACQUIRE(...) \ 38*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) 39*58b9f456SAndroid Build Coastguard Worker 40*58b9f456SAndroid Build Coastguard Worker #define ACQUIRE_SHARED(...) \ 41*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) 42*58b9f456SAndroid Build Coastguard Worker 43*58b9f456SAndroid Build Coastguard Worker #define RELEASE(...) \ 44*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) 45*58b9f456SAndroid Build Coastguard Worker 46*58b9f456SAndroid Build Coastguard Worker #define RELEASE_SHARED(...) \ 47*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) 48*58b9f456SAndroid Build Coastguard Worker 49*58b9f456SAndroid Build Coastguard Worker #define TRY_ACQUIRE(...) \ 50*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) 51*58b9f456SAndroid Build Coastguard Worker 52*58b9f456SAndroid Build Coastguard Worker #define TRY_ACQUIRE_SHARED(...) \ 53*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) 54*58b9f456SAndroid Build Coastguard Worker 55*58b9f456SAndroid Build Coastguard Worker #define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) 56*58b9f456SAndroid Build Coastguard Worker 57*58b9f456SAndroid Build Coastguard Worker #define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) 58*58b9f456SAndroid Build Coastguard Worker 59*58b9f456SAndroid Build Coastguard Worker #define ASSERT_SHARED_CAPABILITY(x) \ 60*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) 61*58b9f456SAndroid Build Coastguard Worker 62*58b9f456SAndroid Build Coastguard Worker #define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) 63*58b9f456SAndroid Build Coastguard Worker 64*58b9f456SAndroid Build Coastguard Worker #define NO_THREAD_SAFETY_ANALYSIS \ 65*58b9f456SAndroid Build Coastguard Worker THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) 66*58b9f456SAndroid Build Coastguard Worker 67*58b9f456SAndroid Build Coastguard Worker namespace benchmark { 68*58b9f456SAndroid Build Coastguard Worker 69*58b9f456SAndroid Build Coastguard Worker typedef std::condition_variable Condition; 70*58b9f456SAndroid Build Coastguard Worker 71*58b9f456SAndroid Build Coastguard Worker // NOTE: Wrappers for std::mutex and std::unique_lock are provided so that 72*58b9f456SAndroid Build Coastguard Worker // we can annotate them with thread safety attributes and use the 73*58b9f456SAndroid Build Coastguard Worker // -Wthread-safety warning with clang. The standard library types cannot be 74*58b9f456SAndroid Build Coastguard Worker // used directly because they do not provided the required annotations. 75*58b9f456SAndroid Build Coastguard Worker class CAPABILITY("mutex") Mutex { 76*58b9f456SAndroid Build Coastguard Worker public: Mutex()77*58b9f456SAndroid Build Coastguard Worker Mutex() {} 78*58b9f456SAndroid Build Coastguard Worker lock()79*58b9f456SAndroid Build Coastguard Worker void lock() ACQUIRE() { mut_.lock(); } unlock()80*58b9f456SAndroid Build Coastguard Worker void unlock() RELEASE() { mut_.unlock(); } native_handle()81*58b9f456SAndroid Build Coastguard Worker std::mutex& native_handle() { return mut_; } 82*58b9f456SAndroid Build Coastguard Worker 83*58b9f456SAndroid Build Coastguard Worker private: 84*58b9f456SAndroid Build Coastguard Worker std::mutex mut_; 85*58b9f456SAndroid Build Coastguard Worker }; 86*58b9f456SAndroid Build Coastguard Worker 87*58b9f456SAndroid Build Coastguard Worker class SCOPED_CAPABILITY MutexLock { 88*58b9f456SAndroid Build Coastguard Worker typedef std::unique_lock<std::mutex> MutexLockImp; 89*58b9f456SAndroid Build Coastguard Worker 90*58b9f456SAndroid Build Coastguard Worker public: MutexLock(Mutex & m)91*58b9f456SAndroid Build Coastguard Worker MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {} RELEASE()92*58b9f456SAndroid Build Coastguard Worker ~MutexLock() RELEASE() {} native_handle()93*58b9f456SAndroid Build Coastguard Worker MutexLockImp& native_handle() { return ml_; } 94*58b9f456SAndroid Build Coastguard Worker 95*58b9f456SAndroid Build Coastguard Worker private: 96*58b9f456SAndroid Build Coastguard Worker MutexLockImp ml_; 97*58b9f456SAndroid Build Coastguard Worker }; 98*58b9f456SAndroid Build Coastguard Worker 99*58b9f456SAndroid Build Coastguard Worker class Barrier { 100*58b9f456SAndroid Build Coastguard Worker public: Barrier(int num_threads)101*58b9f456SAndroid Build Coastguard Worker Barrier(int num_threads) : running_threads_(num_threads) {} 102*58b9f456SAndroid Build Coastguard Worker 103*58b9f456SAndroid Build Coastguard Worker // Called by each thread wait()104*58b9f456SAndroid Build Coastguard Worker bool wait() EXCLUDES(lock_) { 105*58b9f456SAndroid Build Coastguard Worker bool last_thread = false; 106*58b9f456SAndroid Build Coastguard Worker { 107*58b9f456SAndroid Build Coastguard Worker MutexLock ml(lock_); 108*58b9f456SAndroid Build Coastguard Worker last_thread = createBarrier(ml); 109*58b9f456SAndroid Build Coastguard Worker } 110*58b9f456SAndroid Build Coastguard Worker if (last_thread) phase_condition_.notify_all(); 111*58b9f456SAndroid Build Coastguard Worker return last_thread; 112*58b9f456SAndroid Build Coastguard Worker } 113*58b9f456SAndroid Build Coastguard Worker removeThread()114*58b9f456SAndroid Build Coastguard Worker void removeThread() EXCLUDES(lock_) { 115*58b9f456SAndroid Build Coastguard Worker MutexLock ml(lock_); 116*58b9f456SAndroid Build Coastguard Worker --running_threads_; 117*58b9f456SAndroid Build Coastguard Worker if (entered_ != 0) phase_condition_.notify_all(); 118*58b9f456SAndroid Build Coastguard Worker } 119*58b9f456SAndroid Build Coastguard Worker 120*58b9f456SAndroid Build Coastguard Worker private: 121*58b9f456SAndroid Build Coastguard Worker Mutex lock_; 122*58b9f456SAndroid Build Coastguard Worker Condition phase_condition_; 123*58b9f456SAndroid Build Coastguard Worker int running_threads_; 124*58b9f456SAndroid Build Coastguard Worker 125*58b9f456SAndroid Build Coastguard Worker // State for barrier management 126*58b9f456SAndroid Build Coastguard Worker int phase_number_ = 0; 127*58b9f456SAndroid Build Coastguard Worker int entered_ = 0; // Number of threads that have entered this barrier 128*58b9f456SAndroid Build Coastguard Worker 129*58b9f456SAndroid Build Coastguard Worker // Enter the barrier and wait until all other threads have also 130*58b9f456SAndroid Build Coastguard Worker // entered the barrier. Returns iff this is the last thread to 131*58b9f456SAndroid Build Coastguard Worker // enter the barrier. createBarrier(MutexLock & ml)132*58b9f456SAndroid Build Coastguard Worker bool createBarrier(MutexLock& ml) REQUIRES(lock_) { 133*58b9f456SAndroid Build Coastguard Worker CHECK_LT(entered_, running_threads_); 134*58b9f456SAndroid Build Coastguard Worker entered_++; 135*58b9f456SAndroid Build Coastguard Worker if (entered_ < running_threads_) { 136*58b9f456SAndroid Build Coastguard Worker // Wait for all threads to enter 137*58b9f456SAndroid Build Coastguard Worker int phase_number_cp = phase_number_; 138*58b9f456SAndroid Build Coastguard Worker auto cb = [this, phase_number_cp]() { 139*58b9f456SAndroid Build Coastguard Worker return this->phase_number_ > phase_number_cp || 140*58b9f456SAndroid Build Coastguard Worker entered_ == running_threads_; // A thread has aborted in error 141*58b9f456SAndroid Build Coastguard Worker }; 142*58b9f456SAndroid Build Coastguard Worker phase_condition_.wait(ml.native_handle(), cb); 143*58b9f456SAndroid Build Coastguard Worker if (phase_number_ > phase_number_cp) return false; 144*58b9f456SAndroid Build Coastguard Worker // else (running_threads_ == entered_) and we are the last thread. 145*58b9f456SAndroid Build Coastguard Worker } 146*58b9f456SAndroid Build Coastguard Worker // Last thread has reached the barrier 147*58b9f456SAndroid Build Coastguard Worker phase_number_++; 148*58b9f456SAndroid Build Coastguard Worker entered_ = 0; 149*58b9f456SAndroid Build Coastguard Worker return true; 150*58b9f456SAndroid Build Coastguard Worker } 151*58b9f456SAndroid Build Coastguard Worker }; 152*58b9f456SAndroid Build Coastguard Worker 153*58b9f456SAndroid Build Coastguard Worker } // end namespace benchmark 154*58b9f456SAndroid Build Coastguard Worker 155*58b9f456SAndroid Build Coastguard Worker #endif // BENCHMARK_MUTEX_H_ 156