xref: /aosp_15_r20/external/libcxx/utils/google-benchmark/src/mutex.h (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
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