xref: /aosp_15_r20/external/abseil-cpp/absl/synchronization/mutex.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker 
15*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
16*9356374aSAndroid Build Coastguard Worker 
17*9356374aSAndroid Build Coastguard Worker #ifdef _WIN32
18*9356374aSAndroid Build Coastguard Worker #include <windows.h>
19*9356374aSAndroid Build Coastguard Worker #ifdef ERROR
20*9356374aSAndroid Build Coastguard Worker #undef ERROR
21*9356374aSAndroid Build Coastguard Worker #endif
22*9356374aSAndroid Build Coastguard Worker #else
23*9356374aSAndroid Build Coastguard Worker #include <fcntl.h>
24*9356374aSAndroid Build Coastguard Worker #include <pthread.h>
25*9356374aSAndroid Build Coastguard Worker #include <sched.h>
26*9356374aSAndroid Build Coastguard Worker #include <sys/time.h>
27*9356374aSAndroid Build Coastguard Worker #endif
28*9356374aSAndroid Build Coastguard Worker 
29*9356374aSAndroid Build Coastguard Worker #include <assert.h>
30*9356374aSAndroid Build Coastguard Worker #include <errno.h>
31*9356374aSAndroid Build Coastguard Worker #include <stdio.h>
32*9356374aSAndroid Build Coastguard Worker #include <stdlib.h>
33*9356374aSAndroid Build Coastguard Worker #include <string.h>
34*9356374aSAndroid Build Coastguard Worker #include <time.h>
35*9356374aSAndroid Build Coastguard Worker 
36*9356374aSAndroid Build Coastguard Worker #include <algorithm>
37*9356374aSAndroid Build Coastguard Worker #include <atomic>
38*9356374aSAndroid Build Coastguard Worker #include <cstddef>
39*9356374aSAndroid Build Coastguard Worker #include <cstdlib>
40*9356374aSAndroid Build Coastguard Worker #include <cstring>
41*9356374aSAndroid Build Coastguard Worker #include <thread>  // NOLINT(build/c++11)
42*9356374aSAndroid Build Coastguard Worker 
43*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
44*9356374aSAndroid Build Coastguard Worker #include "absl/base/call_once.h"
45*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
46*9356374aSAndroid Build Coastguard Worker #include "absl/base/dynamic_annotations.h"
47*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/atomic_hook.h"
48*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/cycleclock.h"
49*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/hide_ptr.h"
50*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/low_level_alloc.h"
51*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/raw_logging.h"
52*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/spinlock.h"
53*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/sysinfo.h"
54*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/thread_identity.h"
55*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/tsan_mutex_interface.h"
56*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
57*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/stacktrace.h"
58*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/symbolize.h"
59*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/graphcycles.h"
60*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/per_thread_sem.h"
61*9356374aSAndroid Build Coastguard Worker #include "absl/time/time.h"
62*9356374aSAndroid Build Coastguard Worker 
63*9356374aSAndroid Build Coastguard Worker using absl::base_internal::CurrentThreadIdentityIfPresent;
64*9356374aSAndroid Build Coastguard Worker using absl::base_internal::CycleClock;
65*9356374aSAndroid Build Coastguard Worker using absl::base_internal::PerThreadSynch;
66*9356374aSAndroid Build Coastguard Worker using absl::base_internal::SchedulingGuard;
67*9356374aSAndroid Build Coastguard Worker using absl::base_internal::ThreadIdentity;
68*9356374aSAndroid Build Coastguard Worker using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;
69*9356374aSAndroid Build Coastguard Worker using absl::synchronization_internal::GraphCycles;
70*9356374aSAndroid Build Coastguard Worker using absl::synchronization_internal::GraphId;
71*9356374aSAndroid Build Coastguard Worker using absl::synchronization_internal::InvalidGraphId;
72*9356374aSAndroid Build Coastguard Worker using absl::synchronization_internal::KernelTimeout;
73*9356374aSAndroid Build Coastguard Worker using absl::synchronization_internal::PerThreadSem;
74*9356374aSAndroid Build Coastguard Worker 
75*9356374aSAndroid Build Coastguard Worker extern "C" {
ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)76*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)() {
77*9356374aSAndroid Build Coastguard Worker   std::this_thread::yield();
78*9356374aSAndroid Build Coastguard Worker }
79*9356374aSAndroid Build Coastguard Worker }  // extern "C"
80*9356374aSAndroid Build Coastguard Worker 
81*9356374aSAndroid Build Coastguard Worker namespace absl {
82*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
83*9356374aSAndroid Build Coastguard Worker 
84*9356374aSAndroid Build Coastguard Worker namespace {
85*9356374aSAndroid Build Coastguard Worker 
86*9356374aSAndroid Build Coastguard Worker #if defined(ABSL_HAVE_THREAD_SANITIZER)
87*9356374aSAndroid Build Coastguard Worker constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore;
88*9356374aSAndroid Build Coastguard Worker #else
89*9356374aSAndroid Build Coastguard Worker constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort;
90*9356374aSAndroid Build Coastguard Worker #endif
91*9356374aSAndroid Build Coastguard Worker 
92*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::atomic<OnDeadlockCycle> synch_deadlock_detection(
93*9356374aSAndroid Build Coastguard Worker     kDeadlockDetectionDefault);
94*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);
95*9356374aSAndroid Build Coastguard Worker 
96*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
97*9356374aSAndroid Build Coastguard Worker absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
98*9356374aSAndroid Build Coastguard Worker     submit_profile_data;
99*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
100*9356374aSAndroid Build Coastguard Worker     const char* msg, const void* obj, int64_t wait_cycles)>
101*9356374aSAndroid Build Coastguard Worker     mutex_tracer;
102*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
103*9356374aSAndroid Build Coastguard Worker absl::base_internal::AtomicHook<void (*)(const char* msg, const void* cv)>
104*9356374aSAndroid Build Coastguard Worker     cond_var_tracer;
105*9356374aSAndroid Build Coastguard Worker 
106*9356374aSAndroid Build Coastguard Worker }  // namespace
107*9356374aSAndroid Build Coastguard Worker 
108*9356374aSAndroid Build Coastguard Worker static inline bool EvalConditionAnnotated(const Condition* cond, Mutex* mu,
109*9356374aSAndroid Build Coastguard Worker                                           bool locking, bool trylock,
110*9356374aSAndroid Build Coastguard Worker                                           bool read_lock);
111*9356374aSAndroid Build Coastguard Worker 
RegisterMutexProfiler(void (* fn)(int64_t wait_cycles))112*9356374aSAndroid Build Coastguard Worker void RegisterMutexProfiler(void (*fn)(int64_t wait_cycles)) {
113*9356374aSAndroid Build Coastguard Worker   submit_profile_data.Store(fn);
114*9356374aSAndroid Build Coastguard Worker }
115*9356374aSAndroid Build Coastguard Worker 
RegisterMutexTracer(void (* fn)(const char * msg,const void * obj,int64_t wait_cycles))116*9356374aSAndroid Build Coastguard Worker void RegisterMutexTracer(void (*fn)(const char* msg, const void* obj,
117*9356374aSAndroid Build Coastguard Worker                                     int64_t wait_cycles)) {
118*9356374aSAndroid Build Coastguard Worker   mutex_tracer.Store(fn);
119*9356374aSAndroid Build Coastguard Worker }
120*9356374aSAndroid Build Coastguard Worker 
RegisterCondVarTracer(void (* fn)(const char * msg,const void * cv))121*9356374aSAndroid Build Coastguard Worker void RegisterCondVarTracer(void (*fn)(const char* msg, const void* cv)) {
122*9356374aSAndroid Build Coastguard Worker   cond_var_tracer.Store(fn);
123*9356374aSAndroid Build Coastguard Worker }
124*9356374aSAndroid Build Coastguard Worker 
125*9356374aSAndroid Build Coastguard Worker namespace {
126*9356374aSAndroid Build Coastguard Worker // Represents the strategy for spin and yield.
127*9356374aSAndroid Build Coastguard Worker // See the comment in GetMutexGlobals() for more information.
128*9356374aSAndroid Build Coastguard Worker enum DelayMode { AGGRESSIVE, GENTLE };
129*9356374aSAndroid Build Coastguard Worker 
130*9356374aSAndroid Build Coastguard Worker struct ABSL_CACHELINE_ALIGNED MutexGlobals {
131*9356374aSAndroid Build Coastguard Worker   absl::once_flag once;
132*9356374aSAndroid Build Coastguard Worker   // Note: this variable is initialized separately in Mutex::LockSlow,
133*9356374aSAndroid Build Coastguard Worker   // so that Mutex::Lock does not have a stack frame in optimized build.
134*9356374aSAndroid Build Coastguard Worker   std::atomic<int> spinloop_iterations{0};
135*9356374aSAndroid Build Coastguard Worker   int32_t mutex_sleep_spins[2] = {};
136*9356374aSAndroid Build Coastguard Worker   absl::Duration mutex_sleep_time;
137*9356374aSAndroid Build Coastguard Worker };
138*9356374aSAndroid Build Coastguard Worker 
139*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT static MutexGlobals globals;
140*9356374aSAndroid Build Coastguard Worker 
MeasureTimeToYield()141*9356374aSAndroid Build Coastguard Worker absl::Duration MeasureTimeToYield() {
142*9356374aSAndroid Build Coastguard Worker   absl::Time before = absl::Now();
143*9356374aSAndroid Build Coastguard Worker   ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
144*9356374aSAndroid Build Coastguard Worker   return absl::Now() - before;
145*9356374aSAndroid Build Coastguard Worker }
146*9356374aSAndroid Build Coastguard Worker 
GetMutexGlobals()147*9356374aSAndroid Build Coastguard Worker const MutexGlobals& GetMutexGlobals() {
148*9356374aSAndroid Build Coastguard Worker   absl::base_internal::LowLevelCallOnce(&globals.once, [&]() {
149*9356374aSAndroid Build Coastguard Worker     if (absl::base_internal::NumCPUs() > 1) {
150*9356374aSAndroid Build Coastguard Worker       // If the mode is aggressive then spin many times before yielding.
151*9356374aSAndroid Build Coastguard Worker       // If the mode is gentle then spin only a few times before yielding.
152*9356374aSAndroid Build Coastguard Worker       // Aggressive spinning is used to ensure that an Unlock() call,
153*9356374aSAndroid Build Coastguard Worker       // which must get the spin lock for any thread to make progress gets it
154*9356374aSAndroid Build Coastguard Worker       // without undue delay.
155*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_spins[AGGRESSIVE] = 5000;
156*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_spins[GENTLE] = 250;
157*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_time = absl::Microseconds(10);
158*9356374aSAndroid Build Coastguard Worker     } else {
159*9356374aSAndroid Build Coastguard Worker       // If this a uniprocessor, only yield/sleep. Real-time threads are often
160*9356374aSAndroid Build Coastguard Worker       // unable to yield, so the sleep time needs to be long enough to keep
161*9356374aSAndroid Build Coastguard Worker       // the calling thread asleep until scheduling happens.
162*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_spins[AGGRESSIVE] = 0;
163*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_spins[GENTLE] = 0;
164*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_time = MeasureTimeToYield() * 5;
165*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_time =
166*9356374aSAndroid Build Coastguard Worker           std::min(globals.mutex_sleep_time, absl::Milliseconds(1));
167*9356374aSAndroid Build Coastguard Worker       globals.mutex_sleep_time =
168*9356374aSAndroid Build Coastguard Worker           std::max(globals.mutex_sleep_time, absl::Microseconds(10));
169*9356374aSAndroid Build Coastguard Worker     }
170*9356374aSAndroid Build Coastguard Worker   });
171*9356374aSAndroid Build Coastguard Worker   return globals;
172*9356374aSAndroid Build Coastguard Worker }
173*9356374aSAndroid Build Coastguard Worker }  // namespace
174*9356374aSAndroid Build Coastguard Worker 
175*9356374aSAndroid Build Coastguard Worker namespace synchronization_internal {
176*9356374aSAndroid Build Coastguard Worker // Returns the Mutex delay on iteration `c` depending on the given `mode`.
177*9356374aSAndroid Build Coastguard Worker // The returned value should be used as `c` for the next call to `MutexDelay`.
MutexDelay(int32_t c,int mode)178*9356374aSAndroid Build Coastguard Worker int MutexDelay(int32_t c, int mode) {
179*9356374aSAndroid Build Coastguard Worker   const int32_t limit = GetMutexGlobals().mutex_sleep_spins[mode];
180*9356374aSAndroid Build Coastguard Worker   const absl::Duration sleep_time = GetMutexGlobals().mutex_sleep_time;
181*9356374aSAndroid Build Coastguard Worker   if (c < limit) {
182*9356374aSAndroid Build Coastguard Worker     // Spin.
183*9356374aSAndroid Build Coastguard Worker     c++;
184*9356374aSAndroid Build Coastguard Worker   } else {
185*9356374aSAndroid Build Coastguard Worker     SchedulingGuard::ScopedEnable enable_rescheduling;
186*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);
187*9356374aSAndroid Build Coastguard Worker     if (c == limit) {
188*9356374aSAndroid Build Coastguard Worker       // Yield once.
189*9356374aSAndroid Build Coastguard Worker       ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
190*9356374aSAndroid Build Coastguard Worker       c++;
191*9356374aSAndroid Build Coastguard Worker     } else {
192*9356374aSAndroid Build Coastguard Worker       // Then wait.
193*9356374aSAndroid Build Coastguard Worker       absl::SleepFor(sleep_time);
194*9356374aSAndroid Build Coastguard Worker       c = 0;
195*9356374aSAndroid Build Coastguard Worker     }
196*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);
197*9356374aSAndroid Build Coastguard Worker   }
198*9356374aSAndroid Build Coastguard Worker   return c;
199*9356374aSAndroid Build Coastguard Worker }
200*9356374aSAndroid Build Coastguard Worker }  // namespace synchronization_internal
201*9356374aSAndroid Build Coastguard Worker 
202*9356374aSAndroid Build Coastguard Worker // --------------------------Generic atomic ops
203*9356374aSAndroid Build Coastguard Worker // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to
204*9356374aSAndroid Build Coastguard Worker // "*pv | bits" if necessary.  Wait until (*pv & wait_until_clear)==0
205*9356374aSAndroid Build Coastguard Worker // before making any change.
206*9356374aSAndroid Build Coastguard Worker // Returns true if bits were previously unset and set by the call.
207*9356374aSAndroid Build Coastguard Worker // This is used to set flags in mutex and condition variable words.
AtomicSetBits(std::atomic<intptr_t> * pv,intptr_t bits,intptr_t wait_until_clear)208*9356374aSAndroid Build Coastguard Worker static bool AtomicSetBits(std::atomic<intptr_t>* pv, intptr_t bits,
209*9356374aSAndroid Build Coastguard Worker                           intptr_t wait_until_clear) {
210*9356374aSAndroid Build Coastguard Worker   for (;;) {
211*9356374aSAndroid Build Coastguard Worker     intptr_t v = pv->load(std::memory_order_relaxed);
212*9356374aSAndroid Build Coastguard Worker     if ((v & bits) == bits) {
213*9356374aSAndroid Build Coastguard Worker       return false;
214*9356374aSAndroid Build Coastguard Worker     }
215*9356374aSAndroid Build Coastguard Worker     if ((v & wait_until_clear) != 0) {
216*9356374aSAndroid Build Coastguard Worker       continue;
217*9356374aSAndroid Build Coastguard Worker     }
218*9356374aSAndroid Build Coastguard Worker     if (pv->compare_exchange_weak(v, v | bits, std::memory_order_release,
219*9356374aSAndroid Build Coastguard Worker                                   std::memory_order_relaxed)) {
220*9356374aSAndroid Build Coastguard Worker       return true;
221*9356374aSAndroid Build Coastguard Worker     }
222*9356374aSAndroid Build Coastguard Worker   }
223*9356374aSAndroid Build Coastguard Worker }
224*9356374aSAndroid Build Coastguard Worker 
225*9356374aSAndroid Build Coastguard Worker //------------------------------------------------------------------
226*9356374aSAndroid Build Coastguard Worker 
227*9356374aSAndroid Build Coastguard Worker // Data for doing deadlock detection.
228*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu(
229*9356374aSAndroid Build Coastguard Worker     absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
230*9356374aSAndroid Build Coastguard Worker 
231*9356374aSAndroid Build Coastguard Worker // Graph used to detect deadlocks.
232*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT static GraphCycles* deadlock_graph
233*9356374aSAndroid Build Coastguard Worker     ABSL_GUARDED_BY(deadlock_graph_mu) ABSL_PT_GUARDED_BY(deadlock_graph_mu);
234*9356374aSAndroid Build Coastguard Worker 
235*9356374aSAndroid Build Coastguard Worker //------------------------------------------------------------------
236*9356374aSAndroid Build Coastguard Worker // An event mechanism for debugging mutex use.
237*9356374aSAndroid Build Coastguard Worker // It also allows mutexes to be given names for those who can't handle
238*9356374aSAndroid Build Coastguard Worker // addresses, and instead like to give their data structures names like
239*9356374aSAndroid Build Coastguard Worker // "Henry", "Fido", or "Rupert IV, King of Yondavia".
240*9356374aSAndroid Build Coastguard Worker 
241*9356374aSAndroid Build Coastguard Worker namespace {  // to prevent name pollution
242*9356374aSAndroid Build Coastguard Worker enum {       // Mutex and CondVar events passed as "ev" to PostSynchEvent
243*9356374aSAndroid Build Coastguard Worker              // Mutex events
244*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_TRYLOCK_SUCCESS,
245*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_TRYLOCK_FAILED,
246*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_READERTRYLOCK_SUCCESS,
247*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_READERTRYLOCK_FAILED,
248*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_LOCK,
249*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_LOCK_RETURNING,
250*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_READERLOCK,
251*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_READERLOCK_RETURNING,
252*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_UNLOCK,
253*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_READERUNLOCK,
254*9356374aSAndroid Build Coastguard Worker 
255*9356374aSAndroid Build Coastguard Worker   // CondVar events
256*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_WAIT,
257*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_WAIT_RETURNING,
258*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_SIGNAL,
259*9356374aSAndroid Build Coastguard Worker   SYNCH_EV_SIGNALALL,
260*9356374aSAndroid Build Coastguard Worker };
261*9356374aSAndroid Build Coastguard Worker 
262*9356374aSAndroid Build Coastguard Worker enum {                    // Event flags
263*9356374aSAndroid Build Coastguard Worker   SYNCH_F_R = 0x01,       // reader event
264*9356374aSAndroid Build Coastguard Worker   SYNCH_F_LCK = 0x02,     // PostSynchEvent called with mutex held
265*9356374aSAndroid Build Coastguard Worker   SYNCH_F_TRY = 0x04,     // TryLock or ReaderTryLock
266*9356374aSAndroid Build Coastguard Worker   SYNCH_F_UNLOCK = 0x08,  // Unlock or ReaderUnlock
267*9356374aSAndroid Build Coastguard Worker 
268*9356374aSAndroid Build Coastguard Worker   SYNCH_F_LCK_W = SYNCH_F_LCK,
269*9356374aSAndroid Build Coastguard Worker   SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R,
270*9356374aSAndroid Build Coastguard Worker };
271*9356374aSAndroid Build Coastguard Worker }  // anonymous namespace
272*9356374aSAndroid Build Coastguard Worker 
273*9356374aSAndroid Build Coastguard Worker // Properties of the events.
274*9356374aSAndroid Build Coastguard Worker static const struct {
275*9356374aSAndroid Build Coastguard Worker   int flags;
276*9356374aSAndroid Build Coastguard Worker   const char* msg;
277*9356374aSAndroid Build Coastguard Worker } event_properties[] = {
278*9356374aSAndroid Build Coastguard Worker     {SYNCH_F_LCK_W | SYNCH_F_TRY, "TryLock succeeded "},
279*9356374aSAndroid Build Coastguard Worker     {0, "TryLock failed "},
280*9356374aSAndroid Build Coastguard Worker     {SYNCH_F_LCK_R | SYNCH_F_TRY, "ReaderTryLock succeeded "},
281*9356374aSAndroid Build Coastguard Worker     {0, "ReaderTryLock failed "},
282*9356374aSAndroid Build Coastguard Worker     {0, "Lock blocking "},
283*9356374aSAndroid Build Coastguard Worker     {SYNCH_F_LCK_W, "Lock returning "},
284*9356374aSAndroid Build Coastguard Worker     {0, "ReaderLock blocking "},
285*9356374aSAndroid Build Coastguard Worker     {SYNCH_F_LCK_R, "ReaderLock returning "},
286*9356374aSAndroid Build Coastguard Worker     {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, "Unlock "},
287*9356374aSAndroid Build Coastguard Worker     {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, "ReaderUnlock "},
288*9356374aSAndroid Build Coastguard Worker     {0, "Wait on "},
289*9356374aSAndroid Build Coastguard Worker     {0, "Wait unblocked "},
290*9356374aSAndroid Build Coastguard Worker     {0, "Signal on "},
291*9356374aSAndroid Build Coastguard Worker     {0, "SignalAll on "},
292*9356374aSAndroid Build Coastguard Worker };
293*9356374aSAndroid Build Coastguard Worker 
294*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu(
295*9356374aSAndroid Build Coastguard Worker     absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
296*9356374aSAndroid Build Coastguard Worker 
297*9356374aSAndroid Build Coastguard Worker // Hash table size; should be prime > 2.
298*9356374aSAndroid Build Coastguard Worker // Can't be too small, as it's used for deadlock detection information.
299*9356374aSAndroid Build Coastguard Worker static constexpr uint32_t kNSynchEvent = 1031;
300*9356374aSAndroid Build Coastguard Worker 
301*9356374aSAndroid Build Coastguard Worker static struct SynchEvent {  // this is a trivial hash table for the events
302*9356374aSAndroid Build Coastguard Worker   // struct is freed when refcount reaches 0
303*9356374aSAndroid Build Coastguard Worker   int refcount ABSL_GUARDED_BY(synch_event_mu);
304*9356374aSAndroid Build Coastguard Worker 
305*9356374aSAndroid Build Coastguard Worker   // buckets have linear, 0-terminated  chains
306*9356374aSAndroid Build Coastguard Worker   SynchEvent* next ABSL_GUARDED_BY(synch_event_mu);
307*9356374aSAndroid Build Coastguard Worker 
308*9356374aSAndroid Build Coastguard Worker   // Constant after initialization
309*9356374aSAndroid Build Coastguard Worker   uintptr_t masked_addr;  // object at this address is called "name"
310*9356374aSAndroid Build Coastguard Worker 
311*9356374aSAndroid Build Coastguard Worker   // No explicit synchronization used.  Instead we assume that the
312*9356374aSAndroid Build Coastguard Worker   // client who enables/disables invariants/logging on a Mutex does so
313*9356374aSAndroid Build Coastguard Worker   // while the Mutex is not being concurrently accessed by others.
314*9356374aSAndroid Build Coastguard Worker   void (*invariant)(void* arg);  // called on each event
315*9356374aSAndroid Build Coastguard Worker   void* arg;                     // first arg to (*invariant)()
316*9356374aSAndroid Build Coastguard Worker   bool log;                      // logging turned on
317*9356374aSAndroid Build Coastguard Worker 
318*9356374aSAndroid Build Coastguard Worker   // Constant after initialization
319*9356374aSAndroid Build Coastguard Worker   char name[1];  // actually longer---NUL-terminated string
320*9356374aSAndroid Build Coastguard Worker }* synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);
321*9356374aSAndroid Build Coastguard Worker 
322*9356374aSAndroid Build Coastguard Worker // Ensure that the object at "addr" has a SynchEvent struct associated with it,
323*9356374aSAndroid Build Coastguard Worker // set "bits" in the word there (waiting until lockbit is clear before doing
324*9356374aSAndroid Build Coastguard Worker // so), and return a refcounted reference that will remain valid until
325*9356374aSAndroid Build Coastguard Worker // UnrefSynchEvent() is called.  If a new SynchEvent is allocated,
326*9356374aSAndroid Build Coastguard Worker // the string name is copied into it.
327*9356374aSAndroid Build Coastguard Worker // When used with a mutex, the caller should also ensure that kMuEvent
328*9356374aSAndroid Build Coastguard Worker // is set in the mutex word, and similarly for condition variables and kCVEvent.
EnsureSynchEvent(std::atomic<intptr_t> * addr,const char * name,intptr_t bits,intptr_t lockbit)329*9356374aSAndroid Build Coastguard Worker static SynchEvent* EnsureSynchEvent(std::atomic<intptr_t>* addr,
330*9356374aSAndroid Build Coastguard Worker                                     const char* name, intptr_t bits,
331*9356374aSAndroid Build Coastguard Worker                                     intptr_t lockbit) {
332*9356374aSAndroid Build Coastguard Worker   uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;
333*9356374aSAndroid Build Coastguard Worker   synch_event_mu.Lock();
334*9356374aSAndroid Build Coastguard Worker   // When a Mutex/CondVar is destroyed, we don't remove the associated
335*9356374aSAndroid Build Coastguard Worker   // SynchEvent to keep destructors empty in release builds for performance
336*9356374aSAndroid Build Coastguard Worker   // reasons. If the current call is the first to set bits (kMuEvent/kCVEvent),
337*9356374aSAndroid Build Coastguard Worker   // we don't look up the existing even because (if it exists, it must be for
338*9356374aSAndroid Build Coastguard Worker   // the previous Mutex/CondVar that existed at the same address).
339*9356374aSAndroid Build Coastguard Worker   // The leaking events must not be a problem for tests, which should create
340*9356374aSAndroid Build Coastguard Worker   // bounded amount of events. And debug logging is not supposed to be enabled
341*9356374aSAndroid Build Coastguard Worker   // in production. However, if it's accidentally enabled, or briefly enabled
342*9356374aSAndroid Build Coastguard Worker   // for some debugging, we don't want to crash the program. Instead we drop
343*9356374aSAndroid Build Coastguard Worker   // all events, if we accumulated too many of them. Size of a single event
344*9356374aSAndroid Build Coastguard Worker   // is ~48 bytes, so 100K events is ~5 MB.
345*9356374aSAndroid Build Coastguard Worker   // Additionally we could delete the old event for the same address,
346*9356374aSAndroid Build Coastguard Worker   // but it would require a better hashmap (if we accumulate too many events,
347*9356374aSAndroid Build Coastguard Worker   // linked lists will grow and traversing them will be very slow).
348*9356374aSAndroid Build Coastguard Worker   constexpr size_t kMaxSynchEventCount = 100 << 10;
349*9356374aSAndroid Build Coastguard Worker   // Total number of live synch events.
350*9356374aSAndroid Build Coastguard Worker   static size_t synch_event_count ABSL_GUARDED_BY(synch_event_mu);
351*9356374aSAndroid Build Coastguard Worker   if (++synch_event_count > kMaxSynchEventCount) {
352*9356374aSAndroid Build Coastguard Worker     synch_event_count = 0;
353*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_LOG(ERROR,
354*9356374aSAndroid Build Coastguard Worker                  "Accumulated %zu Mutex debug objects. If you see this"
355*9356374aSAndroid Build Coastguard Worker                  " in production, it may mean that the production code"
356*9356374aSAndroid Build Coastguard Worker                  " accidentally calls "
357*9356374aSAndroid Build Coastguard Worker                  "Mutex/CondVar::EnableDebugLog/EnableInvariantDebugging.",
358*9356374aSAndroid Build Coastguard Worker                  kMaxSynchEventCount);
359*9356374aSAndroid Build Coastguard Worker     for (auto*& head : synch_event) {
360*9356374aSAndroid Build Coastguard Worker       for (auto* e = head; e != nullptr;) {
361*9356374aSAndroid Build Coastguard Worker         SynchEvent* next = e->next;
362*9356374aSAndroid Build Coastguard Worker         if (--(e->refcount) == 0) {
363*9356374aSAndroid Build Coastguard Worker           base_internal::LowLevelAlloc::Free(e);
364*9356374aSAndroid Build Coastguard Worker         }
365*9356374aSAndroid Build Coastguard Worker         e = next;
366*9356374aSAndroid Build Coastguard Worker       }
367*9356374aSAndroid Build Coastguard Worker       head = nullptr;
368*9356374aSAndroid Build Coastguard Worker     }
369*9356374aSAndroid Build Coastguard Worker   }
370*9356374aSAndroid Build Coastguard Worker   SynchEvent* e = nullptr;
371*9356374aSAndroid Build Coastguard Worker   if (!AtomicSetBits(addr, bits, lockbit)) {
372*9356374aSAndroid Build Coastguard Worker     for (e = synch_event[h];
373*9356374aSAndroid Build Coastguard Worker          e != nullptr && e->masked_addr != base_internal::HidePtr(addr);
374*9356374aSAndroid Build Coastguard Worker          e = e->next) {
375*9356374aSAndroid Build Coastguard Worker     }
376*9356374aSAndroid Build Coastguard Worker   }
377*9356374aSAndroid Build Coastguard Worker   if (e == nullptr) {  // no SynchEvent struct found; make one.
378*9356374aSAndroid Build Coastguard Worker     if (name == nullptr) {
379*9356374aSAndroid Build Coastguard Worker       name = "";
380*9356374aSAndroid Build Coastguard Worker     }
381*9356374aSAndroid Build Coastguard Worker     size_t l = strlen(name);
382*9356374aSAndroid Build Coastguard Worker     e = reinterpret_cast<SynchEvent*>(
383*9356374aSAndroid Build Coastguard Worker         base_internal::LowLevelAlloc::Alloc(sizeof(*e) + l));
384*9356374aSAndroid Build Coastguard Worker     e->refcount = 2;  // one for return value, one for linked list
385*9356374aSAndroid Build Coastguard Worker     e->masked_addr = base_internal::HidePtr(addr);
386*9356374aSAndroid Build Coastguard Worker     e->invariant = nullptr;
387*9356374aSAndroid Build Coastguard Worker     e->arg = nullptr;
388*9356374aSAndroid Build Coastguard Worker     e->log = false;
389*9356374aSAndroid Build Coastguard Worker     strcpy(e->name, name);  // NOLINT(runtime/printf)
390*9356374aSAndroid Build Coastguard Worker     e->next = synch_event[h];
391*9356374aSAndroid Build Coastguard Worker     synch_event[h] = e;
392*9356374aSAndroid Build Coastguard Worker   } else {
393*9356374aSAndroid Build Coastguard Worker     e->refcount++;  // for return value
394*9356374aSAndroid Build Coastguard Worker   }
395*9356374aSAndroid Build Coastguard Worker   synch_event_mu.Unlock();
396*9356374aSAndroid Build Coastguard Worker   return e;
397*9356374aSAndroid Build Coastguard Worker }
398*9356374aSAndroid Build Coastguard Worker 
399*9356374aSAndroid Build Coastguard Worker // Decrement the reference count of *e, or do nothing if e==null.
UnrefSynchEvent(SynchEvent * e)400*9356374aSAndroid Build Coastguard Worker static void UnrefSynchEvent(SynchEvent* e) {
401*9356374aSAndroid Build Coastguard Worker   if (e != nullptr) {
402*9356374aSAndroid Build Coastguard Worker     synch_event_mu.Lock();
403*9356374aSAndroid Build Coastguard Worker     bool del = (--(e->refcount) == 0);
404*9356374aSAndroid Build Coastguard Worker     synch_event_mu.Unlock();
405*9356374aSAndroid Build Coastguard Worker     if (del) {
406*9356374aSAndroid Build Coastguard Worker       base_internal::LowLevelAlloc::Free(e);
407*9356374aSAndroid Build Coastguard Worker     }
408*9356374aSAndroid Build Coastguard Worker   }
409*9356374aSAndroid Build Coastguard Worker }
410*9356374aSAndroid Build Coastguard Worker 
411*9356374aSAndroid Build Coastguard Worker // Return a refcounted reference to the SynchEvent of the object at address
412*9356374aSAndroid Build Coastguard Worker // "addr", if any.  The pointer returned is valid until the UnrefSynchEvent() is
413*9356374aSAndroid Build Coastguard Worker // called.
GetSynchEvent(const void * addr)414*9356374aSAndroid Build Coastguard Worker static SynchEvent* GetSynchEvent(const void* addr) {
415*9356374aSAndroid Build Coastguard Worker   uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;
416*9356374aSAndroid Build Coastguard Worker   SynchEvent* e;
417*9356374aSAndroid Build Coastguard Worker   synch_event_mu.Lock();
418*9356374aSAndroid Build Coastguard Worker   for (e = synch_event[h];
419*9356374aSAndroid Build Coastguard Worker        e != nullptr && e->masked_addr != base_internal::HidePtr(addr);
420*9356374aSAndroid Build Coastguard Worker        e = e->next) {
421*9356374aSAndroid Build Coastguard Worker   }
422*9356374aSAndroid Build Coastguard Worker   if (e != nullptr) {
423*9356374aSAndroid Build Coastguard Worker     e->refcount++;
424*9356374aSAndroid Build Coastguard Worker   }
425*9356374aSAndroid Build Coastguard Worker   synch_event_mu.Unlock();
426*9356374aSAndroid Build Coastguard Worker   return e;
427*9356374aSAndroid Build Coastguard Worker }
428*9356374aSAndroid Build Coastguard Worker 
429*9356374aSAndroid Build Coastguard Worker // Called when an event "ev" occurs on a Mutex of CondVar "obj"
430*9356374aSAndroid Build Coastguard Worker // if event recording is on
PostSynchEvent(void * obj,int ev)431*9356374aSAndroid Build Coastguard Worker static void PostSynchEvent(void* obj, int ev) {
432*9356374aSAndroid Build Coastguard Worker   SynchEvent* e = GetSynchEvent(obj);
433*9356374aSAndroid Build Coastguard Worker   // logging is on if event recording is on and either there's no event struct,
434*9356374aSAndroid Build Coastguard Worker   // or it explicitly says to log
435*9356374aSAndroid Build Coastguard Worker   if (e == nullptr || e->log) {
436*9356374aSAndroid Build Coastguard Worker     void* pcs[40];
437*9356374aSAndroid Build Coastguard Worker     int n = absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 1);
438*9356374aSAndroid Build Coastguard Worker     // A buffer with enough space for the ASCII for all the PCs, even on a
439*9356374aSAndroid Build Coastguard Worker     // 64-bit machine.
440*9356374aSAndroid Build Coastguard Worker     char buffer[ABSL_ARRAYSIZE(pcs) * 24];
441*9356374aSAndroid Build Coastguard Worker     int pos = snprintf(buffer, sizeof(buffer), " @");
442*9356374aSAndroid Build Coastguard Worker     for (int i = 0; i != n; i++) {
443*9356374aSAndroid Build Coastguard Worker       int b = snprintf(&buffer[pos], sizeof(buffer) - static_cast<size_t>(pos),
444*9356374aSAndroid Build Coastguard Worker                        " %p", pcs[i]);
445*9356374aSAndroid Build Coastguard Worker       if (b < 0 ||
446*9356374aSAndroid Build Coastguard Worker           static_cast<size_t>(b) >= sizeof(buffer) - static_cast<size_t>(pos)) {
447*9356374aSAndroid Build Coastguard Worker         break;
448*9356374aSAndroid Build Coastguard Worker       }
449*9356374aSAndroid Build Coastguard Worker       pos += b;
450*9356374aSAndroid Build Coastguard Worker     }
451*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj,
452*9356374aSAndroid Build Coastguard Worker                  (e == nullptr ? "" : e->name), buffer);
453*9356374aSAndroid Build Coastguard Worker   }
454*9356374aSAndroid Build Coastguard Worker   const int flags = event_properties[ev].flags;
455*9356374aSAndroid Build Coastguard Worker   if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) {
456*9356374aSAndroid Build Coastguard Worker     // Calling the invariant as is causes problems under ThreadSanitizer.
457*9356374aSAndroid Build Coastguard Worker     // We are currently inside of Mutex Lock/Unlock and are ignoring all
458*9356374aSAndroid Build Coastguard Worker     // memory accesses and synchronization. If the invariant transitively
459*9356374aSAndroid Build Coastguard Worker     // synchronizes something else and we ignore the synchronization, we will
460*9356374aSAndroid Build Coastguard Worker     // get false positive race reports later.
461*9356374aSAndroid Build Coastguard Worker     // Reuse EvalConditionAnnotated to properly call into user code.
462*9356374aSAndroid Build Coastguard Worker     struct local {
463*9356374aSAndroid Build Coastguard Worker       static bool pred(SynchEvent* ev) {
464*9356374aSAndroid Build Coastguard Worker         (*ev->invariant)(ev->arg);
465*9356374aSAndroid Build Coastguard Worker         return false;
466*9356374aSAndroid Build Coastguard Worker       }
467*9356374aSAndroid Build Coastguard Worker     };
468*9356374aSAndroid Build Coastguard Worker     Condition cond(&local::pred, e);
469*9356374aSAndroid Build Coastguard Worker     Mutex* mu = static_cast<Mutex*>(obj);
470*9356374aSAndroid Build Coastguard Worker     const bool locking = (flags & SYNCH_F_UNLOCK) == 0;
471*9356374aSAndroid Build Coastguard Worker     const bool trylock = (flags & SYNCH_F_TRY) != 0;
472*9356374aSAndroid Build Coastguard Worker     const bool read_lock = (flags & SYNCH_F_R) != 0;
473*9356374aSAndroid Build Coastguard Worker     EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock);
474*9356374aSAndroid Build Coastguard Worker   }
475*9356374aSAndroid Build Coastguard Worker   UnrefSynchEvent(e);
476*9356374aSAndroid Build Coastguard Worker }
477*9356374aSAndroid Build Coastguard Worker 
478*9356374aSAndroid Build Coastguard Worker //------------------------------------------------------------------
479*9356374aSAndroid Build Coastguard Worker 
480*9356374aSAndroid Build Coastguard Worker // The SynchWaitParams struct encapsulates the way in which a thread is waiting:
481*9356374aSAndroid Build Coastguard Worker // whether it has a timeout, the condition, exclusive/shared, and whether a
482*9356374aSAndroid Build Coastguard Worker // condition variable wait has an associated Mutex (as opposed to another
483*9356374aSAndroid Build Coastguard Worker // type of lock).  It also points to the PerThreadSynch struct of its thread.
484*9356374aSAndroid Build Coastguard Worker // cv_word tells Enqueue() to enqueue on a CondVar using CondVarEnqueue().
485*9356374aSAndroid Build Coastguard Worker //
486*9356374aSAndroid Build Coastguard Worker // This structure is held on the stack rather than directly in
487*9356374aSAndroid Build Coastguard Worker // PerThreadSynch because a thread can be waiting on multiple Mutexes if,
488*9356374aSAndroid Build Coastguard Worker // while waiting on one Mutex, the implementation calls a client callback
489*9356374aSAndroid Build Coastguard Worker // (such as a Condition function) that acquires another Mutex. We don't
490*9356374aSAndroid Build Coastguard Worker // strictly need to allow this, but programmers become confused if we do not
491*9356374aSAndroid Build Coastguard Worker // allow them to use functions such a LOG() within Condition functions.  The
492*9356374aSAndroid Build Coastguard Worker // PerThreadSynch struct points at the most recent SynchWaitParams struct when
493*9356374aSAndroid Build Coastguard Worker // the thread is on a Mutex's waiter queue.
494*9356374aSAndroid Build Coastguard Worker struct SynchWaitParams {
SynchWaitParamsabsl::SynchWaitParams495*9356374aSAndroid Build Coastguard Worker   SynchWaitParams(Mutex::MuHow how_arg, const Condition* cond_arg,
496*9356374aSAndroid Build Coastguard Worker                   KernelTimeout timeout_arg, Mutex* cvmu_arg,
497*9356374aSAndroid Build Coastguard Worker                   PerThreadSynch* thread_arg,
498*9356374aSAndroid Build Coastguard Worker                   std::atomic<intptr_t>* cv_word_arg)
499*9356374aSAndroid Build Coastguard Worker       : how(how_arg),
500*9356374aSAndroid Build Coastguard Worker         cond(cond_arg),
501*9356374aSAndroid Build Coastguard Worker         timeout(timeout_arg),
502*9356374aSAndroid Build Coastguard Worker         cvmu(cvmu_arg),
503*9356374aSAndroid Build Coastguard Worker         thread(thread_arg),
504*9356374aSAndroid Build Coastguard Worker         cv_word(cv_word_arg),
505*9356374aSAndroid Build Coastguard Worker         contention_start_cycles(CycleClock::Now()),
506*9356374aSAndroid Build Coastguard Worker         should_submit_contention_data(false) {}
507*9356374aSAndroid Build Coastguard Worker 
508*9356374aSAndroid Build Coastguard Worker   const Mutex::MuHow how;  // How this thread needs to wait.
509*9356374aSAndroid Build Coastguard Worker   const Condition* cond;   // The condition that this thread is waiting for.
510*9356374aSAndroid Build Coastguard Worker                            // In Mutex, this field is set to zero if a timeout
511*9356374aSAndroid Build Coastguard Worker                            // expires.
512*9356374aSAndroid Build Coastguard Worker   KernelTimeout timeout;  // timeout expiry---absolute time
513*9356374aSAndroid Build Coastguard Worker                           // In Mutex, this field is set to zero if a timeout
514*9356374aSAndroid Build Coastguard Worker                           // expires.
515*9356374aSAndroid Build Coastguard Worker   Mutex* const cvmu;      // used for transfer from cond var to mutex
516*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* const thread;  // thread that is waiting
517*9356374aSAndroid Build Coastguard Worker 
518*9356374aSAndroid Build Coastguard Worker   // If not null, thread should be enqueued on the CondVar whose state
519*9356374aSAndroid Build Coastguard Worker   // word is cv_word instead of queueing normally on the Mutex.
520*9356374aSAndroid Build Coastguard Worker   std::atomic<intptr_t>* cv_word;
521*9356374aSAndroid Build Coastguard Worker 
522*9356374aSAndroid Build Coastguard Worker   int64_t contention_start_cycles;  // Time (in cycles) when this thread started
523*9356374aSAndroid Build Coastguard Worker                                     // to contend for the mutex.
524*9356374aSAndroid Build Coastguard Worker   bool should_submit_contention_data;
525*9356374aSAndroid Build Coastguard Worker };
526*9356374aSAndroid Build Coastguard Worker 
527*9356374aSAndroid Build Coastguard Worker struct SynchLocksHeld {
528*9356374aSAndroid Build Coastguard Worker   int n;          // number of valid entries in locks[]
529*9356374aSAndroid Build Coastguard Worker   bool overflow;  // true iff we overflowed the array at some point
530*9356374aSAndroid Build Coastguard Worker   struct {
531*9356374aSAndroid Build Coastguard Worker     Mutex* mu;      // lock acquired
532*9356374aSAndroid Build Coastguard Worker     int32_t count;  // times acquired
533*9356374aSAndroid Build Coastguard Worker     GraphId id;     // deadlock_graph id of acquired lock
534*9356374aSAndroid Build Coastguard Worker   } locks[40];
535*9356374aSAndroid Build Coastguard Worker   // If a thread overfills the array during deadlock detection, we
536*9356374aSAndroid Build Coastguard Worker   // continue, discarding information as needed.  If no overflow has
537*9356374aSAndroid Build Coastguard Worker   // taken place, we can provide more error checking, such as
538*9356374aSAndroid Build Coastguard Worker   // detecting when a thread releases a lock it does not hold.
539*9356374aSAndroid Build Coastguard Worker };
540*9356374aSAndroid Build Coastguard Worker 
541*9356374aSAndroid Build Coastguard Worker // A sentinel value in lists that is not 0.
542*9356374aSAndroid Build Coastguard Worker // A 0 value is used to mean "not on a list".
543*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* const kPerThreadSynchNull =
544*9356374aSAndroid Build Coastguard Worker     reinterpret_cast<PerThreadSynch*>(1);
545*9356374aSAndroid Build Coastguard Worker 
LocksHeldAlloc()546*9356374aSAndroid Build Coastguard Worker static SynchLocksHeld* LocksHeldAlloc() {
547*9356374aSAndroid Build Coastguard Worker   SynchLocksHeld* ret = reinterpret_cast<SynchLocksHeld*>(
548*9356374aSAndroid Build Coastguard Worker       base_internal::LowLevelAlloc::Alloc(sizeof(SynchLocksHeld)));
549*9356374aSAndroid Build Coastguard Worker   ret->n = 0;
550*9356374aSAndroid Build Coastguard Worker   ret->overflow = false;
551*9356374aSAndroid Build Coastguard Worker   return ret;
552*9356374aSAndroid Build Coastguard Worker }
553*9356374aSAndroid Build Coastguard Worker 
554*9356374aSAndroid Build Coastguard Worker // Return the PerThreadSynch-struct for this thread.
Synch_GetPerThread()555*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* Synch_GetPerThread() {
556*9356374aSAndroid Build Coastguard Worker   ThreadIdentity* identity = GetOrCreateCurrentThreadIdentity();
557*9356374aSAndroid Build Coastguard Worker   return &identity->per_thread_synch;
558*9356374aSAndroid Build Coastguard Worker }
559*9356374aSAndroid Build Coastguard Worker 
Synch_GetPerThreadAnnotated(Mutex * mu)560*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* Synch_GetPerThreadAnnotated(Mutex* mu) {
561*9356374aSAndroid Build Coastguard Worker   if (mu) {
562*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
563*9356374aSAndroid Build Coastguard Worker   }
564*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* w = Synch_GetPerThread();
565*9356374aSAndroid Build Coastguard Worker   if (mu) {
566*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
567*9356374aSAndroid Build Coastguard Worker   }
568*9356374aSAndroid Build Coastguard Worker   return w;
569*9356374aSAndroid Build Coastguard Worker }
570*9356374aSAndroid Build Coastguard Worker 
Synch_GetAllLocks()571*9356374aSAndroid Build Coastguard Worker static SynchLocksHeld* Synch_GetAllLocks() {
572*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* s = Synch_GetPerThread();
573*9356374aSAndroid Build Coastguard Worker   if (s->all_locks == nullptr) {
574*9356374aSAndroid Build Coastguard Worker     s->all_locks = LocksHeldAlloc();  // Freed by ReclaimThreadIdentity.
575*9356374aSAndroid Build Coastguard Worker   }
576*9356374aSAndroid Build Coastguard Worker   return s->all_locks;
577*9356374aSAndroid Build Coastguard Worker }
578*9356374aSAndroid Build Coastguard Worker 
579*9356374aSAndroid Build Coastguard Worker // Post on "w"'s associated PerThreadSem.
IncrementSynchSem(Mutex * mu,PerThreadSynch * w)580*9356374aSAndroid Build Coastguard Worker void Mutex::IncrementSynchSem(Mutex* mu, PerThreadSynch* w) {
581*9356374aSAndroid Build Coastguard Worker   static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.
582*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
583*9356374aSAndroid Build Coastguard Worker   // We miss synchronization around passing PerThreadSynch between threads
584*9356374aSAndroid Build Coastguard Worker   // since it happens inside of the Mutex code, so we need to ignore all
585*9356374aSAndroid Build Coastguard Worker   // accesses to the object.
586*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
587*9356374aSAndroid Build Coastguard Worker   PerThreadSem::Post(w->thread_identity());
588*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
589*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
590*9356374aSAndroid Build Coastguard Worker }
591*9356374aSAndroid Build Coastguard Worker 
592*9356374aSAndroid Build Coastguard Worker // Wait on "w"'s associated PerThreadSem; returns false if timeout expired.
DecrementSynchSem(Mutex * mu,PerThreadSynch * w,KernelTimeout t)593*9356374aSAndroid Build Coastguard Worker bool Mutex::DecrementSynchSem(Mutex* mu, PerThreadSynch* w, KernelTimeout t) {
594*9356374aSAndroid Build Coastguard Worker   static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.
595*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
596*9356374aSAndroid Build Coastguard Worker   assert(w == Synch_GetPerThread());
597*9356374aSAndroid Build Coastguard Worker   static_cast<void>(w);
598*9356374aSAndroid Build Coastguard Worker   bool res = PerThreadSem::Wait(t);
599*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
600*9356374aSAndroid Build Coastguard Worker   return res;
601*9356374aSAndroid Build Coastguard Worker }
602*9356374aSAndroid Build Coastguard Worker 
603*9356374aSAndroid Build Coastguard Worker // We're in a fatal signal handler that hopes to use Mutex and to get
604*9356374aSAndroid Build Coastguard Worker // lucky by not deadlocking.  We try to improve its chances of success
605*9356374aSAndroid Build Coastguard Worker // by effectively disabling some of the consistency checks.  This will
606*9356374aSAndroid Build Coastguard Worker // prevent certain ABSL_RAW_CHECK() statements from being triggered when
607*9356374aSAndroid Build Coastguard Worker // re-rentry is detected.  The ABSL_RAW_CHECK() statements are those in the
608*9356374aSAndroid Build Coastguard Worker // Mutex code checking that the "waitp" field has not been reused.
InternalAttemptToUseMutexInFatalSignalHandler()609*9356374aSAndroid Build Coastguard Worker void Mutex::InternalAttemptToUseMutexInFatalSignalHandler() {
610*9356374aSAndroid Build Coastguard Worker   // Fix the per-thread state only if it exists.
611*9356374aSAndroid Build Coastguard Worker   ThreadIdentity* identity = CurrentThreadIdentityIfPresent();
612*9356374aSAndroid Build Coastguard Worker   if (identity != nullptr) {
613*9356374aSAndroid Build Coastguard Worker     identity->per_thread_synch.suppress_fatal_errors = true;
614*9356374aSAndroid Build Coastguard Worker   }
615*9356374aSAndroid Build Coastguard Worker   // Don't do deadlock detection when we are already failing.
616*9356374aSAndroid Build Coastguard Worker   synch_deadlock_detection.store(OnDeadlockCycle::kIgnore,
617*9356374aSAndroid Build Coastguard Worker                                  std::memory_order_release);
618*9356374aSAndroid Build Coastguard Worker }
619*9356374aSAndroid Build Coastguard Worker 
620*9356374aSAndroid Build Coastguard Worker // --------------------------Mutexes
621*9356374aSAndroid Build Coastguard Worker 
622*9356374aSAndroid Build Coastguard Worker // In the layout below, the msb of the bottom byte is currently unused.  Also,
623*9356374aSAndroid Build Coastguard Worker // the following constraints were considered in choosing the layout:
624*9356374aSAndroid Build Coastguard Worker //  o Both the debug allocator's "uninitialized" and "freed" patterns (0xab and
625*9356374aSAndroid Build Coastguard Worker //    0xcd) are illegal: reader and writer lock both held.
626*9356374aSAndroid Build Coastguard Worker //  o kMuWriter and kMuEvent should exceed kMuDesig and kMuWait, to enable the
627*9356374aSAndroid Build Coastguard Worker //    bit-twiddling trick in Mutex::Unlock().
628*9356374aSAndroid Build Coastguard Worker //  o kMuWriter / kMuReader == kMuWrWait / kMuWait,
629*9356374aSAndroid Build Coastguard Worker //    to enable the bit-twiddling trick in CheckForMutexCorruption().
630*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuReader = 0x0001L;  // a reader holds the lock
631*9356374aSAndroid Build Coastguard Worker // There's a designated waker.
632*9356374aSAndroid Build Coastguard Worker // INVARIANT1:  there's a thread that was blocked on the mutex, is
633*9356374aSAndroid Build Coastguard Worker // no longer, yet has not yet acquired the mutex.  If there's a
634*9356374aSAndroid Build Coastguard Worker // designated waker, all threads can avoid taking the slow path in
635*9356374aSAndroid Build Coastguard Worker // unlock because the designated waker will subsequently acquire
636*9356374aSAndroid Build Coastguard Worker // the lock and wake someone.  To maintain INVARIANT1 the bit is
637*9356374aSAndroid Build Coastguard Worker // set when a thread is unblocked(INV1a), and threads that were
638*9356374aSAndroid Build Coastguard Worker // unblocked reset the bit when they either acquire or re-block (INV1b).
639*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuDesig = 0x0002L;
640*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuWait = 0x0004L;    // threads are waiting
641*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuWriter = 0x0008L;  // a writer holds the lock
642*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuEvent = 0x0010L;   // record this mutex's events
643*9356374aSAndroid Build Coastguard Worker // Runnable writer is waiting for a reader.
644*9356374aSAndroid Build Coastguard Worker // If set, new readers will not lock the mutex to avoid writer starvation.
645*9356374aSAndroid Build Coastguard Worker // Note: if a reader has higher priority than the writer, it will still lock
646*9356374aSAndroid Build Coastguard Worker // the mutex ahead of the waiting writer, but in a very inefficient manner:
647*9356374aSAndroid Build Coastguard Worker // the reader will first queue itself and block, but then the last unlocking
648*9356374aSAndroid Build Coastguard Worker // reader will wake it.
649*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuWrWait = 0x0020L;
650*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuSpin = 0x0040L;  // spinlock protects wait list
651*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuLow = 0x00ffL;   // mask all mutex bits
652*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuHigh = ~kMuLow;  // mask pointer/reader count
653*9356374aSAndroid Build Coastguard Worker 
654*9356374aSAndroid Build Coastguard Worker // Hack to make constant values available to gdb pretty printer
655*9356374aSAndroid Build Coastguard Worker enum {
656*9356374aSAndroid Build Coastguard Worker   kGdbMuSpin = kMuSpin,
657*9356374aSAndroid Build Coastguard Worker   kGdbMuEvent = kMuEvent,
658*9356374aSAndroid Build Coastguard Worker   kGdbMuWait = kMuWait,
659*9356374aSAndroid Build Coastguard Worker   kGdbMuWriter = kMuWriter,
660*9356374aSAndroid Build Coastguard Worker   kGdbMuDesig = kMuDesig,
661*9356374aSAndroid Build Coastguard Worker   kGdbMuWrWait = kMuWrWait,
662*9356374aSAndroid Build Coastguard Worker   kGdbMuReader = kMuReader,
663*9356374aSAndroid Build Coastguard Worker   kGdbMuLow = kMuLow,
664*9356374aSAndroid Build Coastguard Worker };
665*9356374aSAndroid Build Coastguard Worker 
666*9356374aSAndroid Build Coastguard Worker // kMuWrWait implies kMuWait.
667*9356374aSAndroid Build Coastguard Worker // kMuReader and kMuWriter are mutually exclusive.
668*9356374aSAndroid Build Coastguard Worker // If kMuReader is zero, there are no readers.
669*9356374aSAndroid Build Coastguard Worker // Otherwise, if kMuWait is zero, the high order bits contain a count of the
670*9356374aSAndroid Build Coastguard Worker // number of readers.  Otherwise, the reader count is held in
671*9356374aSAndroid Build Coastguard Worker // PerThreadSynch::readers of the most recently queued waiter, again in the
672*9356374aSAndroid Build Coastguard Worker // bits above kMuLow.
673*9356374aSAndroid Build Coastguard Worker static const intptr_t kMuOne = 0x0100;  // a count of one reader
674*9356374aSAndroid Build Coastguard Worker 
675*9356374aSAndroid Build Coastguard Worker // flags passed to Enqueue and LockSlow{,WithTimeout,Loop}
676*9356374aSAndroid Build Coastguard Worker static const int kMuHasBlocked = 0x01;  // already blocked (MUST == 1)
677*9356374aSAndroid Build Coastguard Worker static const int kMuIsCond = 0x02;      // conditional waiter (CV or Condition)
678*9356374aSAndroid Build Coastguard Worker static const int kMuIsFer = 0x04;       // wait morphing from a CondVar
679*9356374aSAndroid Build Coastguard Worker 
680*9356374aSAndroid Build Coastguard Worker static_assert(PerThreadSynch::kAlignment > kMuLow,
681*9356374aSAndroid Build Coastguard Worker               "PerThreadSynch::kAlignment must be greater than kMuLow");
682*9356374aSAndroid Build Coastguard Worker 
683*9356374aSAndroid Build Coastguard Worker // This struct contains various bitmasks to be used in
684*9356374aSAndroid Build Coastguard Worker // acquiring and releasing a mutex in a particular mode.
685*9356374aSAndroid Build Coastguard Worker struct MuHowS {
686*9356374aSAndroid Build Coastguard Worker   // if all the bits in fast_need_zero are zero, the lock can be acquired by
687*9356374aSAndroid Build Coastguard Worker   // adding fast_add and oring fast_or.  The bit kMuDesig should be reset iff
688*9356374aSAndroid Build Coastguard Worker   // this is the designated waker.
689*9356374aSAndroid Build Coastguard Worker   intptr_t fast_need_zero;
690*9356374aSAndroid Build Coastguard Worker   intptr_t fast_or;
691*9356374aSAndroid Build Coastguard Worker   intptr_t fast_add;
692*9356374aSAndroid Build Coastguard Worker 
693*9356374aSAndroid Build Coastguard Worker   intptr_t slow_need_zero;  // fast_need_zero with events (e.g. logging)
694*9356374aSAndroid Build Coastguard Worker 
695*9356374aSAndroid Build Coastguard Worker   intptr_t slow_inc_need_zero;  // if all the bits in slow_inc_need_zero are
696*9356374aSAndroid Build Coastguard Worker                                 // zero a reader can acquire a read share by
697*9356374aSAndroid Build Coastguard Worker                                 // setting the reader bit and incrementing
698*9356374aSAndroid Build Coastguard Worker                                 // the reader count (in last waiter since
699*9356374aSAndroid Build Coastguard Worker                                 // we're now slow-path).  kMuWrWait be may
700*9356374aSAndroid Build Coastguard Worker                                 // be ignored if we already waited once.
701*9356374aSAndroid Build Coastguard Worker };
702*9356374aSAndroid Build Coastguard Worker 
703*9356374aSAndroid Build Coastguard Worker static const MuHowS kSharedS = {
704*9356374aSAndroid Build Coastguard Worker     // shared or read lock
705*9356374aSAndroid Build Coastguard Worker     kMuWriter | kMuWait | kMuEvent,   // fast_need_zero
706*9356374aSAndroid Build Coastguard Worker     kMuReader,                        // fast_or
707*9356374aSAndroid Build Coastguard Worker     kMuOne,                           // fast_add
708*9356374aSAndroid Build Coastguard Worker     kMuWriter | kMuWait,              // slow_need_zero
709*9356374aSAndroid Build Coastguard Worker     kMuSpin | kMuWriter | kMuWrWait,  // slow_inc_need_zero
710*9356374aSAndroid Build Coastguard Worker };
711*9356374aSAndroid Build Coastguard Worker static const MuHowS kExclusiveS = {
712*9356374aSAndroid Build Coastguard Worker     // exclusive or write lock
713*9356374aSAndroid Build Coastguard Worker     kMuWriter | kMuReader | kMuEvent,  // fast_need_zero
714*9356374aSAndroid Build Coastguard Worker     kMuWriter,                         // fast_or
715*9356374aSAndroid Build Coastguard Worker     0,                                 // fast_add
716*9356374aSAndroid Build Coastguard Worker     kMuWriter | kMuReader,             // slow_need_zero
717*9356374aSAndroid Build Coastguard Worker     ~static_cast<intptr_t>(0),         // slow_inc_need_zero
718*9356374aSAndroid Build Coastguard Worker };
719*9356374aSAndroid Build Coastguard Worker static const Mutex::MuHow kShared = &kSharedS;        // shared lock
720*9356374aSAndroid Build Coastguard Worker static const Mutex::MuHow kExclusive = &kExclusiveS;  // exclusive lock
721*9356374aSAndroid Build Coastguard Worker 
722*9356374aSAndroid Build Coastguard Worker #ifdef NDEBUG
723*9356374aSAndroid Build Coastguard Worker static constexpr bool kDebugMode = false;
724*9356374aSAndroid Build Coastguard Worker #else
725*9356374aSAndroid Build Coastguard Worker static constexpr bool kDebugMode = true;
726*9356374aSAndroid Build Coastguard Worker #endif
727*9356374aSAndroid Build Coastguard Worker 
728*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
TsanFlags(Mutex::MuHow how)729*9356374aSAndroid Build Coastguard Worker static unsigned TsanFlags(Mutex::MuHow how) {
730*9356374aSAndroid Build Coastguard Worker   return how == kShared ? __tsan_mutex_read_lock : 0;
731*9356374aSAndroid Build Coastguard Worker }
732*9356374aSAndroid Build Coastguard Worker #endif
733*9356374aSAndroid Build Coastguard Worker 
734*9356374aSAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(ABSL_BUILD_DLL)
735*9356374aSAndroid Build Coastguard Worker // When building a dll symbol export lists may reference the destructor
736*9356374aSAndroid Build Coastguard Worker // and want it to be an exported symbol rather than an inline function.
737*9356374aSAndroid Build Coastguard Worker // Some apple builds also do dynamic library build but don't say it explicitly.
~Mutex()738*9356374aSAndroid Build Coastguard Worker Mutex::~Mutex() { Dtor(); }
739*9356374aSAndroid Build Coastguard Worker #endif
740*9356374aSAndroid Build Coastguard Worker 
741*9356374aSAndroid Build Coastguard Worker #if !defined(NDEBUG) || defined(ABSL_HAVE_THREAD_SANITIZER)
Dtor()742*9356374aSAndroid Build Coastguard Worker void Mutex::Dtor() {
743*9356374aSAndroid Build Coastguard Worker   if (kDebugMode) {
744*9356374aSAndroid Build Coastguard Worker     this->ForgetDeadlockInfo();
745*9356374aSAndroid Build Coastguard Worker   }
746*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static);
747*9356374aSAndroid Build Coastguard Worker }
748*9356374aSAndroid Build Coastguard Worker #endif
749*9356374aSAndroid Build Coastguard Worker 
EnableDebugLog(const char * name)750*9356374aSAndroid Build Coastguard Worker void Mutex::EnableDebugLog(const char* name) {
751*9356374aSAndroid Build Coastguard Worker   // Need to disable writes here and in EnableInvariantDebugging to prevent
752*9356374aSAndroid Build Coastguard Worker   // false race reports on SynchEvent objects. TSan ignores synchronization
753*9356374aSAndroid Build Coastguard Worker   // on synch_event_mu in Lock/Unlock/etc methods due to mutex annotations,
754*9356374aSAndroid Build Coastguard Worker   // but it sees few accesses to SynchEvent in EvalConditionAnnotated.
755*9356374aSAndroid Build Coastguard Worker   // If we don't ignore accesses here, it can result in false races
756*9356374aSAndroid Build Coastguard Worker   // between EvalConditionAnnotated and SynchEvent reuse in EnsureSynchEvent.
757*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_WRITES_BEGIN();
758*9356374aSAndroid Build Coastguard Worker   SynchEvent* e = EnsureSynchEvent(&this->mu_, name, kMuEvent, kMuSpin);
759*9356374aSAndroid Build Coastguard Worker   e->log = true;
760*9356374aSAndroid Build Coastguard Worker   UnrefSynchEvent(e);
761*9356374aSAndroid Build Coastguard Worker   // This prevents "error: undefined symbol: absl::Mutex::~Mutex()"
762*9356374aSAndroid Build Coastguard Worker   // in a release build (NDEBUG defined) when a test does "#undef NDEBUG"
763*9356374aSAndroid Build Coastguard Worker   // to use assert macro. In such case, the test does not get the dtor
764*9356374aSAndroid Build Coastguard Worker   // definition because it's supposed to be outline when NDEBUG is not defined,
765*9356374aSAndroid Build Coastguard Worker   // and this source file does not define one either because NDEBUG is defined.
766*9356374aSAndroid Build Coastguard Worker   // Since it's not possible to take address of a destructor, we move the
767*9356374aSAndroid Build Coastguard Worker   // actual destructor code into the separate Dtor function and force the
768*9356374aSAndroid Build Coastguard Worker   // compiler to emit this function even if it's inline by taking its address.
769*9356374aSAndroid Build Coastguard Worker   ABSL_ATTRIBUTE_UNUSED volatile auto dtor = &Mutex::Dtor;
770*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_WRITES_END();
771*9356374aSAndroid Build Coastguard Worker }
772*9356374aSAndroid Build Coastguard Worker 
EnableMutexInvariantDebugging(bool enabled)773*9356374aSAndroid Build Coastguard Worker void EnableMutexInvariantDebugging(bool enabled) {
774*9356374aSAndroid Build Coastguard Worker   synch_check_invariants.store(enabled, std::memory_order_release);
775*9356374aSAndroid Build Coastguard Worker }
776*9356374aSAndroid Build Coastguard Worker 
EnableInvariantDebugging(void (* invariant)(void *),void * arg)777*9356374aSAndroid Build Coastguard Worker void Mutex::EnableInvariantDebugging(void (*invariant)(void*), void* arg) {
778*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_WRITES_BEGIN();
779*9356374aSAndroid Build Coastguard Worker   if (synch_check_invariants.load(std::memory_order_acquire) &&
780*9356374aSAndroid Build Coastguard Worker       invariant != nullptr) {
781*9356374aSAndroid Build Coastguard Worker     SynchEvent* e = EnsureSynchEvent(&this->mu_, nullptr, kMuEvent, kMuSpin);
782*9356374aSAndroid Build Coastguard Worker     e->invariant = invariant;
783*9356374aSAndroid Build Coastguard Worker     e->arg = arg;
784*9356374aSAndroid Build Coastguard Worker     UnrefSynchEvent(e);
785*9356374aSAndroid Build Coastguard Worker   }
786*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_WRITES_END();
787*9356374aSAndroid Build Coastguard Worker }
788*9356374aSAndroid Build Coastguard Worker 
SetMutexDeadlockDetectionMode(OnDeadlockCycle mode)789*9356374aSAndroid Build Coastguard Worker void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) {
790*9356374aSAndroid Build Coastguard Worker   synch_deadlock_detection.store(mode, std::memory_order_release);
791*9356374aSAndroid Build Coastguard Worker }
792*9356374aSAndroid Build Coastguard Worker 
793*9356374aSAndroid Build Coastguard Worker // Return true iff threads x and y are part of the same equivalence
794*9356374aSAndroid Build Coastguard Worker // class of waiters. An equivalence class is defined as the set of
795*9356374aSAndroid Build Coastguard Worker // waiters with the same condition, type of lock, and thread priority.
796*9356374aSAndroid Build Coastguard Worker //
797*9356374aSAndroid Build Coastguard Worker // Requires that x and y be waiting on the same Mutex queue.
MuEquivalentWaiter(PerThreadSynch * x,PerThreadSynch * y)798*9356374aSAndroid Build Coastguard Worker static bool MuEquivalentWaiter(PerThreadSynch* x, PerThreadSynch* y) {
799*9356374aSAndroid Build Coastguard Worker   return x->waitp->how == y->waitp->how && x->priority == y->priority &&
800*9356374aSAndroid Build Coastguard Worker          Condition::GuaranteedEqual(x->waitp->cond, y->waitp->cond);
801*9356374aSAndroid Build Coastguard Worker }
802*9356374aSAndroid Build Coastguard Worker 
803*9356374aSAndroid Build Coastguard Worker // Given the contents of a mutex word containing a PerThreadSynch pointer,
804*9356374aSAndroid Build Coastguard Worker // return the pointer.
GetPerThreadSynch(intptr_t v)805*9356374aSAndroid Build Coastguard Worker static inline PerThreadSynch* GetPerThreadSynch(intptr_t v) {
806*9356374aSAndroid Build Coastguard Worker   return reinterpret_cast<PerThreadSynch*>(v & kMuHigh);
807*9356374aSAndroid Build Coastguard Worker }
808*9356374aSAndroid Build Coastguard Worker 
809*9356374aSAndroid Build Coastguard Worker // The next several routines maintain the per-thread next and skip fields
810*9356374aSAndroid Build Coastguard Worker // used in the Mutex waiter queue.
811*9356374aSAndroid Build Coastguard Worker // The queue is a circular singly-linked list, of which the "head" is the
812*9356374aSAndroid Build Coastguard Worker // last element, and head->next if the first element.
813*9356374aSAndroid Build Coastguard Worker // The skip field has the invariant:
814*9356374aSAndroid Build Coastguard Worker //   For thread x, x->skip is one of:
815*9356374aSAndroid Build Coastguard Worker //     - invalid (iff x is not in a Mutex wait queue),
816*9356374aSAndroid Build Coastguard Worker //     - null, or
817*9356374aSAndroid Build Coastguard Worker //     - a pointer to a distinct thread waiting later in the same Mutex queue
818*9356374aSAndroid Build Coastguard Worker //       such that all threads in [x, x->skip] have the same condition, priority
819*9356374aSAndroid Build Coastguard Worker //       and lock type (MuEquivalentWaiter() is true for all pairs in [x,
820*9356374aSAndroid Build Coastguard Worker //       x->skip]).
821*9356374aSAndroid Build Coastguard Worker // In addition, if x->skip is  valid, (x->may_skip || x->skip == null)
822*9356374aSAndroid Build Coastguard Worker //
823*9356374aSAndroid Build Coastguard Worker // By the spec of MuEquivalentWaiter(), it is not necessary when removing the
824*9356374aSAndroid Build Coastguard Worker // first runnable thread y from the front a Mutex queue to adjust the skip
825*9356374aSAndroid Build Coastguard Worker // field of another thread x because if x->skip==y, x->skip must (have) become
826*9356374aSAndroid Build Coastguard Worker // invalid before y is removed.  The function TryRemove can remove a specified
827*9356374aSAndroid Build Coastguard Worker // thread from an arbitrary position in the queue whether runnable or not, so
828*9356374aSAndroid Build Coastguard Worker // it fixes up skip fields that would otherwise be left dangling.
829*9356374aSAndroid Build Coastguard Worker // The statement
830*9356374aSAndroid Build Coastguard Worker //     if (x->may_skip && MuEquivalentWaiter(x, x->next)) { x->skip = x->next; }
831*9356374aSAndroid Build Coastguard Worker // maintains the invariant provided x is not the last waiter in a Mutex queue
832*9356374aSAndroid Build Coastguard Worker // The statement
833*9356374aSAndroid Build Coastguard Worker //          if (x->skip != null) { x->skip = x->skip->skip; }
834*9356374aSAndroid Build Coastguard Worker // maintains the invariant.
835*9356374aSAndroid Build Coastguard Worker 
836*9356374aSAndroid Build Coastguard Worker // Returns the last thread y in a mutex waiter queue such that all threads in
837*9356374aSAndroid Build Coastguard Worker // [x, y] inclusive share the same condition.  Sets skip fields of some threads
838*9356374aSAndroid Build Coastguard Worker // in that range to optimize future evaluation of Skip() on x values in
839*9356374aSAndroid Build Coastguard Worker // the range.  Requires thread x is in a mutex waiter queue.
840*9356374aSAndroid Build Coastguard Worker // The locking is unusual.  Skip() is called under these conditions:
841*9356374aSAndroid Build Coastguard Worker //   - spinlock is held in call from Enqueue(), with maybe_unlocking == false
842*9356374aSAndroid Build Coastguard Worker //   - Mutex is held in call from UnlockSlow() by last unlocker, with
843*9356374aSAndroid Build Coastguard Worker //     maybe_unlocking == true
844*9356374aSAndroid Build Coastguard Worker //   - both Mutex and spinlock are held in call from DequeueAllWakeable() (from
845*9356374aSAndroid Build Coastguard Worker //     UnlockSlow()) and TryRemove()
846*9356374aSAndroid Build Coastguard Worker // These cases are mutually exclusive, so Skip() never runs concurrently
847*9356374aSAndroid Build Coastguard Worker // with itself on the same Mutex.   The skip chain is used in these other places
848*9356374aSAndroid Build Coastguard Worker // that cannot occur concurrently:
849*9356374aSAndroid Build Coastguard Worker //   - FixSkip() (from TryRemove()) - spinlock and Mutex are held)
850*9356374aSAndroid Build Coastguard Worker //   - Dequeue() (with spinlock and Mutex held)
851*9356374aSAndroid Build Coastguard Worker //   - UnlockSlow() (with spinlock and Mutex held)
852*9356374aSAndroid Build Coastguard Worker // A more complex case is Enqueue()
853*9356374aSAndroid Build Coastguard Worker //   - Enqueue() (with spinlock held and maybe_unlocking == false)
854*9356374aSAndroid Build Coastguard Worker //               This is the first case in which Skip is called, above.
855*9356374aSAndroid Build Coastguard Worker //   - Enqueue() (without spinlock held; but queue is empty and being freshly
856*9356374aSAndroid Build Coastguard Worker //                formed)
857*9356374aSAndroid Build Coastguard Worker //   - Enqueue() (with spinlock held and maybe_unlocking == true)
858*9356374aSAndroid Build Coastguard Worker // The first case has mutual exclusion, and the second isolation through
859*9356374aSAndroid Build Coastguard Worker // working on an otherwise unreachable data structure.
860*9356374aSAndroid Build Coastguard Worker // In the last case, Enqueue() is required to change no skip/next pointers
861*9356374aSAndroid Build Coastguard Worker // except those in the added node and the former "head" node.  This implies
862*9356374aSAndroid Build Coastguard Worker // that the new node is added after head, and so must be the new head or the
863*9356374aSAndroid Build Coastguard Worker // new front of the queue.
Skip(PerThreadSynch * x)864*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* Skip(PerThreadSynch* x) {
865*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* x0 = nullptr;
866*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* x1 = x;
867*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* x2 = x->skip;
868*9356374aSAndroid Build Coastguard Worker   if (x2 != nullptr) {
869*9356374aSAndroid Build Coastguard Worker     // Each iteration attempts to advance sequence (x0,x1,x2) to next sequence
870*9356374aSAndroid Build Coastguard Worker     // such that   x1 == x0->skip && x2 == x1->skip
871*9356374aSAndroid Build Coastguard Worker     while ((x0 = x1, x1 = x2, x2 = x2->skip) != nullptr) {
872*9356374aSAndroid Build Coastguard Worker       x0->skip = x2;  // short-circuit skip from x0 to x2
873*9356374aSAndroid Build Coastguard Worker     }
874*9356374aSAndroid Build Coastguard Worker     x->skip = x1;  // short-circuit skip from x to result
875*9356374aSAndroid Build Coastguard Worker   }
876*9356374aSAndroid Build Coastguard Worker   return x1;
877*9356374aSAndroid Build Coastguard Worker }
878*9356374aSAndroid Build Coastguard Worker 
879*9356374aSAndroid Build Coastguard Worker // "ancestor" appears before "to_be_removed" in the same Mutex waiter queue.
880*9356374aSAndroid Build Coastguard Worker // The latter is going to be removed out of order, because of a timeout.
881*9356374aSAndroid Build Coastguard Worker // Check whether "ancestor" has a skip field pointing to "to_be_removed",
882*9356374aSAndroid Build Coastguard Worker // and fix it if it does.
FixSkip(PerThreadSynch * ancestor,PerThreadSynch * to_be_removed)883*9356374aSAndroid Build Coastguard Worker static void FixSkip(PerThreadSynch* ancestor, PerThreadSynch* to_be_removed) {
884*9356374aSAndroid Build Coastguard Worker   if (ancestor->skip == to_be_removed) {  // ancestor->skip left dangling
885*9356374aSAndroid Build Coastguard Worker     if (to_be_removed->skip != nullptr) {
886*9356374aSAndroid Build Coastguard Worker       ancestor->skip = to_be_removed->skip;  // can skip past to_be_removed
887*9356374aSAndroid Build Coastguard Worker     } else if (ancestor->next != to_be_removed) {  // they are not adjacent
888*9356374aSAndroid Build Coastguard Worker       ancestor->skip = ancestor->next;             // can skip one past ancestor
889*9356374aSAndroid Build Coastguard Worker     } else {
890*9356374aSAndroid Build Coastguard Worker       ancestor->skip = nullptr;  // can't skip at all
891*9356374aSAndroid Build Coastguard Worker     }
892*9356374aSAndroid Build Coastguard Worker   }
893*9356374aSAndroid Build Coastguard Worker }
894*9356374aSAndroid Build Coastguard Worker 
895*9356374aSAndroid Build Coastguard Worker static void CondVarEnqueue(SynchWaitParams* waitp);
896*9356374aSAndroid Build Coastguard Worker 
897*9356374aSAndroid Build Coastguard Worker // Enqueue thread "waitp->thread" on a waiter queue.
898*9356374aSAndroid Build Coastguard Worker // Called with mutex spinlock held if head != nullptr
899*9356374aSAndroid Build Coastguard Worker // If head==nullptr and waitp->cv_word==nullptr, then Enqueue() is
900*9356374aSAndroid Build Coastguard Worker // idempotent; it alters no state associated with the existing (empty)
901*9356374aSAndroid Build Coastguard Worker // queue.
902*9356374aSAndroid Build Coastguard Worker //
903*9356374aSAndroid Build Coastguard Worker // If waitp->cv_word == nullptr, queue the thread at either the front or
904*9356374aSAndroid Build Coastguard Worker // the end (according to its priority) of the circular mutex waiter queue whose
905*9356374aSAndroid Build Coastguard Worker // head is "head", and return the new head.  mu is the previous mutex state,
906*9356374aSAndroid Build Coastguard Worker // which contains the reader count (perhaps adjusted for the operation in
907*9356374aSAndroid Build Coastguard Worker // progress) if the list was empty and a read lock held, and the holder hint if
908*9356374aSAndroid Build Coastguard Worker // the list was empty and a write lock held.  (flags & kMuIsCond) indicates
909*9356374aSAndroid Build Coastguard Worker // whether this thread was transferred from a CondVar or is waiting for a
910*9356374aSAndroid Build Coastguard Worker // non-trivial condition.  In this case, Enqueue() never returns nullptr
911*9356374aSAndroid Build Coastguard Worker //
912*9356374aSAndroid Build Coastguard Worker // If waitp->cv_word != nullptr, CondVarEnqueue() is called, and "head" is
913*9356374aSAndroid Build Coastguard Worker // returned. This mechanism is used by CondVar to queue a thread on the
914*9356374aSAndroid Build Coastguard Worker // condition variable queue instead of the mutex queue in implementing Wait().
915*9356374aSAndroid Build Coastguard Worker // In this case, Enqueue() can return nullptr (if head==nullptr).
Enqueue(PerThreadSynch * head,SynchWaitParams * waitp,intptr_t mu,int flags)916*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* Enqueue(PerThreadSynch* head, SynchWaitParams* waitp,
917*9356374aSAndroid Build Coastguard Worker                                intptr_t mu, int flags) {
918*9356374aSAndroid Build Coastguard Worker   // If we have been given a cv_word, call CondVarEnqueue() and return
919*9356374aSAndroid Build Coastguard Worker   // the previous head of the Mutex waiter queue.
920*9356374aSAndroid Build Coastguard Worker   if (waitp->cv_word != nullptr) {
921*9356374aSAndroid Build Coastguard Worker     CondVarEnqueue(waitp);
922*9356374aSAndroid Build Coastguard Worker     return head;
923*9356374aSAndroid Build Coastguard Worker   }
924*9356374aSAndroid Build Coastguard Worker 
925*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* s = waitp->thread;
926*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(
927*9356374aSAndroid Build Coastguard Worker       s->waitp == nullptr ||    // normal case
928*9356374aSAndroid Build Coastguard Worker           s->waitp == waitp ||  // Fer()---transfer from condition variable
929*9356374aSAndroid Build Coastguard Worker           s->suppress_fatal_errors,
930*9356374aSAndroid Build Coastguard Worker       "detected illegal recursion into Mutex code");
931*9356374aSAndroid Build Coastguard Worker   s->waitp = waitp;
932*9356374aSAndroid Build Coastguard Worker   s->skip = nullptr;   // maintain skip invariant (see above)
933*9356374aSAndroid Build Coastguard Worker   s->may_skip = true;  // always true on entering queue
934*9356374aSAndroid Build Coastguard Worker   s->wake = false;     // not being woken
935*9356374aSAndroid Build Coastguard Worker   s->cond_waiter = ((flags & kMuIsCond) != 0);
936*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
937*9356374aSAndroid Build Coastguard Worker   if ((flags & kMuIsFer) == 0) {
938*9356374aSAndroid Build Coastguard Worker     assert(s == Synch_GetPerThread());
939*9356374aSAndroid Build Coastguard Worker     int64_t now_cycles = CycleClock::Now();
940*9356374aSAndroid Build Coastguard Worker     if (s->next_priority_read_cycles < now_cycles) {
941*9356374aSAndroid Build Coastguard Worker       // Every so often, update our idea of the thread's priority.
942*9356374aSAndroid Build Coastguard Worker       // pthread_getschedparam() is 5% of the block/wakeup time;
943*9356374aSAndroid Build Coastguard Worker       // CycleClock::Now() is 0.5%.
944*9356374aSAndroid Build Coastguard Worker       int policy;
945*9356374aSAndroid Build Coastguard Worker       struct sched_param param;
946*9356374aSAndroid Build Coastguard Worker       const int err = pthread_getschedparam(pthread_self(), &policy, &param);
947*9356374aSAndroid Build Coastguard Worker       if (err != 0) {
948*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err);
949*9356374aSAndroid Build Coastguard Worker       } else {
950*9356374aSAndroid Build Coastguard Worker         s->priority = param.sched_priority;
951*9356374aSAndroid Build Coastguard Worker         s->next_priority_read_cycles =
952*9356374aSAndroid Build Coastguard Worker             now_cycles + static_cast<int64_t>(CycleClock::Frequency());
953*9356374aSAndroid Build Coastguard Worker       }
954*9356374aSAndroid Build Coastguard Worker     }
955*9356374aSAndroid Build Coastguard Worker   }
956*9356374aSAndroid Build Coastguard Worker #endif
957*9356374aSAndroid Build Coastguard Worker   if (head == nullptr) {         // s is the only waiter
958*9356374aSAndroid Build Coastguard Worker     s->next = s;                 // it's the only entry in the cycle
959*9356374aSAndroid Build Coastguard Worker     s->readers = mu;             // reader count is from mu word
960*9356374aSAndroid Build Coastguard Worker     s->maybe_unlocking = false;  // no one is searching an empty list
961*9356374aSAndroid Build Coastguard Worker     head = s;                    // s is new head
962*9356374aSAndroid Build Coastguard Worker   } else {
963*9356374aSAndroid Build Coastguard Worker     PerThreadSynch* enqueue_after = nullptr;  // we'll put s after this element
964*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
965*9356374aSAndroid Build Coastguard Worker     if (s->priority > head->priority) {  // s's priority is above head's
966*9356374aSAndroid Build Coastguard Worker       // try to put s in priority-fifo order, or failing that at the front.
967*9356374aSAndroid Build Coastguard Worker       if (!head->maybe_unlocking) {
968*9356374aSAndroid Build Coastguard Worker         // No unlocker can be scanning the queue, so we can insert into the
969*9356374aSAndroid Build Coastguard Worker         // middle of the queue.
970*9356374aSAndroid Build Coastguard Worker         //
971*9356374aSAndroid Build Coastguard Worker         // Within a skip chain, all waiters have the same priority, so we can
972*9356374aSAndroid Build Coastguard Worker         // skip forward through the chains until we find one with a lower
973*9356374aSAndroid Build Coastguard Worker         // priority than the waiter to be enqueued.
974*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* advance_to = head;  // next value of enqueue_after
975*9356374aSAndroid Build Coastguard Worker         do {
976*9356374aSAndroid Build Coastguard Worker           enqueue_after = advance_to;
977*9356374aSAndroid Build Coastguard Worker           // (side-effect: optimizes skip chain)
978*9356374aSAndroid Build Coastguard Worker           advance_to = Skip(enqueue_after->next);
979*9356374aSAndroid Build Coastguard Worker         } while (s->priority <= advance_to->priority);
980*9356374aSAndroid Build Coastguard Worker         // termination guaranteed because s->priority > head->priority
981*9356374aSAndroid Build Coastguard Worker         // and head is the end of a skip chain
982*9356374aSAndroid Build Coastguard Worker       } else if (waitp->how == kExclusive && waitp->cond == nullptr) {
983*9356374aSAndroid Build Coastguard Worker         // An unlocker could be scanning the queue, but we know it will recheck
984*9356374aSAndroid Build Coastguard Worker         // the queue front for writers that have no condition, which is what s
985*9356374aSAndroid Build Coastguard Worker         // is, so an insert at front is safe.
986*9356374aSAndroid Build Coastguard Worker         enqueue_after = head;  // add after head, at front
987*9356374aSAndroid Build Coastguard Worker       }
988*9356374aSAndroid Build Coastguard Worker     }
989*9356374aSAndroid Build Coastguard Worker #endif
990*9356374aSAndroid Build Coastguard Worker     if (enqueue_after != nullptr) {
991*9356374aSAndroid Build Coastguard Worker       s->next = enqueue_after->next;
992*9356374aSAndroid Build Coastguard Worker       enqueue_after->next = s;
993*9356374aSAndroid Build Coastguard Worker 
994*9356374aSAndroid Build Coastguard Worker       // enqueue_after can be: head, Skip(...), or cur.
995*9356374aSAndroid Build Coastguard Worker       // The first two imply enqueue_after->skip == nullptr, and
996*9356374aSAndroid Build Coastguard Worker       // the last is used only if MuEquivalentWaiter(s, cur).
997*9356374aSAndroid Build Coastguard Worker       // We require this because clearing enqueue_after->skip
998*9356374aSAndroid Build Coastguard Worker       // is impossible; enqueue_after's predecessors might also
999*9356374aSAndroid Build Coastguard Worker       // incorrectly skip over s if we were to allow other
1000*9356374aSAndroid Build Coastguard Worker       // insertion points.
1001*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_CHECK(enqueue_after->skip == nullptr ||
1002*9356374aSAndroid Build Coastguard Worker                          MuEquivalentWaiter(enqueue_after, s),
1003*9356374aSAndroid Build Coastguard Worker                      "Mutex Enqueue failure");
1004*9356374aSAndroid Build Coastguard Worker 
1005*9356374aSAndroid Build Coastguard Worker       if (enqueue_after != head && enqueue_after->may_skip &&
1006*9356374aSAndroid Build Coastguard Worker           MuEquivalentWaiter(enqueue_after, enqueue_after->next)) {
1007*9356374aSAndroid Build Coastguard Worker         // enqueue_after can skip to its new successor, s
1008*9356374aSAndroid Build Coastguard Worker         enqueue_after->skip = enqueue_after->next;
1009*9356374aSAndroid Build Coastguard Worker       }
1010*9356374aSAndroid Build Coastguard Worker       if (MuEquivalentWaiter(s, s->next)) {  // s->may_skip is known to be true
1011*9356374aSAndroid Build Coastguard Worker         s->skip = s->next;                   // s may skip to its successor
1012*9356374aSAndroid Build Coastguard Worker       }
1013*9356374aSAndroid Build Coastguard Worker     } else if ((flags & kMuHasBlocked) &&
1014*9356374aSAndroid Build Coastguard Worker                (s->priority >= head->next->priority) &&
1015*9356374aSAndroid Build Coastguard Worker                (!head->maybe_unlocking ||
1016*9356374aSAndroid Build Coastguard Worker                 (waitp->how == kExclusive &&
1017*9356374aSAndroid Build Coastguard Worker                  Condition::GuaranteedEqual(waitp->cond, nullptr)))) {
1018*9356374aSAndroid Build Coastguard Worker       // This thread has already waited, then was woken, then failed to acquire
1019*9356374aSAndroid Build Coastguard Worker       // the mutex and now tries to requeue. Try to requeue it at head,
1020*9356374aSAndroid Build Coastguard Worker       // otherwise it can suffer bad latency (wait whole queue several times).
1021*9356374aSAndroid Build Coastguard Worker       // However, we need to be conservative. First, we need to ensure that we
1022*9356374aSAndroid Build Coastguard Worker       // respect priorities. Then, we need to be careful to not break wait
1023*9356374aSAndroid Build Coastguard Worker       // queue invariants: we require either that unlocker is not scanning
1024*9356374aSAndroid Build Coastguard Worker       // the queue or that the current thread is a writer with no condition
1025*9356374aSAndroid Build Coastguard Worker       // (unlocker will recheck the queue for such waiters).
1026*9356374aSAndroid Build Coastguard Worker       s->next = head->next;
1027*9356374aSAndroid Build Coastguard Worker       head->next = s;
1028*9356374aSAndroid Build Coastguard Worker       if (MuEquivalentWaiter(s, s->next)) {  // s->may_skip is known to be true
1029*9356374aSAndroid Build Coastguard Worker         s->skip = s->next;                   // s may skip to its successor
1030*9356374aSAndroid Build Coastguard Worker       }
1031*9356374aSAndroid Build Coastguard Worker     } else {  // enqueue not done any other way, so
1032*9356374aSAndroid Build Coastguard Worker               // we're inserting s at the back
1033*9356374aSAndroid Build Coastguard Worker       // s will become new head; copy data from head into it
1034*9356374aSAndroid Build Coastguard Worker       s->next = head->next;  // add s after head
1035*9356374aSAndroid Build Coastguard Worker       head->next = s;
1036*9356374aSAndroid Build Coastguard Worker       s->readers = head->readers;  // reader count is from previous head
1037*9356374aSAndroid Build Coastguard Worker       s->maybe_unlocking = head->maybe_unlocking;  // same for unlock hint
1038*9356374aSAndroid Build Coastguard Worker       if (head->may_skip && MuEquivalentWaiter(head, s)) {
1039*9356374aSAndroid Build Coastguard Worker         // head now has successor; may skip
1040*9356374aSAndroid Build Coastguard Worker         head->skip = s;
1041*9356374aSAndroid Build Coastguard Worker       }
1042*9356374aSAndroid Build Coastguard Worker       head = s;  // s is new head
1043*9356374aSAndroid Build Coastguard Worker     }
1044*9356374aSAndroid Build Coastguard Worker   }
1045*9356374aSAndroid Build Coastguard Worker   s->state.store(PerThreadSynch::kQueued, std::memory_order_relaxed);
1046*9356374aSAndroid Build Coastguard Worker   return head;
1047*9356374aSAndroid Build Coastguard Worker }
1048*9356374aSAndroid Build Coastguard Worker 
1049*9356374aSAndroid Build Coastguard Worker // Dequeue the successor pw->next of thread pw from the Mutex waiter queue
1050*9356374aSAndroid Build Coastguard Worker // whose last element is head.  The new head element is returned, or null
1051*9356374aSAndroid Build Coastguard Worker // if the list is made empty.
1052*9356374aSAndroid Build Coastguard Worker // Dequeue is called with both spinlock and Mutex held.
Dequeue(PerThreadSynch * head,PerThreadSynch * pw)1053*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* Dequeue(PerThreadSynch* head, PerThreadSynch* pw) {
1054*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* w = pw->next;
1055*9356374aSAndroid Build Coastguard Worker   pw->next = w->next;                 // snip w out of list
1056*9356374aSAndroid Build Coastguard Worker   if (head == w) {                    // we removed the head
1057*9356374aSAndroid Build Coastguard Worker     head = (pw == w) ? nullptr : pw;  // either emptied list, or pw is new head
1058*9356374aSAndroid Build Coastguard Worker   } else if (pw != head && MuEquivalentWaiter(pw, pw->next)) {
1059*9356374aSAndroid Build Coastguard Worker     // pw can skip to its new successor
1060*9356374aSAndroid Build Coastguard Worker     if (pw->next->skip !=
1061*9356374aSAndroid Build Coastguard Worker         nullptr) {  // either skip to its successors skip target
1062*9356374aSAndroid Build Coastguard Worker       pw->skip = pw->next->skip;
1063*9356374aSAndroid Build Coastguard Worker     } else {  // or to pw's successor
1064*9356374aSAndroid Build Coastguard Worker       pw->skip = pw->next;
1065*9356374aSAndroid Build Coastguard Worker     }
1066*9356374aSAndroid Build Coastguard Worker   }
1067*9356374aSAndroid Build Coastguard Worker   return head;
1068*9356374aSAndroid Build Coastguard Worker }
1069*9356374aSAndroid Build Coastguard Worker 
1070*9356374aSAndroid Build Coastguard Worker // Traverse the elements [ pw->next, h] of the circular list whose last element
1071*9356374aSAndroid Build Coastguard Worker // is head.
1072*9356374aSAndroid Build Coastguard Worker // Remove all elements with wake==true and place them in the
1073*9356374aSAndroid Build Coastguard Worker // singly-linked list wake_list in the order found.   Assumes that
1074*9356374aSAndroid Build Coastguard Worker // there is only one such element if the element has how == kExclusive.
1075*9356374aSAndroid Build Coastguard Worker // Return the new head.
DequeueAllWakeable(PerThreadSynch * head,PerThreadSynch * pw,PerThreadSynch ** wake_tail)1076*9356374aSAndroid Build Coastguard Worker static PerThreadSynch* DequeueAllWakeable(PerThreadSynch* head,
1077*9356374aSAndroid Build Coastguard Worker                                           PerThreadSynch* pw,
1078*9356374aSAndroid Build Coastguard Worker                                           PerThreadSynch** wake_tail) {
1079*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* orig_h = head;
1080*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* w = pw->next;
1081*9356374aSAndroid Build Coastguard Worker   bool skipped = false;
1082*9356374aSAndroid Build Coastguard Worker   do {
1083*9356374aSAndroid Build Coastguard Worker     if (w->wake) {  // remove this element
1084*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_CHECK(pw->skip == nullptr, "bad skip in DequeueAllWakeable");
1085*9356374aSAndroid Build Coastguard Worker       // we're removing pw's successor so either pw->skip is zero or we should
1086*9356374aSAndroid Build Coastguard Worker       // already have removed pw since if pw->skip!=null, pw has the same
1087*9356374aSAndroid Build Coastguard Worker       // condition as w.
1088*9356374aSAndroid Build Coastguard Worker       head = Dequeue(head, pw);
1089*9356374aSAndroid Build Coastguard Worker       w->next = *wake_tail;               // keep list terminated
1090*9356374aSAndroid Build Coastguard Worker       *wake_tail = w;                     // add w to wake_list;
1091*9356374aSAndroid Build Coastguard Worker       wake_tail = &w->next;               // next addition to end
1092*9356374aSAndroid Build Coastguard Worker       if (w->waitp->how == kExclusive) {  // wake at most 1 writer
1093*9356374aSAndroid Build Coastguard Worker         break;
1094*9356374aSAndroid Build Coastguard Worker       }
1095*9356374aSAndroid Build Coastguard Worker     } else {         // not waking this one; skip
1096*9356374aSAndroid Build Coastguard Worker       pw = Skip(w);  // skip as much as possible
1097*9356374aSAndroid Build Coastguard Worker       skipped = true;
1098*9356374aSAndroid Build Coastguard Worker     }
1099*9356374aSAndroid Build Coastguard Worker     w = pw->next;
1100*9356374aSAndroid Build Coastguard Worker     // We want to stop processing after we've considered the original head,
1101*9356374aSAndroid Build Coastguard Worker     // orig_h.  We can't test for w==orig_h in the loop because w may skip over
1102*9356374aSAndroid Build Coastguard Worker     // it; we are guaranteed only that w's predecessor will not skip over
1103*9356374aSAndroid Build Coastguard Worker     // orig_h.  When we've considered orig_h, either we've processed it and
1104*9356374aSAndroid Build Coastguard Worker     // removed it (so orig_h != head), or we considered it and skipped it (so
1105*9356374aSAndroid Build Coastguard Worker     // skipped==true && pw == head because skipping from head always skips by
1106*9356374aSAndroid Build Coastguard Worker     // just one, leaving pw pointing at head).  So we want to
1107*9356374aSAndroid Build Coastguard Worker     // continue the loop with the negation of that expression.
1108*9356374aSAndroid Build Coastguard Worker   } while (orig_h == head && (pw != head || !skipped));
1109*9356374aSAndroid Build Coastguard Worker   return head;
1110*9356374aSAndroid Build Coastguard Worker }
1111*9356374aSAndroid Build Coastguard Worker 
1112*9356374aSAndroid Build Coastguard Worker // Try to remove thread s from the list of waiters on this mutex.
1113*9356374aSAndroid Build Coastguard Worker // Does nothing if s is not on the waiter list.
TryRemove(PerThreadSynch * s)1114*9356374aSAndroid Build Coastguard Worker void Mutex::TryRemove(PerThreadSynch* s) {
1115*9356374aSAndroid Build Coastguard Worker   SchedulingGuard::ScopedDisable disable_rescheduling;
1116*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1117*9356374aSAndroid Build Coastguard Worker   // acquire spinlock & lock
1118*9356374aSAndroid Build Coastguard Worker   if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait &&
1119*9356374aSAndroid Build Coastguard Worker       mu_.compare_exchange_strong(v, v | kMuSpin | kMuWriter,
1120*9356374aSAndroid Build Coastguard Worker                                   std::memory_order_acquire,
1121*9356374aSAndroid Build Coastguard Worker                                   std::memory_order_relaxed)) {
1122*9356374aSAndroid Build Coastguard Worker     PerThreadSynch* h = GetPerThreadSynch(v);
1123*9356374aSAndroid Build Coastguard Worker     if (h != nullptr) {
1124*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* pw = h;  // pw is w's predecessor
1125*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* w;
1126*9356374aSAndroid Build Coastguard Worker       if ((w = pw->next) != s) {  // search for thread,
1127*9356374aSAndroid Build Coastguard Worker         do {                      // processing at least one element
1128*9356374aSAndroid Build Coastguard Worker           // If the current element isn't equivalent to the waiter to be
1129*9356374aSAndroid Build Coastguard Worker           // removed, we can skip the entire chain.
1130*9356374aSAndroid Build Coastguard Worker           if (!MuEquivalentWaiter(s, w)) {
1131*9356374aSAndroid Build Coastguard Worker             pw = Skip(w);  // so skip all that won't match
1132*9356374aSAndroid Build Coastguard Worker             // we don't have to worry about dangling skip fields
1133*9356374aSAndroid Build Coastguard Worker             // in the threads we skipped; none can point to s
1134*9356374aSAndroid Build Coastguard Worker             // because they are in a different equivalence class.
1135*9356374aSAndroid Build Coastguard Worker           } else {          // seeking same condition
1136*9356374aSAndroid Build Coastguard Worker             FixSkip(w, s);  // fix up any skip pointer from w to s
1137*9356374aSAndroid Build Coastguard Worker             pw = w;
1138*9356374aSAndroid Build Coastguard Worker           }
1139*9356374aSAndroid Build Coastguard Worker           // don't search further if we found the thread, or we're about to
1140*9356374aSAndroid Build Coastguard Worker           // process the first thread again.
1141*9356374aSAndroid Build Coastguard Worker         } while ((w = pw->next) != s && pw != h);
1142*9356374aSAndroid Build Coastguard Worker       }
1143*9356374aSAndroid Build Coastguard Worker       if (w == s) {  // found thread; remove it
1144*9356374aSAndroid Build Coastguard Worker         // pw->skip may be non-zero here; the loop above ensured that
1145*9356374aSAndroid Build Coastguard Worker         // no ancestor of s can skip to s, so removal is safe anyway.
1146*9356374aSAndroid Build Coastguard Worker         h = Dequeue(h, pw);
1147*9356374aSAndroid Build Coastguard Worker         s->next = nullptr;
1148*9356374aSAndroid Build Coastguard Worker         s->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
1149*9356374aSAndroid Build Coastguard Worker       }
1150*9356374aSAndroid Build Coastguard Worker     }
1151*9356374aSAndroid Build Coastguard Worker     intptr_t nv;
1152*9356374aSAndroid Build Coastguard Worker     do {  // release spinlock and lock
1153*9356374aSAndroid Build Coastguard Worker       v = mu_.load(std::memory_order_relaxed);
1154*9356374aSAndroid Build Coastguard Worker       nv = v & (kMuDesig | kMuEvent);
1155*9356374aSAndroid Build Coastguard Worker       if (h != nullptr) {
1156*9356374aSAndroid Build Coastguard Worker         nv |= kMuWait | reinterpret_cast<intptr_t>(h);
1157*9356374aSAndroid Build Coastguard Worker         h->readers = 0;              // we hold writer lock
1158*9356374aSAndroid Build Coastguard Worker         h->maybe_unlocking = false;  // finished unlocking
1159*9356374aSAndroid Build Coastguard Worker       }
1160*9356374aSAndroid Build Coastguard Worker     } while (!mu_.compare_exchange_weak(v, nv, std::memory_order_release,
1161*9356374aSAndroid Build Coastguard Worker                                         std::memory_order_relaxed));
1162*9356374aSAndroid Build Coastguard Worker   }
1163*9356374aSAndroid Build Coastguard Worker }
1164*9356374aSAndroid Build Coastguard Worker 
1165*9356374aSAndroid Build Coastguard Worker // Wait until thread "s", which must be the current thread, is removed from the
1166*9356374aSAndroid Build Coastguard Worker // this mutex's waiter queue.  If "s->waitp->timeout" has a timeout, wake up
1167*9356374aSAndroid Build Coastguard Worker // if the wait extends past the absolute time specified, even if "s" is still
1168*9356374aSAndroid Build Coastguard Worker // on the mutex queue.  In this case, remove "s" from the queue and return
1169*9356374aSAndroid Build Coastguard Worker // true, otherwise return false.
Block(PerThreadSynch * s)1170*9356374aSAndroid Build Coastguard Worker void Mutex::Block(PerThreadSynch* s) {
1171*9356374aSAndroid Build Coastguard Worker   while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
1172*9356374aSAndroid Build Coastguard Worker     if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
1173*9356374aSAndroid Build Coastguard Worker       // After a timeout, we go into a spin loop until we remove ourselves
1174*9356374aSAndroid Build Coastguard Worker       // from the queue, or someone else removes us.  We can't be sure to be
1175*9356374aSAndroid Build Coastguard Worker       // able to remove ourselves in a single lock acquisition because this
1176*9356374aSAndroid Build Coastguard Worker       // mutex may be held, and the holder has the right to read the centre
1177*9356374aSAndroid Build Coastguard Worker       // of the waiter queue without holding the spinlock.
1178*9356374aSAndroid Build Coastguard Worker       this->TryRemove(s);
1179*9356374aSAndroid Build Coastguard Worker       int c = 0;
1180*9356374aSAndroid Build Coastguard Worker       while (s->next != nullptr) {
1181*9356374aSAndroid Build Coastguard Worker         c = synchronization_internal::MutexDelay(c, GENTLE);
1182*9356374aSAndroid Build Coastguard Worker         this->TryRemove(s);
1183*9356374aSAndroid Build Coastguard Worker       }
1184*9356374aSAndroid Build Coastguard Worker       if (kDebugMode) {
1185*9356374aSAndroid Build Coastguard Worker         // This ensures that we test the case that TryRemove() is called when s
1186*9356374aSAndroid Build Coastguard Worker         // is not on the queue.
1187*9356374aSAndroid Build Coastguard Worker         this->TryRemove(s);
1188*9356374aSAndroid Build Coastguard Worker       }
1189*9356374aSAndroid Build Coastguard Worker       s->waitp->timeout = KernelTimeout::Never();  // timeout is satisfied
1190*9356374aSAndroid Build Coastguard Worker       s->waitp->cond = nullptr;  // condition no longer relevant for wakeups
1191*9356374aSAndroid Build Coastguard Worker     }
1192*9356374aSAndroid Build Coastguard Worker   }
1193*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(s->waitp != nullptr || s->suppress_fatal_errors,
1194*9356374aSAndroid Build Coastguard Worker                  "detected illegal recursion in Mutex code");
1195*9356374aSAndroid Build Coastguard Worker   s->waitp = nullptr;
1196*9356374aSAndroid Build Coastguard Worker }
1197*9356374aSAndroid Build Coastguard Worker 
1198*9356374aSAndroid Build Coastguard Worker // Wake thread w, and return the next thread in the list.
Wakeup(PerThreadSynch * w)1199*9356374aSAndroid Build Coastguard Worker PerThreadSynch* Mutex::Wakeup(PerThreadSynch* w) {
1200*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* next = w->next;
1201*9356374aSAndroid Build Coastguard Worker   w->next = nullptr;
1202*9356374aSAndroid Build Coastguard Worker   w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
1203*9356374aSAndroid Build Coastguard Worker   IncrementSynchSem(this, w);
1204*9356374aSAndroid Build Coastguard Worker 
1205*9356374aSAndroid Build Coastguard Worker   return next;
1206*9356374aSAndroid Build Coastguard Worker }
1207*9356374aSAndroid Build Coastguard Worker 
GetGraphIdLocked(Mutex * mu)1208*9356374aSAndroid Build Coastguard Worker static GraphId GetGraphIdLocked(Mutex* mu)
1209*9356374aSAndroid Build Coastguard Worker     ABSL_EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {
1210*9356374aSAndroid Build Coastguard Worker   if (!deadlock_graph) {  // (re)create the deadlock graph.
1211*9356374aSAndroid Build Coastguard Worker     deadlock_graph =
1212*9356374aSAndroid Build Coastguard Worker         new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph)))
1213*9356374aSAndroid Build Coastguard Worker             GraphCycles;
1214*9356374aSAndroid Build Coastguard Worker   }
1215*9356374aSAndroid Build Coastguard Worker   return deadlock_graph->GetId(mu);
1216*9356374aSAndroid Build Coastguard Worker }
1217*9356374aSAndroid Build Coastguard Worker 
GetGraphId(Mutex * mu)1218*9356374aSAndroid Build Coastguard Worker static GraphId GetGraphId(Mutex* mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) {
1219*9356374aSAndroid Build Coastguard Worker   deadlock_graph_mu.Lock();
1220*9356374aSAndroid Build Coastguard Worker   GraphId id = GetGraphIdLocked(mu);
1221*9356374aSAndroid Build Coastguard Worker   deadlock_graph_mu.Unlock();
1222*9356374aSAndroid Build Coastguard Worker   return id;
1223*9356374aSAndroid Build Coastguard Worker }
1224*9356374aSAndroid Build Coastguard Worker 
1225*9356374aSAndroid Build Coastguard Worker // Record a lock acquisition.  This is used in debug mode for deadlock
1226*9356374aSAndroid Build Coastguard Worker // detection.  The held_locks pointer points to the relevant data
1227*9356374aSAndroid Build Coastguard Worker // structure for each case.
LockEnter(Mutex * mu,GraphId id,SynchLocksHeld * held_locks)1228*9356374aSAndroid Build Coastguard Worker static void LockEnter(Mutex* mu, GraphId id, SynchLocksHeld* held_locks) {
1229*9356374aSAndroid Build Coastguard Worker   int n = held_locks->n;
1230*9356374aSAndroid Build Coastguard Worker   int i = 0;
1231*9356374aSAndroid Build Coastguard Worker   while (i != n && held_locks->locks[i].id != id) {
1232*9356374aSAndroid Build Coastguard Worker     i++;
1233*9356374aSAndroid Build Coastguard Worker   }
1234*9356374aSAndroid Build Coastguard Worker   if (i == n) {
1235*9356374aSAndroid Build Coastguard Worker     if (n == ABSL_ARRAYSIZE(held_locks->locks)) {
1236*9356374aSAndroid Build Coastguard Worker       held_locks->overflow = true;  // lost some data
1237*9356374aSAndroid Build Coastguard Worker     } else {                        // we have room for lock
1238*9356374aSAndroid Build Coastguard Worker       held_locks->locks[i].mu = mu;
1239*9356374aSAndroid Build Coastguard Worker       held_locks->locks[i].count = 1;
1240*9356374aSAndroid Build Coastguard Worker       held_locks->locks[i].id = id;
1241*9356374aSAndroid Build Coastguard Worker       held_locks->n = n + 1;
1242*9356374aSAndroid Build Coastguard Worker     }
1243*9356374aSAndroid Build Coastguard Worker   } else {
1244*9356374aSAndroid Build Coastguard Worker     held_locks->locks[i].count++;
1245*9356374aSAndroid Build Coastguard Worker   }
1246*9356374aSAndroid Build Coastguard Worker }
1247*9356374aSAndroid Build Coastguard Worker 
1248*9356374aSAndroid Build Coastguard Worker // Record a lock release.  Each call to LockEnter(mu, id, x) should be
1249*9356374aSAndroid Build Coastguard Worker // eventually followed by a call to LockLeave(mu, id, x) by the same thread.
1250*9356374aSAndroid Build Coastguard Worker // It does not process the event if is not needed when deadlock detection is
1251*9356374aSAndroid Build Coastguard Worker // disabled.
LockLeave(Mutex * mu,GraphId id,SynchLocksHeld * held_locks)1252*9356374aSAndroid Build Coastguard Worker static void LockLeave(Mutex* mu, GraphId id, SynchLocksHeld* held_locks) {
1253*9356374aSAndroid Build Coastguard Worker   int n = held_locks->n;
1254*9356374aSAndroid Build Coastguard Worker   int i = 0;
1255*9356374aSAndroid Build Coastguard Worker   while (i != n && held_locks->locks[i].id != id) {
1256*9356374aSAndroid Build Coastguard Worker     i++;
1257*9356374aSAndroid Build Coastguard Worker   }
1258*9356374aSAndroid Build Coastguard Worker   if (i == n) {
1259*9356374aSAndroid Build Coastguard Worker     if (!held_locks->overflow) {
1260*9356374aSAndroid Build Coastguard Worker       // The deadlock id may have been reassigned after ForgetDeadlockInfo,
1261*9356374aSAndroid Build Coastguard Worker       // but in that case mu should still be present.
1262*9356374aSAndroid Build Coastguard Worker       i = 0;
1263*9356374aSAndroid Build Coastguard Worker       while (i != n && held_locks->locks[i].mu != mu) {
1264*9356374aSAndroid Build Coastguard Worker         i++;
1265*9356374aSAndroid Build Coastguard Worker       }
1266*9356374aSAndroid Build Coastguard Worker       if (i == n) {  // mu missing means releasing unheld lock
1267*9356374aSAndroid Build Coastguard Worker         SynchEvent* mu_events = GetSynchEvent(mu);
1268*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_LOG(FATAL,
1269*9356374aSAndroid Build Coastguard Worker                      "thread releasing lock it does not hold: %p %s; "
1270*9356374aSAndroid Build Coastguard Worker                      ,
1271*9356374aSAndroid Build Coastguard Worker                      static_cast<void*>(mu),
1272*9356374aSAndroid Build Coastguard Worker                      mu_events == nullptr ? "" : mu_events->name);
1273*9356374aSAndroid Build Coastguard Worker       }
1274*9356374aSAndroid Build Coastguard Worker     }
1275*9356374aSAndroid Build Coastguard Worker   } else if (held_locks->locks[i].count == 1) {
1276*9356374aSAndroid Build Coastguard Worker     held_locks->n = n - 1;
1277*9356374aSAndroid Build Coastguard Worker     held_locks->locks[i] = held_locks->locks[n - 1];
1278*9356374aSAndroid Build Coastguard Worker     held_locks->locks[n - 1].id = InvalidGraphId();
1279*9356374aSAndroid Build Coastguard Worker     held_locks->locks[n - 1].mu =
1280*9356374aSAndroid Build Coastguard Worker         nullptr;  // clear mu to please the leak detector.
1281*9356374aSAndroid Build Coastguard Worker   } else {
1282*9356374aSAndroid Build Coastguard Worker     assert(held_locks->locks[i].count > 0);
1283*9356374aSAndroid Build Coastguard Worker     held_locks->locks[i].count--;
1284*9356374aSAndroid Build Coastguard Worker   }
1285*9356374aSAndroid Build Coastguard Worker }
1286*9356374aSAndroid Build Coastguard Worker 
1287*9356374aSAndroid Build Coastguard Worker // Call LockEnter() if in debug mode and deadlock detection is enabled.
DebugOnlyLockEnter(Mutex * mu)1288*9356374aSAndroid Build Coastguard Worker static inline void DebugOnlyLockEnter(Mutex* mu) {
1289*9356374aSAndroid Build Coastguard Worker   if (kDebugMode) {
1290*9356374aSAndroid Build Coastguard Worker     if (synch_deadlock_detection.load(std::memory_order_acquire) !=
1291*9356374aSAndroid Build Coastguard Worker         OnDeadlockCycle::kIgnore) {
1292*9356374aSAndroid Build Coastguard Worker       LockEnter(mu, GetGraphId(mu), Synch_GetAllLocks());
1293*9356374aSAndroid Build Coastguard Worker     }
1294*9356374aSAndroid Build Coastguard Worker   }
1295*9356374aSAndroid Build Coastguard Worker }
1296*9356374aSAndroid Build Coastguard Worker 
1297*9356374aSAndroid Build Coastguard Worker // Call LockEnter() if in debug mode and deadlock detection is enabled.
DebugOnlyLockEnter(Mutex * mu,GraphId id)1298*9356374aSAndroid Build Coastguard Worker static inline void DebugOnlyLockEnter(Mutex* mu, GraphId id) {
1299*9356374aSAndroid Build Coastguard Worker   if (kDebugMode) {
1300*9356374aSAndroid Build Coastguard Worker     if (synch_deadlock_detection.load(std::memory_order_acquire) !=
1301*9356374aSAndroid Build Coastguard Worker         OnDeadlockCycle::kIgnore) {
1302*9356374aSAndroid Build Coastguard Worker       LockEnter(mu, id, Synch_GetAllLocks());
1303*9356374aSAndroid Build Coastguard Worker     }
1304*9356374aSAndroid Build Coastguard Worker   }
1305*9356374aSAndroid Build Coastguard Worker }
1306*9356374aSAndroid Build Coastguard Worker 
1307*9356374aSAndroid Build Coastguard Worker // Call LockLeave() if in debug mode and deadlock detection is enabled.
DebugOnlyLockLeave(Mutex * mu)1308*9356374aSAndroid Build Coastguard Worker static inline void DebugOnlyLockLeave(Mutex* mu) {
1309*9356374aSAndroid Build Coastguard Worker   if (kDebugMode) {
1310*9356374aSAndroid Build Coastguard Worker     if (synch_deadlock_detection.load(std::memory_order_acquire) !=
1311*9356374aSAndroid Build Coastguard Worker         OnDeadlockCycle::kIgnore) {
1312*9356374aSAndroid Build Coastguard Worker       LockLeave(mu, GetGraphId(mu), Synch_GetAllLocks());
1313*9356374aSAndroid Build Coastguard Worker     }
1314*9356374aSAndroid Build Coastguard Worker   }
1315*9356374aSAndroid Build Coastguard Worker }
1316*9356374aSAndroid Build Coastguard Worker 
StackString(void ** pcs,int n,char * buf,int maxlen,bool symbolize)1317*9356374aSAndroid Build Coastguard Worker static char* StackString(void** pcs, int n, char* buf, int maxlen,
1318*9356374aSAndroid Build Coastguard Worker                          bool symbolize) {
1319*9356374aSAndroid Build Coastguard Worker   static constexpr int kSymLen = 200;
1320*9356374aSAndroid Build Coastguard Worker   char sym[kSymLen];
1321*9356374aSAndroid Build Coastguard Worker   int len = 0;
1322*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i != n; i++) {
1323*9356374aSAndroid Build Coastguard Worker     if (len >= maxlen)
1324*9356374aSAndroid Build Coastguard Worker       return buf;
1325*9356374aSAndroid Build Coastguard Worker     size_t count = static_cast<size_t>(maxlen - len);
1326*9356374aSAndroid Build Coastguard Worker     if (symbolize) {
1327*9356374aSAndroid Build Coastguard Worker       if (!absl::Symbolize(pcs[i], sym, kSymLen)) {
1328*9356374aSAndroid Build Coastguard Worker         sym[0] = '\0';
1329*9356374aSAndroid Build Coastguard Worker       }
1330*9356374aSAndroid Build Coastguard Worker       snprintf(buf + len, count, "%s\t@ %p %s\n", (i == 0 ? "\n" : ""), pcs[i],
1331*9356374aSAndroid Build Coastguard Worker                sym);
1332*9356374aSAndroid Build Coastguard Worker     } else {
1333*9356374aSAndroid Build Coastguard Worker       snprintf(buf + len, count, " %p", pcs[i]);
1334*9356374aSAndroid Build Coastguard Worker     }
1335*9356374aSAndroid Build Coastguard Worker     len += strlen(&buf[len]);
1336*9356374aSAndroid Build Coastguard Worker   }
1337*9356374aSAndroid Build Coastguard Worker   return buf;
1338*9356374aSAndroid Build Coastguard Worker }
1339*9356374aSAndroid Build Coastguard Worker 
CurrentStackString(char * buf,int maxlen,bool symbolize)1340*9356374aSAndroid Build Coastguard Worker static char* CurrentStackString(char* buf, int maxlen, bool symbolize) {
1341*9356374aSAndroid Build Coastguard Worker   void* pcs[40];
1342*9356374aSAndroid Build Coastguard Worker   return StackString(pcs, absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 2), buf,
1343*9356374aSAndroid Build Coastguard Worker                      maxlen, symbolize);
1344*9356374aSAndroid Build Coastguard Worker }
1345*9356374aSAndroid Build Coastguard Worker 
1346*9356374aSAndroid Build Coastguard Worker namespace {
1347*9356374aSAndroid Build Coastguard Worker enum {
1348*9356374aSAndroid Build Coastguard Worker   kMaxDeadlockPathLen = 10
1349*9356374aSAndroid Build Coastguard Worker };  // maximum length of a deadlock cycle;
1350*9356374aSAndroid Build Coastguard Worker     // a path this long would be remarkable
1351*9356374aSAndroid Build Coastguard Worker // Buffers required to report a deadlock.
1352*9356374aSAndroid Build Coastguard Worker // We do not allocate them on stack to avoid large stack frame.
1353*9356374aSAndroid Build Coastguard Worker struct DeadlockReportBuffers {
1354*9356374aSAndroid Build Coastguard Worker   char buf[6100];
1355*9356374aSAndroid Build Coastguard Worker   GraphId path[kMaxDeadlockPathLen];
1356*9356374aSAndroid Build Coastguard Worker };
1357*9356374aSAndroid Build Coastguard Worker 
1358*9356374aSAndroid Build Coastguard Worker struct ScopedDeadlockReportBuffers {
ScopedDeadlockReportBuffersabsl::__anone4e938ef0a11::ScopedDeadlockReportBuffers1359*9356374aSAndroid Build Coastguard Worker   ScopedDeadlockReportBuffers() {
1360*9356374aSAndroid Build Coastguard Worker     b = reinterpret_cast<DeadlockReportBuffers*>(
1361*9356374aSAndroid Build Coastguard Worker         base_internal::LowLevelAlloc::Alloc(sizeof(*b)));
1362*9356374aSAndroid Build Coastguard Worker   }
~ScopedDeadlockReportBuffersabsl::__anone4e938ef0a11::ScopedDeadlockReportBuffers1363*9356374aSAndroid Build Coastguard Worker   ~ScopedDeadlockReportBuffers() { base_internal::LowLevelAlloc::Free(b); }
1364*9356374aSAndroid Build Coastguard Worker   DeadlockReportBuffers* b;
1365*9356374aSAndroid Build Coastguard Worker };
1366*9356374aSAndroid Build Coastguard Worker 
1367*9356374aSAndroid Build Coastguard Worker // Helper to pass to GraphCycles::UpdateStackTrace.
GetStack(void ** stack,int max_depth)1368*9356374aSAndroid Build Coastguard Worker int GetStack(void** stack, int max_depth) {
1369*9356374aSAndroid Build Coastguard Worker   return absl::GetStackTrace(stack, max_depth, 3);
1370*9356374aSAndroid Build Coastguard Worker }
1371*9356374aSAndroid Build Coastguard Worker }  // anonymous namespace
1372*9356374aSAndroid Build Coastguard Worker 
1373*9356374aSAndroid Build Coastguard Worker // Called in debug mode when a thread is about to acquire a lock in a way that
1374*9356374aSAndroid Build Coastguard Worker // may block.
DeadlockCheck(Mutex * mu)1375*9356374aSAndroid Build Coastguard Worker static GraphId DeadlockCheck(Mutex* mu) {
1376*9356374aSAndroid Build Coastguard Worker   if (synch_deadlock_detection.load(std::memory_order_acquire) ==
1377*9356374aSAndroid Build Coastguard Worker       OnDeadlockCycle::kIgnore) {
1378*9356374aSAndroid Build Coastguard Worker     return InvalidGraphId();
1379*9356374aSAndroid Build Coastguard Worker   }
1380*9356374aSAndroid Build Coastguard Worker 
1381*9356374aSAndroid Build Coastguard Worker   SynchLocksHeld* all_locks = Synch_GetAllLocks();
1382*9356374aSAndroid Build Coastguard Worker 
1383*9356374aSAndroid Build Coastguard Worker   absl::base_internal::SpinLockHolder lock(&deadlock_graph_mu);
1384*9356374aSAndroid Build Coastguard Worker   const GraphId mu_id = GetGraphIdLocked(mu);
1385*9356374aSAndroid Build Coastguard Worker 
1386*9356374aSAndroid Build Coastguard Worker   if (all_locks->n == 0) {
1387*9356374aSAndroid Build Coastguard Worker     // There are no other locks held. Return now so that we don't need to
1388*9356374aSAndroid Build Coastguard Worker     // call GetSynchEvent(). This way we do not record the stack trace
1389*9356374aSAndroid Build Coastguard Worker     // for this Mutex. It's ok, since if this Mutex is involved in a deadlock,
1390*9356374aSAndroid Build Coastguard Worker     // it can't always be the first lock acquired by a thread.
1391*9356374aSAndroid Build Coastguard Worker     return mu_id;
1392*9356374aSAndroid Build Coastguard Worker   }
1393*9356374aSAndroid Build Coastguard Worker 
1394*9356374aSAndroid Build Coastguard Worker   // We prefer to keep stack traces that show a thread holding and acquiring
1395*9356374aSAndroid Build Coastguard Worker   // as many locks as possible.  This increases the chances that a given edge
1396*9356374aSAndroid Build Coastguard Worker   // in the acquires-before graph will be represented in the stack traces
1397*9356374aSAndroid Build Coastguard Worker   // recorded for the locks.
1398*9356374aSAndroid Build Coastguard Worker   deadlock_graph->UpdateStackTrace(mu_id, all_locks->n + 1, GetStack);
1399*9356374aSAndroid Build Coastguard Worker 
1400*9356374aSAndroid Build Coastguard Worker   // For each other mutex already held by this thread:
1401*9356374aSAndroid Build Coastguard Worker   for (int i = 0; i != all_locks->n; i++) {
1402*9356374aSAndroid Build Coastguard Worker     const GraphId other_node_id = all_locks->locks[i].id;
1403*9356374aSAndroid Build Coastguard Worker     const Mutex* other =
1404*9356374aSAndroid Build Coastguard Worker         static_cast<const Mutex*>(deadlock_graph->Ptr(other_node_id));
1405*9356374aSAndroid Build Coastguard Worker     if (other == nullptr) {
1406*9356374aSAndroid Build Coastguard Worker       // Ignore stale lock
1407*9356374aSAndroid Build Coastguard Worker       continue;
1408*9356374aSAndroid Build Coastguard Worker     }
1409*9356374aSAndroid Build Coastguard Worker 
1410*9356374aSAndroid Build Coastguard Worker     // Add the acquired-before edge to the graph.
1411*9356374aSAndroid Build Coastguard Worker     if (!deadlock_graph->InsertEdge(other_node_id, mu_id)) {
1412*9356374aSAndroid Build Coastguard Worker       ScopedDeadlockReportBuffers scoped_buffers;
1413*9356374aSAndroid Build Coastguard Worker       DeadlockReportBuffers* b = scoped_buffers.b;
1414*9356374aSAndroid Build Coastguard Worker       static int number_of_reported_deadlocks = 0;
1415*9356374aSAndroid Build Coastguard Worker       number_of_reported_deadlocks++;
1416*9356374aSAndroid Build Coastguard Worker       // Symbolize only 2 first deadlock report to avoid huge slowdowns.
1417*9356374aSAndroid Build Coastguard Worker       bool symbolize = number_of_reported_deadlocks <= 2;
1418*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_LOG(ERROR, "Potential Mutex deadlock: %s",
1419*9356374aSAndroid Build Coastguard Worker                    CurrentStackString(b->buf, sizeof (b->buf), symbolize));
1420*9356374aSAndroid Build Coastguard Worker       size_t len = 0;
1421*9356374aSAndroid Build Coastguard Worker       for (int j = 0; j != all_locks->n; j++) {
1422*9356374aSAndroid Build Coastguard Worker         void* pr = deadlock_graph->Ptr(all_locks->locks[j].id);
1423*9356374aSAndroid Build Coastguard Worker         if (pr != nullptr) {
1424*9356374aSAndroid Build Coastguard Worker           snprintf(b->buf + len, sizeof(b->buf) - len, " %p", pr);
1425*9356374aSAndroid Build Coastguard Worker           len += strlen(&b->buf[len]);
1426*9356374aSAndroid Build Coastguard Worker         }
1427*9356374aSAndroid Build Coastguard Worker       }
1428*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_LOG(ERROR,
1429*9356374aSAndroid Build Coastguard Worker                    "Acquiring absl::Mutex %p while holding %s; a cycle in the "
1430*9356374aSAndroid Build Coastguard Worker                    "historical lock ordering graph has been observed",
1431*9356374aSAndroid Build Coastguard Worker                    static_cast<void*>(mu), b->buf);
1432*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_LOG(ERROR, "Cycle: ");
1433*9356374aSAndroid Build Coastguard Worker       int path_len = deadlock_graph->FindPath(mu_id, other_node_id,
1434*9356374aSAndroid Build Coastguard Worker                                               ABSL_ARRAYSIZE(b->path), b->path);
1435*9356374aSAndroid Build Coastguard Worker       for (int j = 0; j != path_len && j != ABSL_ARRAYSIZE(b->path); j++) {
1436*9356374aSAndroid Build Coastguard Worker         GraphId id = b->path[j];
1437*9356374aSAndroid Build Coastguard Worker         Mutex* path_mu = static_cast<Mutex*>(deadlock_graph->Ptr(id));
1438*9356374aSAndroid Build Coastguard Worker         if (path_mu == nullptr) continue;
1439*9356374aSAndroid Build Coastguard Worker         void** stack;
1440*9356374aSAndroid Build Coastguard Worker         int depth = deadlock_graph->GetStackTrace(id, &stack);
1441*9356374aSAndroid Build Coastguard Worker         snprintf(b->buf, sizeof(b->buf),
1442*9356374aSAndroid Build Coastguard Worker                  "mutex@%p stack: ", static_cast<void*>(path_mu));
1443*9356374aSAndroid Build Coastguard Worker         StackString(stack, depth, b->buf + strlen(b->buf),
1444*9356374aSAndroid Build Coastguard Worker                     static_cast<int>(sizeof(b->buf) - strlen(b->buf)),
1445*9356374aSAndroid Build Coastguard Worker                     symbolize);
1446*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_LOG(ERROR, "%s", b->buf);
1447*9356374aSAndroid Build Coastguard Worker       }
1448*9356374aSAndroid Build Coastguard Worker       if (path_len > static_cast<int>(ABSL_ARRAYSIZE(b->path))) {
1449*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_LOG(ERROR, "(long cycle; list truncated)");
1450*9356374aSAndroid Build Coastguard Worker       }
1451*9356374aSAndroid Build Coastguard Worker       if (synch_deadlock_detection.load(std::memory_order_acquire) ==
1452*9356374aSAndroid Build Coastguard Worker           OnDeadlockCycle::kAbort) {
1453*9356374aSAndroid Build Coastguard Worker         deadlock_graph_mu.Unlock();  // avoid deadlock in fatal sighandler
1454*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_LOG(FATAL, "dying due to potential deadlock");
1455*9356374aSAndroid Build Coastguard Worker         return mu_id;
1456*9356374aSAndroid Build Coastguard Worker       }
1457*9356374aSAndroid Build Coastguard Worker       break;  // report at most one potential deadlock per acquisition
1458*9356374aSAndroid Build Coastguard Worker     }
1459*9356374aSAndroid Build Coastguard Worker   }
1460*9356374aSAndroid Build Coastguard Worker 
1461*9356374aSAndroid Build Coastguard Worker   return mu_id;
1462*9356374aSAndroid Build Coastguard Worker }
1463*9356374aSAndroid Build Coastguard Worker 
1464*9356374aSAndroid Build Coastguard Worker // Invoke DeadlockCheck() iff we're in debug mode and
1465*9356374aSAndroid Build Coastguard Worker // deadlock checking has been enabled.
DebugOnlyDeadlockCheck(Mutex * mu)1466*9356374aSAndroid Build Coastguard Worker static inline GraphId DebugOnlyDeadlockCheck(Mutex* mu) {
1467*9356374aSAndroid Build Coastguard Worker   if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) !=
1468*9356374aSAndroid Build Coastguard Worker                         OnDeadlockCycle::kIgnore) {
1469*9356374aSAndroid Build Coastguard Worker     return DeadlockCheck(mu);
1470*9356374aSAndroid Build Coastguard Worker   } else {
1471*9356374aSAndroid Build Coastguard Worker     return InvalidGraphId();
1472*9356374aSAndroid Build Coastguard Worker   }
1473*9356374aSAndroid Build Coastguard Worker }
1474*9356374aSAndroid Build Coastguard Worker 
ForgetDeadlockInfo()1475*9356374aSAndroid Build Coastguard Worker void Mutex::ForgetDeadlockInfo() {
1476*9356374aSAndroid Build Coastguard Worker   if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) !=
1477*9356374aSAndroid Build Coastguard Worker                         OnDeadlockCycle::kIgnore) {
1478*9356374aSAndroid Build Coastguard Worker     deadlock_graph_mu.Lock();
1479*9356374aSAndroid Build Coastguard Worker     if (deadlock_graph != nullptr) {
1480*9356374aSAndroid Build Coastguard Worker       deadlock_graph->RemoveNode(this);
1481*9356374aSAndroid Build Coastguard Worker     }
1482*9356374aSAndroid Build Coastguard Worker     deadlock_graph_mu.Unlock();
1483*9356374aSAndroid Build Coastguard Worker   }
1484*9356374aSAndroid Build Coastguard Worker }
1485*9356374aSAndroid Build Coastguard Worker 
AssertNotHeld() const1486*9356374aSAndroid Build Coastguard Worker void Mutex::AssertNotHeld() const {
1487*9356374aSAndroid Build Coastguard Worker   // We have the data to allow this check only if in debug mode and deadlock
1488*9356374aSAndroid Build Coastguard Worker   // detection is enabled.
1489*9356374aSAndroid Build Coastguard Worker   if (kDebugMode &&
1490*9356374aSAndroid Build Coastguard Worker       (mu_.load(std::memory_order_relaxed) & (kMuWriter | kMuReader)) != 0 &&
1491*9356374aSAndroid Build Coastguard Worker       synch_deadlock_detection.load(std::memory_order_acquire) !=
1492*9356374aSAndroid Build Coastguard Worker           OnDeadlockCycle::kIgnore) {
1493*9356374aSAndroid Build Coastguard Worker     GraphId id = GetGraphId(const_cast<Mutex*>(this));
1494*9356374aSAndroid Build Coastguard Worker     SynchLocksHeld* locks = Synch_GetAllLocks();
1495*9356374aSAndroid Build Coastguard Worker     for (int i = 0; i != locks->n; i++) {
1496*9356374aSAndroid Build Coastguard Worker       if (locks->locks[i].id == id) {
1497*9356374aSAndroid Build Coastguard Worker         SynchEvent* mu_events = GetSynchEvent(this);
1498*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_LOG(FATAL, "thread should not hold mutex %p %s",
1499*9356374aSAndroid Build Coastguard Worker                      static_cast<const void*>(this),
1500*9356374aSAndroid Build Coastguard Worker                      (mu_events == nullptr ? "" : mu_events->name));
1501*9356374aSAndroid Build Coastguard Worker       }
1502*9356374aSAndroid Build Coastguard Worker     }
1503*9356374aSAndroid Build Coastguard Worker   }
1504*9356374aSAndroid Build Coastguard Worker }
1505*9356374aSAndroid Build Coastguard Worker 
1506*9356374aSAndroid Build Coastguard Worker // Attempt to acquire *mu, and return whether successful.  The implementation
1507*9356374aSAndroid Build Coastguard Worker // may spin for a short while if the lock cannot be acquired immediately.
TryAcquireWithSpinning(std::atomic<intptr_t> * mu)1508*9356374aSAndroid Build Coastguard Worker static bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) {
1509*9356374aSAndroid Build Coastguard Worker   int c = globals.spinloop_iterations.load(std::memory_order_relaxed);
1510*9356374aSAndroid Build Coastguard Worker   do {  // do/while somewhat faster on AMD
1511*9356374aSAndroid Build Coastguard Worker     intptr_t v = mu->load(std::memory_order_relaxed);
1512*9356374aSAndroid Build Coastguard Worker     if ((v & (kMuReader | kMuEvent)) != 0) {
1513*9356374aSAndroid Build Coastguard Worker       return false;                       // a reader or tracing -> give up
1514*9356374aSAndroid Build Coastguard Worker     } else if (((v & kMuWriter) == 0) &&  // no holder -> try to acquire
1515*9356374aSAndroid Build Coastguard Worker                mu->compare_exchange_strong(v, kMuWriter | v,
1516*9356374aSAndroid Build Coastguard Worker                                            std::memory_order_acquire,
1517*9356374aSAndroid Build Coastguard Worker                                            std::memory_order_relaxed)) {
1518*9356374aSAndroid Build Coastguard Worker       return true;
1519*9356374aSAndroid Build Coastguard Worker     }
1520*9356374aSAndroid Build Coastguard Worker   } while (--c > 0);
1521*9356374aSAndroid Build Coastguard Worker   return false;
1522*9356374aSAndroid Build Coastguard Worker }
1523*9356374aSAndroid Build Coastguard Worker 
Lock()1524*9356374aSAndroid Build Coastguard Worker void Mutex::Lock() {
1525*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
1526*9356374aSAndroid Build Coastguard Worker   GraphId id = DebugOnlyDeadlockCheck(this);
1527*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1528*9356374aSAndroid Build Coastguard Worker   // try fast acquire, then spin loop
1529*9356374aSAndroid Build Coastguard Worker   if (ABSL_PREDICT_FALSE((v & (kMuWriter | kMuReader | kMuEvent)) != 0) ||
1530*9356374aSAndroid Build Coastguard Worker       ABSL_PREDICT_FALSE(!mu_.compare_exchange_strong(
1531*9356374aSAndroid Build Coastguard Worker           v, kMuWriter | v, std::memory_order_acquire,
1532*9356374aSAndroid Build Coastguard Worker           std::memory_order_relaxed))) {
1533*9356374aSAndroid Build Coastguard Worker     // try spin acquire, then slow loop
1534*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(!TryAcquireWithSpinning(&this->mu_))) {
1535*9356374aSAndroid Build Coastguard Worker       this->LockSlow(kExclusive, nullptr, 0);
1536*9356374aSAndroid Build Coastguard Worker     }
1537*9356374aSAndroid Build Coastguard Worker   }
1538*9356374aSAndroid Build Coastguard Worker   DebugOnlyLockEnter(this, id);
1539*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
1540*9356374aSAndroid Build Coastguard Worker }
1541*9356374aSAndroid Build Coastguard Worker 
ReaderLock()1542*9356374aSAndroid Build Coastguard Worker void Mutex::ReaderLock() {
1543*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock);
1544*9356374aSAndroid Build Coastguard Worker   GraphId id = DebugOnlyDeadlockCheck(this);
1545*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1546*9356374aSAndroid Build Coastguard Worker   for (;;) {
1547*9356374aSAndroid Build Coastguard Worker     // If there are non-readers holding the lock, use the slow loop.
1548*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(v & (kMuWriter | kMuWait | kMuEvent)) != 0) {
1549*9356374aSAndroid Build Coastguard Worker       this->LockSlow(kShared, nullptr, 0);
1550*9356374aSAndroid Build Coastguard Worker       break;
1551*9356374aSAndroid Build Coastguard Worker     }
1552*9356374aSAndroid Build Coastguard Worker     // We can avoid the loop and only use the CAS when the lock is free or
1553*9356374aSAndroid Build Coastguard Worker     // only held by readers.
1554*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(mu_.compare_exchange_weak(
1555*9356374aSAndroid Build Coastguard Worker             v, (kMuReader | v) + kMuOne, std::memory_order_acquire,
1556*9356374aSAndroid Build Coastguard Worker             std::memory_order_relaxed))) {
1557*9356374aSAndroid Build Coastguard Worker       break;
1558*9356374aSAndroid Build Coastguard Worker     }
1559*9356374aSAndroid Build Coastguard Worker   }
1560*9356374aSAndroid Build Coastguard Worker   DebugOnlyLockEnter(this, id);
1561*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0);
1562*9356374aSAndroid Build Coastguard Worker }
1563*9356374aSAndroid Build Coastguard Worker 
LockWhenCommon(const Condition & cond,synchronization_internal::KernelTimeout t,bool write)1564*9356374aSAndroid Build Coastguard Worker bool Mutex::LockWhenCommon(const Condition& cond,
1565*9356374aSAndroid Build Coastguard Worker                            synchronization_internal::KernelTimeout t,
1566*9356374aSAndroid Build Coastguard Worker                            bool write) {
1567*9356374aSAndroid Build Coastguard Worker   MuHow how = write ? kExclusive : kShared;
1568*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
1569*9356374aSAndroid Build Coastguard Worker   GraphId id = DebugOnlyDeadlockCheck(this);
1570*9356374aSAndroid Build Coastguard Worker   bool res = LockSlowWithDeadline(how, &cond, t, 0);
1571*9356374aSAndroid Build Coastguard Worker   DebugOnlyLockEnter(this, id);
1572*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
1573*9356374aSAndroid Build Coastguard Worker   return res;
1574*9356374aSAndroid Build Coastguard Worker }
1575*9356374aSAndroid Build Coastguard Worker 
AwaitCommon(const Condition & cond,KernelTimeout t)1576*9356374aSAndroid Build Coastguard Worker bool Mutex::AwaitCommon(const Condition& cond, KernelTimeout t) {
1577*9356374aSAndroid Build Coastguard Worker   if (kDebugMode) {
1578*9356374aSAndroid Build Coastguard Worker     this->AssertReaderHeld();
1579*9356374aSAndroid Build Coastguard Worker   }
1580*9356374aSAndroid Build Coastguard Worker   if (cond.Eval()) {  // condition already true; nothing to do
1581*9356374aSAndroid Build Coastguard Worker     return true;
1582*9356374aSAndroid Build Coastguard Worker   }
1583*9356374aSAndroid Build Coastguard Worker   MuHow how =
1584*9356374aSAndroid Build Coastguard Worker       (mu_.load(std::memory_order_relaxed) & kMuWriter) ? kExclusive : kShared;
1585*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_UNLOCK(this, TsanFlags(how));
1586*9356374aSAndroid Build Coastguard Worker   SynchWaitParams waitp(how, &cond, t, nullptr /*no cvmu*/,
1587*9356374aSAndroid Build Coastguard Worker                         Synch_GetPerThreadAnnotated(this),
1588*9356374aSAndroid Build Coastguard Worker                         nullptr /*no cv_word*/);
1589*9356374aSAndroid Build Coastguard Worker   this->UnlockSlow(&waitp);
1590*9356374aSAndroid Build Coastguard Worker   this->Block(waitp.thread);
1591*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how));
1592*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
1593*9356374aSAndroid Build Coastguard Worker   this->LockSlowLoop(&waitp, kMuHasBlocked | kMuIsCond);
1594*9356374aSAndroid Build Coastguard Worker   bool res = waitp.cond != nullptr ||  // => cond known true from LockSlowLoop
1595*9356374aSAndroid Build Coastguard Worker              EvalConditionAnnotated(&cond, this, true, false, how == kShared);
1596*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
1597*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(res || t.has_timeout(),
1598*9356374aSAndroid Build Coastguard Worker                  "condition untrue on return from Await");
1599*9356374aSAndroid Build Coastguard Worker   return res;
1600*9356374aSAndroid Build Coastguard Worker }
1601*9356374aSAndroid Build Coastguard Worker 
TryLock()1602*9356374aSAndroid Build Coastguard Worker bool Mutex::TryLock() {
1603*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
1604*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1605*9356374aSAndroid Build Coastguard Worker   // Try fast acquire.
1606*9356374aSAndroid Build Coastguard Worker   if (ABSL_PREDICT_TRUE((v & (kMuWriter | kMuReader | kMuEvent)) == 0)) {
1607*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(mu_.compare_exchange_strong(
1608*9356374aSAndroid Build Coastguard Worker             v, kMuWriter | v, std::memory_order_acquire,
1609*9356374aSAndroid Build Coastguard Worker             std::memory_order_relaxed))) {
1610*9356374aSAndroid Build Coastguard Worker       DebugOnlyLockEnter(this);
1611*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);
1612*9356374aSAndroid Build Coastguard Worker       return true;
1613*9356374aSAndroid Build Coastguard Worker     }
1614*9356374aSAndroid Build Coastguard Worker   } else if (ABSL_PREDICT_FALSE((v & kMuEvent) != 0)) {
1615*9356374aSAndroid Build Coastguard Worker     // We're recording events.
1616*9356374aSAndroid Build Coastguard Worker     return TryLockSlow();
1617*9356374aSAndroid Build Coastguard Worker   }
1618*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(
1619*9356374aSAndroid Build Coastguard Worker       this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0);
1620*9356374aSAndroid Build Coastguard Worker   return false;
1621*9356374aSAndroid Build Coastguard Worker }
1622*9356374aSAndroid Build Coastguard Worker 
TryLockSlow()1623*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_NOINLINE bool Mutex::TryLockSlow() {
1624*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1625*9356374aSAndroid Build Coastguard Worker   if ((v & kExclusive->slow_need_zero) == 0 &&  // try fast acquire
1626*9356374aSAndroid Build Coastguard Worker       mu_.compare_exchange_strong(
1627*9356374aSAndroid Build Coastguard Worker           v, (kExclusive->fast_or | v) + kExclusive->fast_add,
1628*9356374aSAndroid Build Coastguard Worker           std::memory_order_acquire, std::memory_order_relaxed)) {
1629*9356374aSAndroid Build Coastguard Worker     DebugOnlyLockEnter(this);
1630*9356374aSAndroid Build Coastguard Worker     PostSynchEvent(this, SYNCH_EV_TRYLOCK_SUCCESS);
1631*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);
1632*9356374aSAndroid Build Coastguard Worker     return true;
1633*9356374aSAndroid Build Coastguard Worker   }
1634*9356374aSAndroid Build Coastguard Worker   PostSynchEvent(this, SYNCH_EV_TRYLOCK_FAILED);
1635*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(
1636*9356374aSAndroid Build Coastguard Worker       this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0);
1637*9356374aSAndroid Build Coastguard Worker   return false;
1638*9356374aSAndroid Build Coastguard Worker }
1639*9356374aSAndroid Build Coastguard Worker 
ReaderTryLock()1640*9356374aSAndroid Build Coastguard Worker bool Mutex::ReaderTryLock() {
1641*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(this,
1642*9356374aSAndroid Build Coastguard Worker                            __tsan_mutex_read_lock | __tsan_mutex_try_lock);
1643*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1644*9356374aSAndroid Build Coastguard Worker   // Clang tends to unroll the loop when compiling with optimization.
1645*9356374aSAndroid Build Coastguard Worker   // But in this case it just unnecessary increases code size.
1646*9356374aSAndroid Build Coastguard Worker   // If CAS is failing due to contention, the jump cost is negligible.
1647*9356374aSAndroid Build Coastguard Worker #if defined(__clang__)
1648*9356374aSAndroid Build Coastguard Worker #pragma nounroll
1649*9356374aSAndroid Build Coastguard Worker #endif
1650*9356374aSAndroid Build Coastguard Worker   // The while-loops (here and below) iterate only if the mutex word keeps
1651*9356374aSAndroid Build Coastguard Worker   // changing (typically because the reader count changes) under the CAS.
1652*9356374aSAndroid Build Coastguard Worker   // We limit the number of attempts to avoid having to think about livelock.
1653*9356374aSAndroid Build Coastguard Worker   for (int loop_limit = 5; loop_limit != 0; loop_limit--) {
1654*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE((v & (kMuWriter | kMuWait | kMuEvent)) != 0)) {
1655*9356374aSAndroid Build Coastguard Worker       break;
1656*9356374aSAndroid Build Coastguard Worker     }
1657*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(mu_.compare_exchange_strong(
1658*9356374aSAndroid Build Coastguard Worker             v, (kMuReader | v) + kMuOne, std::memory_order_acquire,
1659*9356374aSAndroid Build Coastguard Worker             std::memory_order_relaxed))) {
1660*9356374aSAndroid Build Coastguard Worker       DebugOnlyLockEnter(this);
1661*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_POST_LOCK(
1662*9356374aSAndroid Build Coastguard Worker           this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0);
1663*9356374aSAndroid Build Coastguard Worker       return true;
1664*9356374aSAndroid Build Coastguard Worker     }
1665*9356374aSAndroid Build Coastguard Worker   }
1666*9356374aSAndroid Build Coastguard Worker   if (ABSL_PREDICT_TRUE((v & kMuEvent) == 0)) {
1667*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_LOCK(this,
1668*9356374aSAndroid Build Coastguard Worker                               __tsan_mutex_read_lock | __tsan_mutex_try_lock |
1669*9356374aSAndroid Build Coastguard Worker                                   __tsan_mutex_try_lock_failed,
1670*9356374aSAndroid Build Coastguard Worker                               0);
1671*9356374aSAndroid Build Coastguard Worker     return false;
1672*9356374aSAndroid Build Coastguard Worker   }
1673*9356374aSAndroid Build Coastguard Worker   // we're recording events
1674*9356374aSAndroid Build Coastguard Worker   return ReaderTryLockSlow();
1675*9356374aSAndroid Build Coastguard Worker }
1676*9356374aSAndroid Build Coastguard Worker 
ReaderTryLockSlow()1677*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_NOINLINE bool Mutex::ReaderTryLockSlow() {
1678*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1679*9356374aSAndroid Build Coastguard Worker #if defined(__clang__)
1680*9356374aSAndroid Build Coastguard Worker #pragma nounroll
1681*9356374aSAndroid Build Coastguard Worker #endif
1682*9356374aSAndroid Build Coastguard Worker   for (int loop_limit = 5; loop_limit != 0; loop_limit--) {
1683*9356374aSAndroid Build Coastguard Worker     if ((v & kShared->slow_need_zero) == 0 &&
1684*9356374aSAndroid Build Coastguard Worker         mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne,
1685*9356374aSAndroid Build Coastguard Worker                                     std::memory_order_acquire,
1686*9356374aSAndroid Build Coastguard Worker                                     std::memory_order_relaxed)) {
1687*9356374aSAndroid Build Coastguard Worker       DebugOnlyLockEnter(this);
1688*9356374aSAndroid Build Coastguard Worker       PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_SUCCESS);
1689*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_POST_LOCK(
1690*9356374aSAndroid Build Coastguard Worker           this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0);
1691*9356374aSAndroid Build Coastguard Worker       return true;
1692*9356374aSAndroid Build Coastguard Worker     }
1693*9356374aSAndroid Build Coastguard Worker   }
1694*9356374aSAndroid Build Coastguard Worker   PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_FAILED);
1695*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(this,
1696*9356374aSAndroid Build Coastguard Worker                             __tsan_mutex_read_lock | __tsan_mutex_try_lock |
1697*9356374aSAndroid Build Coastguard Worker                                 __tsan_mutex_try_lock_failed,
1698*9356374aSAndroid Build Coastguard Worker                             0);
1699*9356374aSAndroid Build Coastguard Worker   return false;
1700*9356374aSAndroid Build Coastguard Worker }
1701*9356374aSAndroid Build Coastguard Worker 
Unlock()1702*9356374aSAndroid Build Coastguard Worker void Mutex::Unlock() {
1703*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
1704*9356374aSAndroid Build Coastguard Worker   DebugOnlyLockLeave(this);
1705*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1706*9356374aSAndroid Build Coastguard Worker 
1707*9356374aSAndroid Build Coastguard Worker   if (kDebugMode && ((v & (kMuWriter | kMuReader)) != kMuWriter)) {
1708*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_LOG(FATAL, "Mutex unlocked when destroyed or not locked: v=0x%x",
1709*9356374aSAndroid Build Coastguard Worker                  static_cast<unsigned>(v));
1710*9356374aSAndroid Build Coastguard Worker   }
1711*9356374aSAndroid Build Coastguard Worker 
1712*9356374aSAndroid Build Coastguard Worker   // should_try_cas is whether we'll try a compare-and-swap immediately.
1713*9356374aSAndroid Build Coastguard Worker   // NOTE: optimized out when kDebugMode is false.
1714*9356374aSAndroid Build Coastguard Worker   bool should_try_cas = ((v & (kMuEvent | kMuWriter)) == kMuWriter &&
1715*9356374aSAndroid Build Coastguard Worker                          (v & (kMuWait | kMuDesig)) != kMuWait);
1716*9356374aSAndroid Build Coastguard Worker   // But, we can use an alternate computation of it, that compilers
1717*9356374aSAndroid Build Coastguard Worker   // currently don't find on their own.  When that changes, this function
1718*9356374aSAndroid Build Coastguard Worker   // can be simplified.
1719*9356374aSAndroid Build Coastguard Worker   intptr_t x = (v ^ (kMuWriter | kMuWait)) & (kMuWriter | kMuEvent);
1720*9356374aSAndroid Build Coastguard Worker   intptr_t y = (v ^ (kMuWriter | kMuWait)) & (kMuWait | kMuDesig);
1721*9356374aSAndroid Build Coastguard Worker   // Claim: "x == 0 && y > 0" is equal to should_try_cas.
1722*9356374aSAndroid Build Coastguard Worker   // Also, because kMuWriter and kMuEvent exceed kMuDesig and kMuWait,
1723*9356374aSAndroid Build Coastguard Worker   // all possible non-zero values for x exceed all possible values for y.
1724*9356374aSAndroid Build Coastguard Worker   // Therefore, (x == 0 && y > 0) == (x < y).
1725*9356374aSAndroid Build Coastguard Worker   if (kDebugMode && should_try_cas != (x < y)) {
1726*9356374aSAndroid Build Coastguard Worker     // We would usually use PRIdPTR here, but is not correctly implemented
1727*9356374aSAndroid Build Coastguard Worker     // within the android toolchain.
1728*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_LOG(FATAL, "internal logic error %llx %llx %llx\n",
1729*9356374aSAndroid Build Coastguard Worker                  static_cast<long long>(v), static_cast<long long>(x),
1730*9356374aSAndroid Build Coastguard Worker                  static_cast<long long>(y));
1731*9356374aSAndroid Build Coastguard Worker   }
1732*9356374aSAndroid Build Coastguard Worker   if (x < y && mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),
1733*9356374aSAndroid Build Coastguard Worker                                            std::memory_order_release,
1734*9356374aSAndroid Build Coastguard Worker                                            std::memory_order_relaxed)) {
1735*9356374aSAndroid Build Coastguard Worker     // fast writer release (writer with no waiters or with designated waker)
1736*9356374aSAndroid Build Coastguard Worker   } else {
1737*9356374aSAndroid Build Coastguard Worker     this->UnlockSlow(nullptr /*no waitp*/);  // take slow path
1738*9356374aSAndroid Build Coastguard Worker   }
1739*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);
1740*9356374aSAndroid Build Coastguard Worker }
1741*9356374aSAndroid Build Coastguard Worker 
1742*9356374aSAndroid Build Coastguard Worker // Requires v to represent a reader-locked state.
ExactlyOneReader(intptr_t v)1743*9356374aSAndroid Build Coastguard Worker static bool ExactlyOneReader(intptr_t v) {
1744*9356374aSAndroid Build Coastguard Worker   assert((v & (kMuWriter | kMuReader)) == kMuReader);
1745*9356374aSAndroid Build Coastguard Worker   assert((v & kMuHigh) != 0);
1746*9356374aSAndroid Build Coastguard Worker   // The more straightforward "(v & kMuHigh) == kMuOne" also works, but
1747*9356374aSAndroid Build Coastguard Worker   // on some architectures the following generates slightly smaller code.
1748*9356374aSAndroid Build Coastguard Worker   // It may be faster too.
1749*9356374aSAndroid Build Coastguard Worker   constexpr intptr_t kMuMultipleWaitersMask = kMuHigh ^ kMuOne;
1750*9356374aSAndroid Build Coastguard Worker   return (v & kMuMultipleWaitersMask) == 0;
1751*9356374aSAndroid Build Coastguard Worker }
1752*9356374aSAndroid Build Coastguard Worker 
ReaderUnlock()1753*9356374aSAndroid Build Coastguard Worker void Mutex::ReaderUnlock() {
1754*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_UNLOCK(this, __tsan_mutex_read_lock);
1755*9356374aSAndroid Build Coastguard Worker   DebugOnlyLockLeave(this);
1756*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1757*9356374aSAndroid Build Coastguard Worker   assert((v & (kMuWriter | kMuReader)) == kMuReader);
1758*9356374aSAndroid Build Coastguard Worker   for (;;) {
1759*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE((v & (kMuReader | kMuWait | kMuEvent)) !=
1760*9356374aSAndroid Build Coastguard Worker                            kMuReader)) {
1761*9356374aSAndroid Build Coastguard Worker       this->UnlockSlow(nullptr /*no waitp*/);  // take slow path
1762*9356374aSAndroid Build Coastguard Worker       break;
1763*9356374aSAndroid Build Coastguard Worker     }
1764*9356374aSAndroid Build Coastguard Worker     // fast reader release (reader with no waiters)
1765*9356374aSAndroid Build Coastguard Worker     intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne;
1766*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_TRUE(
1767*9356374aSAndroid Build Coastguard Worker             mu_.compare_exchange_strong(v, v - clear, std::memory_order_release,
1768*9356374aSAndroid Build Coastguard Worker                                         std::memory_order_relaxed))) {
1769*9356374aSAndroid Build Coastguard Worker       break;
1770*9356374aSAndroid Build Coastguard Worker     }
1771*9356374aSAndroid Build Coastguard Worker   }
1772*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock);
1773*9356374aSAndroid Build Coastguard Worker }
1774*9356374aSAndroid Build Coastguard Worker 
1775*9356374aSAndroid Build Coastguard Worker // Clears the designated waker flag in the mutex if this thread has blocked, and
1776*9356374aSAndroid Build Coastguard Worker // therefore may be the designated waker.
ClearDesignatedWakerMask(int flag)1777*9356374aSAndroid Build Coastguard Worker static intptr_t ClearDesignatedWakerMask(int flag) {
1778*9356374aSAndroid Build Coastguard Worker   assert(flag >= 0);
1779*9356374aSAndroid Build Coastguard Worker   assert(flag <= 1);
1780*9356374aSAndroid Build Coastguard Worker   switch (flag) {
1781*9356374aSAndroid Build Coastguard Worker     case 0:  // not blocked
1782*9356374aSAndroid Build Coastguard Worker       return ~static_cast<intptr_t>(0);
1783*9356374aSAndroid Build Coastguard Worker     case 1:  // blocked; turn off the designated waker bit
1784*9356374aSAndroid Build Coastguard Worker       return ~static_cast<intptr_t>(kMuDesig);
1785*9356374aSAndroid Build Coastguard Worker   }
1786*9356374aSAndroid Build Coastguard Worker   ABSL_UNREACHABLE();
1787*9356374aSAndroid Build Coastguard Worker }
1788*9356374aSAndroid Build Coastguard Worker 
1789*9356374aSAndroid Build Coastguard Worker // Conditionally ignores the existence of waiting writers if a reader that has
1790*9356374aSAndroid Build Coastguard Worker // already blocked once wakes up.
IgnoreWaitingWritersMask(int flag)1791*9356374aSAndroid Build Coastguard Worker static intptr_t IgnoreWaitingWritersMask(int flag) {
1792*9356374aSAndroid Build Coastguard Worker   assert(flag >= 0);
1793*9356374aSAndroid Build Coastguard Worker   assert(flag <= 1);
1794*9356374aSAndroid Build Coastguard Worker   switch (flag) {
1795*9356374aSAndroid Build Coastguard Worker     case 0:  // not blocked
1796*9356374aSAndroid Build Coastguard Worker       return ~static_cast<intptr_t>(0);
1797*9356374aSAndroid Build Coastguard Worker     case 1:  // blocked; pretend there are no waiting writers
1798*9356374aSAndroid Build Coastguard Worker       return ~static_cast<intptr_t>(kMuWrWait);
1799*9356374aSAndroid Build Coastguard Worker   }
1800*9356374aSAndroid Build Coastguard Worker   ABSL_UNREACHABLE();
1801*9356374aSAndroid Build Coastguard Worker }
1802*9356374aSAndroid Build Coastguard Worker 
1803*9356374aSAndroid Build Coastguard Worker // Internal version of LockWhen().  See LockSlowWithDeadline()
LockSlow(MuHow how,const Condition * cond,int flags)1804*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition* cond,
1805*9356374aSAndroid Build Coastguard Worker                                              int flags) {
1806*9356374aSAndroid Build Coastguard Worker   // Note: we specifically initialize spinloop_iterations after the first use
1807*9356374aSAndroid Build Coastguard Worker   // in TryAcquireWithSpinning so that Lock function does not have any non-tail
1808*9356374aSAndroid Build Coastguard Worker   // calls and consequently a stack frame. It's fine to have spinloop_iterations
1809*9356374aSAndroid Build Coastguard Worker   // uninitialized (meaning no spinning) in all initial uncontended Lock calls
1810*9356374aSAndroid Build Coastguard Worker   // and in the first contended call. After that we will have
1811*9356374aSAndroid Build Coastguard Worker   // spinloop_iterations properly initialized.
1812*9356374aSAndroid Build Coastguard Worker   if (ABSL_PREDICT_FALSE(
1813*9356374aSAndroid Build Coastguard Worker           globals.spinloop_iterations.load(std::memory_order_relaxed) == 0)) {
1814*9356374aSAndroid Build Coastguard Worker     if (absl::base_internal::NumCPUs() > 1) {
1815*9356374aSAndroid Build Coastguard Worker       // If this is multiprocessor, allow spinning.
1816*9356374aSAndroid Build Coastguard Worker       globals.spinloop_iterations.store(1500, std::memory_order_relaxed);
1817*9356374aSAndroid Build Coastguard Worker     } else {
1818*9356374aSAndroid Build Coastguard Worker       // If this a uniprocessor, only yield/sleep.
1819*9356374aSAndroid Build Coastguard Worker       globals.spinloop_iterations.store(-1, std::memory_order_relaxed);
1820*9356374aSAndroid Build Coastguard Worker     }
1821*9356374aSAndroid Build Coastguard Worker   }
1822*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(
1823*9356374aSAndroid Build Coastguard Worker       this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags),
1824*9356374aSAndroid Build Coastguard Worker       "condition untrue on return from LockSlow");
1825*9356374aSAndroid Build Coastguard Worker }
1826*9356374aSAndroid Build Coastguard Worker 
1827*9356374aSAndroid Build Coastguard Worker // Compute cond->Eval() and tell race detectors that we do it under mutex mu.
EvalConditionAnnotated(const Condition * cond,Mutex * mu,bool locking,bool trylock,bool read_lock)1828*9356374aSAndroid Build Coastguard Worker static inline bool EvalConditionAnnotated(const Condition* cond, Mutex* mu,
1829*9356374aSAndroid Build Coastguard Worker                                           bool locking, bool trylock,
1830*9356374aSAndroid Build Coastguard Worker                                           bool read_lock) {
1831*9356374aSAndroid Build Coastguard Worker   // Delicate annotation dance.
1832*9356374aSAndroid Build Coastguard Worker   // We are currently inside of read/write lock/unlock operation.
1833*9356374aSAndroid Build Coastguard Worker   // All memory accesses are ignored inside of mutex operations + for unlock
1834*9356374aSAndroid Build Coastguard Worker   // operation tsan considers that we've already released the mutex.
1835*9356374aSAndroid Build Coastguard Worker   bool res = false;
1836*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
1837*9356374aSAndroid Build Coastguard Worker   const uint32_t flags = read_lock ? __tsan_mutex_read_lock : 0;
1838*9356374aSAndroid Build Coastguard Worker   const uint32_t tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
1839*9356374aSAndroid Build Coastguard Worker #endif
1840*9356374aSAndroid Build Coastguard Worker   if (locking) {
1841*9356374aSAndroid Build Coastguard Worker     // For lock we pretend that we have finished the operation,
1842*9356374aSAndroid Build Coastguard Worker     // evaluate the predicate, then unlock the mutex and start locking it again
1843*9356374aSAndroid Build Coastguard Worker     // to match the annotation at the end of outer lock operation.
1844*9356374aSAndroid Build Coastguard Worker     // Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan
1845*9356374aSAndroid Build Coastguard Worker     // will think the lock acquisition is recursive which will trigger
1846*9356374aSAndroid Build Coastguard Worker     // deadlock detector.
1847*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0);
1848*9356374aSAndroid Build Coastguard Worker     res = cond->Eval();
1849*9356374aSAndroid Build Coastguard Worker     // There is no "try" version of Unlock, so use flags instead of tryflags.
1850*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
1851*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
1852*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags);
1853*9356374aSAndroid Build Coastguard Worker   } else {
1854*9356374aSAndroid Build Coastguard Worker     // Similarly, for unlock we pretend that we have unlocked the mutex,
1855*9356374aSAndroid Build Coastguard Worker     // lock the mutex, evaluate the predicate, and start unlocking it again
1856*9356374aSAndroid Build Coastguard Worker     // to match the annotation at the end of outer unlock operation.
1857*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
1858*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags);
1859*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0);
1860*9356374aSAndroid Build Coastguard Worker     res = cond->Eval();
1861*9356374aSAndroid Build Coastguard Worker     ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
1862*9356374aSAndroid Build Coastguard Worker   }
1863*9356374aSAndroid Build Coastguard Worker   // Prevent unused param warnings in non-TSAN builds.
1864*9356374aSAndroid Build Coastguard Worker   static_cast<void>(mu);
1865*9356374aSAndroid Build Coastguard Worker   static_cast<void>(trylock);
1866*9356374aSAndroid Build Coastguard Worker   static_cast<void>(read_lock);
1867*9356374aSAndroid Build Coastguard Worker   return res;
1868*9356374aSAndroid Build Coastguard Worker }
1869*9356374aSAndroid Build Coastguard Worker 
1870*9356374aSAndroid Build Coastguard Worker // Compute cond->Eval() hiding it from race detectors.
1871*9356374aSAndroid Build Coastguard Worker // We are hiding it because inside of UnlockSlow we can evaluate a predicate
1872*9356374aSAndroid Build Coastguard Worker // that was just added by a concurrent Lock operation; Lock adds the predicate
1873*9356374aSAndroid Build Coastguard Worker // to the internal Mutex list without actually acquiring the Mutex
1874*9356374aSAndroid Build Coastguard Worker // (it only acquires the internal spinlock, which is rightfully invisible for
1875*9356374aSAndroid Build Coastguard Worker // tsan). As the result there is no tsan-visible synchronization between the
1876*9356374aSAndroid Build Coastguard Worker // addition and this thread. So if we would enable race detection here,
1877*9356374aSAndroid Build Coastguard Worker // it would race with the predicate initialization.
EvalConditionIgnored(Mutex * mu,const Condition * cond)1878*9356374aSAndroid Build Coastguard Worker static inline bool EvalConditionIgnored(Mutex* mu, const Condition* cond) {
1879*9356374aSAndroid Build Coastguard Worker   // Memory accesses are already ignored inside of lock/unlock operations,
1880*9356374aSAndroid Build Coastguard Worker   // but synchronization operations are also ignored. When we evaluate the
1881*9356374aSAndroid Build Coastguard Worker   // predicate we must ignore only memory accesses but not synchronization,
1882*9356374aSAndroid Build Coastguard Worker   // because missed synchronization can lead to false reports later.
1883*9356374aSAndroid Build Coastguard Worker   // So we "divert" (which un-ignores both memory accesses and synchronization)
1884*9356374aSAndroid Build Coastguard Worker   // and then separately turn on ignores of memory accesses.
1885*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
1886*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
1887*9356374aSAndroid Build Coastguard Worker   bool res = cond->Eval();
1888*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
1889*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
1890*9356374aSAndroid Build Coastguard Worker   static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.
1891*9356374aSAndroid Build Coastguard Worker   return res;
1892*9356374aSAndroid Build Coastguard Worker }
1893*9356374aSAndroid Build Coastguard Worker 
1894*9356374aSAndroid Build Coastguard Worker // Internal equivalent of *LockWhenWithDeadline(), where
1895*9356374aSAndroid Build Coastguard Worker //   "t" represents the absolute timeout; !t.has_timeout() means "forever".
1896*9356374aSAndroid Build Coastguard Worker //   "how" is "kShared" (for ReaderLockWhen) or "kExclusive" (for LockWhen)
1897*9356374aSAndroid Build Coastguard Worker // In flags, bits are ored together:
1898*9356374aSAndroid Build Coastguard Worker // - kMuHasBlocked indicates that the client has already blocked on the call so
1899*9356374aSAndroid Build Coastguard Worker //   the designated waker bit must be cleared and waiting writers should not
1900*9356374aSAndroid Build Coastguard Worker //   obstruct this call
1901*9356374aSAndroid Build Coastguard Worker // - kMuIsCond indicates that this is a conditional acquire (condition variable,
1902*9356374aSAndroid Build Coastguard Worker //   Await,  LockWhen) so contention profiling should be suppressed.
LockSlowWithDeadline(MuHow how,const Condition * cond,KernelTimeout t,int flags)1903*9356374aSAndroid Build Coastguard Worker bool Mutex::LockSlowWithDeadline(MuHow how, const Condition* cond,
1904*9356374aSAndroid Build Coastguard Worker                                  KernelTimeout t, int flags) {
1905*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1906*9356374aSAndroid Build Coastguard Worker   bool unlock = false;
1907*9356374aSAndroid Build Coastguard Worker   if ((v & how->fast_need_zero) == 0 &&  // try fast acquire
1908*9356374aSAndroid Build Coastguard Worker       mu_.compare_exchange_strong(
1909*9356374aSAndroid Build Coastguard Worker           v,
1910*9356374aSAndroid Build Coastguard Worker           (how->fast_or |
1911*9356374aSAndroid Build Coastguard Worker            (v & ClearDesignatedWakerMask(flags & kMuHasBlocked))) +
1912*9356374aSAndroid Build Coastguard Worker               how->fast_add,
1913*9356374aSAndroid Build Coastguard Worker           std::memory_order_acquire, std::memory_order_relaxed)) {
1914*9356374aSAndroid Build Coastguard Worker     if (cond == nullptr ||
1915*9356374aSAndroid Build Coastguard Worker         EvalConditionAnnotated(cond, this, true, false, how == kShared)) {
1916*9356374aSAndroid Build Coastguard Worker       return true;
1917*9356374aSAndroid Build Coastguard Worker     }
1918*9356374aSAndroid Build Coastguard Worker     unlock = true;
1919*9356374aSAndroid Build Coastguard Worker   }
1920*9356374aSAndroid Build Coastguard Worker   SynchWaitParams waitp(how, cond, t, nullptr /*no cvmu*/,
1921*9356374aSAndroid Build Coastguard Worker                         Synch_GetPerThreadAnnotated(this),
1922*9356374aSAndroid Build Coastguard Worker                         nullptr /*no cv_word*/);
1923*9356374aSAndroid Build Coastguard Worker   if (cond != nullptr) {
1924*9356374aSAndroid Build Coastguard Worker     flags |= kMuIsCond;
1925*9356374aSAndroid Build Coastguard Worker   }
1926*9356374aSAndroid Build Coastguard Worker   if (unlock) {
1927*9356374aSAndroid Build Coastguard Worker     this->UnlockSlow(&waitp);
1928*9356374aSAndroid Build Coastguard Worker     this->Block(waitp.thread);
1929*9356374aSAndroid Build Coastguard Worker     flags |= kMuHasBlocked;
1930*9356374aSAndroid Build Coastguard Worker   }
1931*9356374aSAndroid Build Coastguard Worker   this->LockSlowLoop(&waitp, flags);
1932*9356374aSAndroid Build Coastguard Worker   return waitp.cond != nullptr ||  // => cond known true from LockSlowLoop
1933*9356374aSAndroid Build Coastguard Worker          cond == nullptr ||
1934*9356374aSAndroid Build Coastguard Worker          EvalConditionAnnotated(cond, this, true, false, how == kShared);
1935*9356374aSAndroid Build Coastguard Worker }
1936*9356374aSAndroid Build Coastguard Worker 
1937*9356374aSAndroid Build Coastguard Worker // RAW_CHECK_FMT() takes a condition, a printf-style format string, and
1938*9356374aSAndroid Build Coastguard Worker // the printf-style argument list.   The format string must be a literal.
1939*9356374aSAndroid Build Coastguard Worker // Arguments after the first are not evaluated unless the condition is true.
1940*9356374aSAndroid Build Coastguard Worker #define RAW_CHECK_FMT(cond, ...)                                   \
1941*9356374aSAndroid Build Coastguard Worker   do {                                                             \
1942*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(!(cond))) {                             \
1943*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_LOG(FATAL, "Check " #cond " failed: " __VA_ARGS__); \
1944*9356374aSAndroid Build Coastguard Worker     }                                                              \
1945*9356374aSAndroid Build Coastguard Worker   } while (0)
1946*9356374aSAndroid Build Coastguard Worker 
CheckForMutexCorruption(intptr_t v,const char * label)1947*9356374aSAndroid Build Coastguard Worker static void CheckForMutexCorruption(intptr_t v, const char* label) {
1948*9356374aSAndroid Build Coastguard Worker   // Test for either of two situations that should not occur in v:
1949*9356374aSAndroid Build Coastguard Worker   //   kMuWriter and kMuReader
1950*9356374aSAndroid Build Coastguard Worker   //   kMuWrWait and !kMuWait
1951*9356374aSAndroid Build Coastguard Worker   const uintptr_t w = static_cast<uintptr_t>(v ^ kMuWait);
1952*9356374aSAndroid Build Coastguard Worker   // By flipping that bit, we can now test for:
1953*9356374aSAndroid Build Coastguard Worker   //   kMuWriter and kMuReader in w
1954*9356374aSAndroid Build Coastguard Worker   //   kMuWrWait and kMuWait in w
1955*9356374aSAndroid Build Coastguard Worker   // We've chosen these two pairs of values to be so that they will overlap,
1956*9356374aSAndroid Build Coastguard Worker   // respectively, when the word is left shifted by three.  This allows us to
1957*9356374aSAndroid Build Coastguard Worker   // save a branch in the common (correct) case of them not being coincident.
1958*9356374aSAndroid Build Coastguard Worker   static_assert(kMuReader << 3 == kMuWriter, "must match");
1959*9356374aSAndroid Build Coastguard Worker   static_assert(kMuWait << 3 == kMuWrWait, "must match");
1960*9356374aSAndroid Build Coastguard Worker   if (ABSL_PREDICT_TRUE((w & (w << 3) & (kMuWriter | kMuWrWait)) == 0)) return;
1961*9356374aSAndroid Build Coastguard Worker   RAW_CHECK_FMT((v & (kMuWriter | kMuReader)) != (kMuWriter | kMuReader),
1962*9356374aSAndroid Build Coastguard Worker                 "%s: Mutex corrupt: both reader and writer lock held: %p",
1963*9356374aSAndroid Build Coastguard Worker                 label, reinterpret_cast<void*>(v));
1964*9356374aSAndroid Build Coastguard Worker   RAW_CHECK_FMT((v & (kMuWait | kMuWrWait)) != kMuWrWait,
1965*9356374aSAndroid Build Coastguard Worker                 "%s: Mutex corrupt: waiting writer with no waiters: %p", label,
1966*9356374aSAndroid Build Coastguard Worker                 reinterpret_cast<void*>(v));
1967*9356374aSAndroid Build Coastguard Worker   assert(false);
1968*9356374aSAndroid Build Coastguard Worker }
1969*9356374aSAndroid Build Coastguard Worker 
LockSlowLoop(SynchWaitParams * waitp,int flags)1970*9356374aSAndroid Build Coastguard Worker void Mutex::LockSlowLoop(SynchWaitParams* waitp, int flags) {
1971*9356374aSAndroid Build Coastguard Worker   SchedulingGuard::ScopedDisable disable_rescheduling;
1972*9356374aSAndroid Build Coastguard Worker   int c = 0;
1973*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
1974*9356374aSAndroid Build Coastguard Worker   if ((v & kMuEvent) != 0) {
1975*9356374aSAndroid Build Coastguard Worker     PostSynchEvent(
1976*9356374aSAndroid Build Coastguard Worker         this, waitp->how == kExclusive ? SYNCH_EV_LOCK : SYNCH_EV_READERLOCK);
1977*9356374aSAndroid Build Coastguard Worker   }
1978*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(
1979*9356374aSAndroid Build Coastguard Worker       waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
1980*9356374aSAndroid Build Coastguard Worker       "detected illegal recursion into Mutex code");
1981*9356374aSAndroid Build Coastguard Worker   for (;;) {
1982*9356374aSAndroid Build Coastguard Worker     v = mu_.load(std::memory_order_relaxed);
1983*9356374aSAndroid Build Coastguard Worker     CheckForMutexCorruption(v, "Lock");
1984*9356374aSAndroid Build Coastguard Worker     if ((v & waitp->how->slow_need_zero) == 0) {
1985*9356374aSAndroid Build Coastguard Worker       if (mu_.compare_exchange_strong(
1986*9356374aSAndroid Build Coastguard Worker               v,
1987*9356374aSAndroid Build Coastguard Worker               (waitp->how->fast_or |
1988*9356374aSAndroid Build Coastguard Worker                (v & ClearDesignatedWakerMask(flags & kMuHasBlocked))) +
1989*9356374aSAndroid Build Coastguard Worker                   waitp->how->fast_add,
1990*9356374aSAndroid Build Coastguard Worker               std::memory_order_acquire, std::memory_order_relaxed)) {
1991*9356374aSAndroid Build Coastguard Worker         if (waitp->cond == nullptr ||
1992*9356374aSAndroid Build Coastguard Worker             EvalConditionAnnotated(waitp->cond, this, true, false,
1993*9356374aSAndroid Build Coastguard Worker                                    waitp->how == kShared)) {
1994*9356374aSAndroid Build Coastguard Worker           break;  // we timed out, or condition true, so return
1995*9356374aSAndroid Build Coastguard Worker         }
1996*9356374aSAndroid Build Coastguard Worker         this->UnlockSlow(waitp);  // got lock but condition false
1997*9356374aSAndroid Build Coastguard Worker         this->Block(waitp->thread);
1998*9356374aSAndroid Build Coastguard Worker         flags |= kMuHasBlocked;
1999*9356374aSAndroid Build Coastguard Worker         c = 0;
2000*9356374aSAndroid Build Coastguard Worker       }
2001*9356374aSAndroid Build Coastguard Worker     } else {  // need to access waiter list
2002*9356374aSAndroid Build Coastguard Worker       bool dowait = false;
2003*9356374aSAndroid Build Coastguard Worker       if ((v & (kMuSpin | kMuWait)) == 0) {  // no waiters
2004*9356374aSAndroid Build Coastguard Worker         // This thread tries to become the one and only waiter.
2005*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* new_h = Enqueue(nullptr, waitp, v, flags);
2006*9356374aSAndroid Build Coastguard Worker         intptr_t nv =
2007*9356374aSAndroid Build Coastguard Worker             (v & ClearDesignatedWakerMask(flags & kMuHasBlocked) & kMuLow) |
2008*9356374aSAndroid Build Coastguard Worker             kMuWait;
2009*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to empty list failed");
2010*9356374aSAndroid Build Coastguard Worker         if (waitp->how == kExclusive && (v & kMuReader) != 0) {
2011*9356374aSAndroid Build Coastguard Worker           nv |= kMuWrWait;
2012*9356374aSAndroid Build Coastguard Worker         }
2013*9356374aSAndroid Build Coastguard Worker         if (mu_.compare_exchange_strong(
2014*9356374aSAndroid Build Coastguard Worker                 v, reinterpret_cast<intptr_t>(new_h) | nv,
2015*9356374aSAndroid Build Coastguard Worker                 std::memory_order_release, std::memory_order_relaxed)) {
2016*9356374aSAndroid Build Coastguard Worker           dowait = true;
2017*9356374aSAndroid Build Coastguard Worker         } else {  // attempted Enqueue() failed
2018*9356374aSAndroid Build Coastguard Worker           // zero out the waitp field set by Enqueue()
2019*9356374aSAndroid Build Coastguard Worker           waitp->thread->waitp = nullptr;
2020*9356374aSAndroid Build Coastguard Worker         }
2021*9356374aSAndroid Build Coastguard Worker       } else if ((v & waitp->how->slow_inc_need_zero &
2022*9356374aSAndroid Build Coastguard Worker                   IgnoreWaitingWritersMask(flags & kMuHasBlocked)) == 0) {
2023*9356374aSAndroid Build Coastguard Worker         // This is a reader that needs to increment the reader count,
2024*9356374aSAndroid Build Coastguard Worker         // but the count is currently held in the last waiter.
2025*9356374aSAndroid Build Coastguard Worker         if (mu_.compare_exchange_strong(
2026*9356374aSAndroid Build Coastguard Worker                 v,
2027*9356374aSAndroid Build Coastguard Worker                 (v & ClearDesignatedWakerMask(flags & kMuHasBlocked)) |
2028*9356374aSAndroid Build Coastguard Worker                     kMuSpin | kMuReader,
2029*9356374aSAndroid Build Coastguard Worker                 std::memory_order_acquire, std::memory_order_relaxed)) {
2030*9356374aSAndroid Build Coastguard Worker           PerThreadSynch* h = GetPerThreadSynch(v);
2031*9356374aSAndroid Build Coastguard Worker           h->readers += kMuOne;  // inc reader count in waiter
2032*9356374aSAndroid Build Coastguard Worker           do {                   // release spinlock
2033*9356374aSAndroid Build Coastguard Worker             v = mu_.load(std::memory_order_relaxed);
2034*9356374aSAndroid Build Coastguard Worker           } while (!mu_.compare_exchange_weak(v, (v & ~kMuSpin) | kMuReader,
2035*9356374aSAndroid Build Coastguard Worker                                               std::memory_order_release,
2036*9356374aSAndroid Build Coastguard Worker                                               std::memory_order_relaxed));
2037*9356374aSAndroid Build Coastguard Worker           if (waitp->cond == nullptr ||
2038*9356374aSAndroid Build Coastguard Worker               EvalConditionAnnotated(waitp->cond, this, true, false,
2039*9356374aSAndroid Build Coastguard Worker                                      waitp->how == kShared)) {
2040*9356374aSAndroid Build Coastguard Worker             break;  // we timed out, or condition true, so return
2041*9356374aSAndroid Build Coastguard Worker           }
2042*9356374aSAndroid Build Coastguard Worker           this->UnlockSlow(waitp);  // got lock but condition false
2043*9356374aSAndroid Build Coastguard Worker           this->Block(waitp->thread);
2044*9356374aSAndroid Build Coastguard Worker           flags |= kMuHasBlocked;
2045*9356374aSAndroid Build Coastguard Worker           c = 0;
2046*9356374aSAndroid Build Coastguard Worker         }
2047*9356374aSAndroid Build Coastguard Worker       } else if ((v & kMuSpin) == 0 &&  // attempt to queue ourselves
2048*9356374aSAndroid Build Coastguard Worker                  mu_.compare_exchange_strong(
2049*9356374aSAndroid Build Coastguard Worker                      v,
2050*9356374aSAndroid Build Coastguard Worker                      (v & ClearDesignatedWakerMask(flags & kMuHasBlocked)) |
2051*9356374aSAndroid Build Coastguard Worker                          kMuSpin | kMuWait,
2052*9356374aSAndroid Build Coastguard Worker                      std::memory_order_acquire, std::memory_order_relaxed)) {
2053*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* h = GetPerThreadSynch(v);
2054*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* new_h = Enqueue(h, waitp, v, flags);
2055*9356374aSAndroid Build Coastguard Worker         intptr_t wr_wait = 0;
2056*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to list failed");
2057*9356374aSAndroid Build Coastguard Worker         if (waitp->how == kExclusive && (v & kMuReader) != 0) {
2058*9356374aSAndroid Build Coastguard Worker           wr_wait = kMuWrWait;  // give priority to a waiting writer
2059*9356374aSAndroid Build Coastguard Worker         }
2060*9356374aSAndroid Build Coastguard Worker         do {  // release spinlock
2061*9356374aSAndroid Build Coastguard Worker           v = mu_.load(std::memory_order_relaxed);
2062*9356374aSAndroid Build Coastguard Worker         } while (!mu_.compare_exchange_weak(
2063*9356374aSAndroid Build Coastguard Worker             v,
2064*9356374aSAndroid Build Coastguard Worker             (v & (kMuLow & ~kMuSpin)) | kMuWait | wr_wait |
2065*9356374aSAndroid Build Coastguard Worker                 reinterpret_cast<intptr_t>(new_h),
2066*9356374aSAndroid Build Coastguard Worker             std::memory_order_release, std::memory_order_relaxed));
2067*9356374aSAndroid Build Coastguard Worker         dowait = true;
2068*9356374aSAndroid Build Coastguard Worker       }
2069*9356374aSAndroid Build Coastguard Worker       if (dowait) {
2070*9356374aSAndroid Build Coastguard Worker         this->Block(waitp->thread);  // wait until removed from list or timeout
2071*9356374aSAndroid Build Coastguard Worker         flags |= kMuHasBlocked;
2072*9356374aSAndroid Build Coastguard Worker         c = 0;
2073*9356374aSAndroid Build Coastguard Worker       }
2074*9356374aSAndroid Build Coastguard Worker     }
2075*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_CHECK(
2076*9356374aSAndroid Build Coastguard Worker         waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
2077*9356374aSAndroid Build Coastguard Worker         "detected illegal recursion into Mutex code");
2078*9356374aSAndroid Build Coastguard Worker     // delay, then try again
2079*9356374aSAndroid Build Coastguard Worker     c = synchronization_internal::MutexDelay(c, GENTLE);
2080*9356374aSAndroid Build Coastguard Worker   }
2081*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(
2082*9356374aSAndroid Build Coastguard Worker       waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
2083*9356374aSAndroid Build Coastguard Worker       "detected illegal recursion into Mutex code");
2084*9356374aSAndroid Build Coastguard Worker   if ((v & kMuEvent) != 0) {
2085*9356374aSAndroid Build Coastguard Worker     PostSynchEvent(this, waitp->how == kExclusive
2086*9356374aSAndroid Build Coastguard Worker                              ? SYNCH_EV_LOCK_RETURNING
2087*9356374aSAndroid Build Coastguard Worker                              : SYNCH_EV_READERLOCK_RETURNING);
2088*9356374aSAndroid Build Coastguard Worker   }
2089*9356374aSAndroid Build Coastguard Worker }
2090*9356374aSAndroid Build Coastguard Worker 
2091*9356374aSAndroid Build Coastguard Worker // Unlock this mutex, which is held by the current thread.
2092*9356374aSAndroid Build Coastguard Worker // If waitp is non-zero, it must be the wait parameters for the current thread
2093*9356374aSAndroid Build Coastguard Worker // which holds the lock but is not runnable because its condition is false
2094*9356374aSAndroid Build Coastguard Worker // or it is in the process of blocking on a condition variable; it must requeue
2095*9356374aSAndroid Build Coastguard Worker // itself on the mutex/condvar to wait for its condition to become true.
UnlockSlow(SynchWaitParams * waitp)2096*9356374aSAndroid Build Coastguard Worker ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams* waitp) {
2097*9356374aSAndroid Build Coastguard Worker   SchedulingGuard::ScopedDisable disable_rescheduling;
2098*9356374aSAndroid Build Coastguard Worker   intptr_t v = mu_.load(std::memory_order_relaxed);
2099*9356374aSAndroid Build Coastguard Worker   this->AssertReaderHeld();
2100*9356374aSAndroid Build Coastguard Worker   CheckForMutexCorruption(v, "Unlock");
2101*9356374aSAndroid Build Coastguard Worker   if ((v & kMuEvent) != 0) {
2102*9356374aSAndroid Build Coastguard Worker     PostSynchEvent(
2103*9356374aSAndroid Build Coastguard Worker         this, (v & kMuWriter) != 0 ? SYNCH_EV_UNLOCK : SYNCH_EV_READERUNLOCK);
2104*9356374aSAndroid Build Coastguard Worker   }
2105*9356374aSAndroid Build Coastguard Worker   int c = 0;
2106*9356374aSAndroid Build Coastguard Worker   // the waiter under consideration to wake, or zero
2107*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* w = nullptr;
2108*9356374aSAndroid Build Coastguard Worker   // the predecessor to w or zero
2109*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* pw = nullptr;
2110*9356374aSAndroid Build Coastguard Worker   // head of the list searched previously, or zero
2111*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* old_h = nullptr;
2112*9356374aSAndroid Build Coastguard Worker   // a condition that's known to be false.
2113*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* wake_list = kPerThreadSynchNull;  // list of threads to wake
2114*9356374aSAndroid Build Coastguard Worker   intptr_t wr_wait = 0;  // set to kMuWrWait if we wake a reader and a
2115*9356374aSAndroid Build Coastguard Worker                          // later writer could have acquired the lock
2116*9356374aSAndroid Build Coastguard Worker                          // (starvation avoidance)
2117*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(waitp == nullptr || waitp->thread->waitp == nullptr ||
2118*9356374aSAndroid Build Coastguard Worker                      waitp->thread->suppress_fatal_errors,
2119*9356374aSAndroid Build Coastguard Worker                  "detected illegal recursion into Mutex code");
2120*9356374aSAndroid Build Coastguard Worker   // This loop finds threads wake_list to wakeup if any, and removes them from
2121*9356374aSAndroid Build Coastguard Worker   // the list of waiters.  In addition, it places waitp.thread on the queue of
2122*9356374aSAndroid Build Coastguard Worker   // waiters if waitp is non-zero.
2123*9356374aSAndroid Build Coastguard Worker   for (;;) {
2124*9356374aSAndroid Build Coastguard Worker     v = mu_.load(std::memory_order_relaxed);
2125*9356374aSAndroid Build Coastguard Worker     if ((v & kMuWriter) != 0 && (v & (kMuWait | kMuDesig)) != kMuWait &&
2126*9356374aSAndroid Build Coastguard Worker         waitp == nullptr) {
2127*9356374aSAndroid Build Coastguard Worker       // fast writer release (writer with no waiters or with designated waker)
2128*9356374aSAndroid Build Coastguard Worker       if (mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),
2129*9356374aSAndroid Build Coastguard Worker                                       std::memory_order_release,
2130*9356374aSAndroid Build Coastguard Worker                                       std::memory_order_relaxed)) {
2131*9356374aSAndroid Build Coastguard Worker         return;
2132*9356374aSAndroid Build Coastguard Worker       }
2133*9356374aSAndroid Build Coastguard Worker     } else if ((v & (kMuReader | kMuWait)) == kMuReader && waitp == nullptr) {
2134*9356374aSAndroid Build Coastguard Worker       // fast reader release (reader with no waiters)
2135*9356374aSAndroid Build Coastguard Worker       intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne;
2136*9356374aSAndroid Build Coastguard Worker       if (mu_.compare_exchange_strong(v, v - clear, std::memory_order_release,
2137*9356374aSAndroid Build Coastguard Worker                                       std::memory_order_relaxed)) {
2138*9356374aSAndroid Build Coastguard Worker         return;
2139*9356374aSAndroid Build Coastguard Worker       }
2140*9356374aSAndroid Build Coastguard Worker     } else if ((v & kMuSpin) == 0 &&  // attempt to get spinlock
2141*9356374aSAndroid Build Coastguard Worker                mu_.compare_exchange_strong(v, v | kMuSpin,
2142*9356374aSAndroid Build Coastguard Worker                                            std::memory_order_acquire,
2143*9356374aSAndroid Build Coastguard Worker                                            std::memory_order_relaxed)) {
2144*9356374aSAndroid Build Coastguard Worker       if ((v & kMuWait) == 0) {  // no one to wake
2145*9356374aSAndroid Build Coastguard Worker         intptr_t nv;
2146*9356374aSAndroid Build Coastguard Worker         bool do_enqueue = true;  // always Enqueue() the first time
2147*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(waitp != nullptr,
2148*9356374aSAndroid Build Coastguard Worker                        "UnlockSlow is confused");  // about to sleep
2149*9356374aSAndroid Build Coastguard Worker         do {  // must loop to release spinlock as reader count may change
2150*9356374aSAndroid Build Coastguard Worker           v = mu_.load(std::memory_order_relaxed);
2151*9356374aSAndroid Build Coastguard Worker           // decrement reader count if there are readers
2152*9356374aSAndroid Build Coastguard Worker           intptr_t new_readers = (v >= kMuOne) ? v - kMuOne : v;
2153*9356374aSAndroid Build Coastguard Worker           PerThreadSynch* new_h = nullptr;
2154*9356374aSAndroid Build Coastguard Worker           if (do_enqueue) {
2155*9356374aSAndroid Build Coastguard Worker             // If we are enqueuing on a CondVar (waitp->cv_word != nullptr) then
2156*9356374aSAndroid Build Coastguard Worker             // we must not retry here.  The initial attempt will always have
2157*9356374aSAndroid Build Coastguard Worker             // succeeded, further attempts would enqueue us against *this due to
2158*9356374aSAndroid Build Coastguard Worker             // Fer() handling.
2159*9356374aSAndroid Build Coastguard Worker             do_enqueue = (waitp->cv_word == nullptr);
2160*9356374aSAndroid Build Coastguard Worker             new_h = Enqueue(nullptr, waitp, new_readers, kMuIsCond);
2161*9356374aSAndroid Build Coastguard Worker           }
2162*9356374aSAndroid Build Coastguard Worker           intptr_t clear = kMuWrWait | kMuWriter;  // by default clear write bit
2163*9356374aSAndroid Build Coastguard Worker           if ((v & kMuWriter) == 0 && ExactlyOneReader(v)) {  // last reader
2164*9356374aSAndroid Build Coastguard Worker             clear = kMuWrWait | kMuReader;                    // clear read bit
2165*9356374aSAndroid Build Coastguard Worker           }
2166*9356374aSAndroid Build Coastguard Worker           nv = (v & kMuLow & ~clear & ~kMuSpin);
2167*9356374aSAndroid Build Coastguard Worker           if (new_h != nullptr) {
2168*9356374aSAndroid Build Coastguard Worker             nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);
2169*9356374aSAndroid Build Coastguard Worker           } else {  // new_h could be nullptr if we queued ourselves on a
2170*9356374aSAndroid Build Coastguard Worker                     // CondVar
2171*9356374aSAndroid Build Coastguard Worker             // In that case, we must place the reader count back in the mutex
2172*9356374aSAndroid Build Coastguard Worker             // word, as Enqueue() did not store it in the new waiter.
2173*9356374aSAndroid Build Coastguard Worker             nv |= new_readers & kMuHigh;
2174*9356374aSAndroid Build Coastguard Worker           }
2175*9356374aSAndroid Build Coastguard Worker           // release spinlock & our lock; retry if reader-count changed
2176*9356374aSAndroid Build Coastguard Worker           // (writer count cannot change since we hold lock)
2177*9356374aSAndroid Build Coastguard Worker         } while (!mu_.compare_exchange_weak(v, nv, std::memory_order_release,
2178*9356374aSAndroid Build Coastguard Worker                                             std::memory_order_relaxed));
2179*9356374aSAndroid Build Coastguard Worker         break;
2180*9356374aSAndroid Build Coastguard Worker       }
2181*9356374aSAndroid Build Coastguard Worker 
2182*9356374aSAndroid Build Coastguard Worker       // There are waiters.
2183*9356374aSAndroid Build Coastguard Worker       // Set h to the head of the circular waiter list.
2184*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* h = GetPerThreadSynch(v);
2185*9356374aSAndroid Build Coastguard Worker       if ((v & kMuReader) != 0 && (h->readers & kMuHigh) > kMuOne) {
2186*9356374aSAndroid Build Coastguard Worker         // a reader but not the last
2187*9356374aSAndroid Build Coastguard Worker         h->readers -= kMuOne;    // release our lock
2188*9356374aSAndroid Build Coastguard Worker         intptr_t nv = v;         // normally just release spinlock
2189*9356374aSAndroid Build Coastguard Worker         if (waitp != nullptr) {  // but waitp!=nullptr => must queue ourselves
2190*9356374aSAndroid Build Coastguard Worker           PerThreadSynch* new_h = Enqueue(h, waitp, v, kMuIsCond);
2191*9356374aSAndroid Build Coastguard Worker           ABSL_RAW_CHECK(new_h != nullptr,
2192*9356374aSAndroid Build Coastguard Worker                          "waiters disappeared during Enqueue()!");
2193*9356374aSAndroid Build Coastguard Worker           nv &= kMuLow;
2194*9356374aSAndroid Build Coastguard Worker           nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);
2195*9356374aSAndroid Build Coastguard Worker         }
2196*9356374aSAndroid Build Coastguard Worker         mu_.store(nv, std::memory_order_release);  // release spinlock
2197*9356374aSAndroid Build Coastguard Worker         // can release with a store because there were waiters
2198*9356374aSAndroid Build Coastguard Worker         break;
2199*9356374aSAndroid Build Coastguard Worker       }
2200*9356374aSAndroid Build Coastguard Worker 
2201*9356374aSAndroid Build Coastguard Worker       // Either we didn't search before, or we marked the queue
2202*9356374aSAndroid Build Coastguard Worker       // as "maybe_unlocking" and no one else should have changed it.
2203*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_CHECK(old_h == nullptr || h->maybe_unlocking,
2204*9356374aSAndroid Build Coastguard Worker                      "Mutex queue changed beneath us");
2205*9356374aSAndroid Build Coastguard Worker 
2206*9356374aSAndroid Build Coastguard Worker       // The lock is becoming free, and there's a waiter
2207*9356374aSAndroid Build Coastguard Worker       if (old_h != nullptr &&
2208*9356374aSAndroid Build Coastguard Worker           !old_h->may_skip) {    // we used old_h as a terminator
2209*9356374aSAndroid Build Coastguard Worker         old_h->may_skip = true;  // allow old_h to skip once more
2210*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(old_h->skip == nullptr, "illegal skip from head");
2211*9356374aSAndroid Build Coastguard Worker         if (h != old_h && MuEquivalentWaiter(old_h, old_h->next)) {
2212*9356374aSAndroid Build Coastguard Worker           old_h->skip = old_h->next;  // old_h not head & can skip to successor
2213*9356374aSAndroid Build Coastguard Worker         }
2214*9356374aSAndroid Build Coastguard Worker       }
2215*9356374aSAndroid Build Coastguard Worker       if (h->next->waitp->how == kExclusive &&
2216*9356374aSAndroid Build Coastguard Worker           h->next->waitp->cond == nullptr) {
2217*9356374aSAndroid Build Coastguard Worker         // easy case: writer with no condition; no need to search
2218*9356374aSAndroid Build Coastguard Worker         pw = h;  // wake w, the successor of h (=pw)
2219*9356374aSAndroid Build Coastguard Worker         w = h->next;
2220*9356374aSAndroid Build Coastguard Worker         w->wake = true;
2221*9356374aSAndroid Build Coastguard Worker         // We are waking up a writer.  This writer may be racing against
2222*9356374aSAndroid Build Coastguard Worker         // an already awake reader for the lock.  We want the
2223*9356374aSAndroid Build Coastguard Worker         // writer to usually win this race,
2224*9356374aSAndroid Build Coastguard Worker         // because if it doesn't, we can potentially keep taking a reader
2225*9356374aSAndroid Build Coastguard Worker         // perpetually and writers will starve.  Worse than
2226*9356374aSAndroid Build Coastguard Worker         // that, this can also starve other readers if kMuWrWait gets set
2227*9356374aSAndroid Build Coastguard Worker         // later.
2228*9356374aSAndroid Build Coastguard Worker         wr_wait = kMuWrWait;
2229*9356374aSAndroid Build Coastguard Worker       } else if (w != nullptr && (w->waitp->how == kExclusive || h == old_h)) {
2230*9356374aSAndroid Build Coastguard Worker         // we found a waiter w to wake on a previous iteration and either it's
2231*9356374aSAndroid Build Coastguard Worker         // a writer, or we've searched the entire list so we have all the
2232*9356374aSAndroid Build Coastguard Worker         // readers.
2233*9356374aSAndroid Build Coastguard Worker         if (pw == nullptr) {  // if w's predecessor is unknown, it must be h
2234*9356374aSAndroid Build Coastguard Worker           pw = h;
2235*9356374aSAndroid Build Coastguard Worker         }
2236*9356374aSAndroid Build Coastguard Worker       } else {
2237*9356374aSAndroid Build Coastguard Worker         // At this point we don't know all the waiters to wake, and the first
2238*9356374aSAndroid Build Coastguard Worker         // waiter has a condition or is a reader.  We avoid searching over
2239*9356374aSAndroid Build Coastguard Worker         // waiters we've searched on previous iterations by starting at
2240*9356374aSAndroid Build Coastguard Worker         // old_h if it's set.  If old_h==h, there's no one to wakeup at all.
2241*9356374aSAndroid Build Coastguard Worker         if (old_h == h) {  // we've searched before, and nothing's new
2242*9356374aSAndroid Build Coastguard Worker                            // so there's no one to wake.
2243*9356374aSAndroid Build Coastguard Worker           intptr_t nv = (v & ~(kMuReader | kMuWriter | kMuWrWait));
2244*9356374aSAndroid Build Coastguard Worker           h->readers = 0;
2245*9356374aSAndroid Build Coastguard Worker           h->maybe_unlocking = false;  // finished unlocking
2246*9356374aSAndroid Build Coastguard Worker           if (waitp != nullptr) {      // we must queue ourselves and sleep
2247*9356374aSAndroid Build Coastguard Worker             PerThreadSynch* new_h = Enqueue(h, waitp, v, kMuIsCond);
2248*9356374aSAndroid Build Coastguard Worker             nv &= kMuLow;
2249*9356374aSAndroid Build Coastguard Worker             if (new_h != nullptr) {
2250*9356374aSAndroid Build Coastguard Worker               nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);
2251*9356374aSAndroid Build Coastguard Worker             }  // else new_h could be nullptr if we queued ourselves on a
2252*9356374aSAndroid Build Coastguard Worker                // CondVar
2253*9356374aSAndroid Build Coastguard Worker           }
2254*9356374aSAndroid Build Coastguard Worker           // release spinlock & lock
2255*9356374aSAndroid Build Coastguard Worker           // can release with a store because there were waiters
2256*9356374aSAndroid Build Coastguard Worker           mu_.store(nv, std::memory_order_release);
2257*9356374aSAndroid Build Coastguard Worker           break;
2258*9356374aSAndroid Build Coastguard Worker         }
2259*9356374aSAndroid Build Coastguard Worker 
2260*9356374aSAndroid Build Coastguard Worker         // set up to walk the list
2261*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* w_walk;   // current waiter during list walk
2262*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* pw_walk;  // previous waiter during list walk
2263*9356374aSAndroid Build Coastguard Worker         if (old_h != nullptr) {  // we've searched up to old_h before
2264*9356374aSAndroid Build Coastguard Worker           pw_walk = old_h;
2265*9356374aSAndroid Build Coastguard Worker           w_walk = old_h->next;
2266*9356374aSAndroid Build Coastguard Worker         } else {  // no prior search, start at beginning
2267*9356374aSAndroid Build Coastguard Worker           pw_walk =
2268*9356374aSAndroid Build Coastguard Worker               nullptr;  // h->next's predecessor may change; don't record it
2269*9356374aSAndroid Build Coastguard Worker           w_walk = h->next;
2270*9356374aSAndroid Build Coastguard Worker         }
2271*9356374aSAndroid Build Coastguard Worker 
2272*9356374aSAndroid Build Coastguard Worker         h->may_skip = false;  // ensure we never skip past h in future searches
2273*9356374aSAndroid Build Coastguard Worker                               // even if other waiters are queued after it.
2274*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(h->skip == nullptr, "illegal skip from head");
2275*9356374aSAndroid Build Coastguard Worker 
2276*9356374aSAndroid Build Coastguard Worker         h->maybe_unlocking = true;  // we're about to scan the waiter list
2277*9356374aSAndroid Build Coastguard Worker                                     // without the spinlock held.
2278*9356374aSAndroid Build Coastguard Worker                                     // Enqueue must be conservative about
2279*9356374aSAndroid Build Coastguard Worker                                     // priority queuing.
2280*9356374aSAndroid Build Coastguard Worker 
2281*9356374aSAndroid Build Coastguard Worker         // We must release the spinlock to evaluate the conditions.
2282*9356374aSAndroid Build Coastguard Worker         mu_.store(v, std::memory_order_release);  // release just spinlock
2283*9356374aSAndroid Build Coastguard Worker         // can release with a store because there were waiters
2284*9356374aSAndroid Build Coastguard Worker 
2285*9356374aSAndroid Build Coastguard Worker         // h is the last waiter queued, and w_walk the first unsearched waiter.
2286*9356374aSAndroid Build Coastguard Worker         // Without the spinlock, the locations mu_ and h->next may now change
2287*9356374aSAndroid Build Coastguard Worker         // underneath us, but since we hold the lock itself, the only legal
2288*9356374aSAndroid Build Coastguard Worker         // change is to add waiters between h and w_walk.  Therefore, it's safe
2289*9356374aSAndroid Build Coastguard Worker         // to walk the path from w_walk to h inclusive. (TryRemove() can remove
2290*9356374aSAndroid Build Coastguard Worker         // a waiter anywhere, but it acquires both the spinlock and the Mutex)
2291*9356374aSAndroid Build Coastguard Worker 
2292*9356374aSAndroid Build Coastguard Worker         old_h = h;  // remember we searched to here
2293*9356374aSAndroid Build Coastguard Worker 
2294*9356374aSAndroid Build Coastguard Worker         // Walk the path upto and including h looking for waiters we can wake.
2295*9356374aSAndroid Build Coastguard Worker         while (pw_walk != h) {
2296*9356374aSAndroid Build Coastguard Worker           w_walk->wake = false;
2297*9356374aSAndroid Build Coastguard Worker           if (w_walk->waitp->cond ==
2298*9356374aSAndroid Build Coastguard Worker                   nullptr ||  // no condition => vacuously true OR
2299*9356374aSAndroid Build Coastguard Worker                               // this thread's condition is true
2300*9356374aSAndroid Build Coastguard Worker               EvalConditionIgnored(this, w_walk->waitp->cond)) {
2301*9356374aSAndroid Build Coastguard Worker             if (w == nullptr) {
2302*9356374aSAndroid Build Coastguard Worker               w_walk->wake = true;  // can wake this waiter
2303*9356374aSAndroid Build Coastguard Worker               w = w_walk;
2304*9356374aSAndroid Build Coastguard Worker               pw = pw_walk;
2305*9356374aSAndroid Build Coastguard Worker               if (w_walk->waitp->how == kExclusive) {
2306*9356374aSAndroid Build Coastguard Worker                 wr_wait = kMuWrWait;
2307*9356374aSAndroid Build Coastguard Worker                 break;  // bail if waking this writer
2308*9356374aSAndroid Build Coastguard Worker               }
2309*9356374aSAndroid Build Coastguard Worker             } else if (w_walk->waitp->how == kShared) {  // wake if a reader
2310*9356374aSAndroid Build Coastguard Worker               w_walk->wake = true;
2311*9356374aSAndroid Build Coastguard Worker             } else {  // writer with true condition
2312*9356374aSAndroid Build Coastguard Worker               wr_wait = kMuWrWait;
2313*9356374aSAndroid Build Coastguard Worker             }
2314*9356374aSAndroid Build Coastguard Worker           }
2315*9356374aSAndroid Build Coastguard Worker           if (w_walk->wake) {  // we're waking reader w_walk
2316*9356374aSAndroid Build Coastguard Worker             pw_walk = w_walk;  // don't skip similar waiters
2317*9356374aSAndroid Build Coastguard Worker           } else {             // not waking; skip as much as possible
2318*9356374aSAndroid Build Coastguard Worker             pw_walk = Skip(w_walk);
2319*9356374aSAndroid Build Coastguard Worker           }
2320*9356374aSAndroid Build Coastguard Worker           // If pw_walk == h, then load of pw_walk->next can race with
2321*9356374aSAndroid Build Coastguard Worker           // concurrent write in Enqueue(). However, at the same time
2322*9356374aSAndroid Build Coastguard Worker           // we do not need to do the load, because we will bail out
2323*9356374aSAndroid Build Coastguard Worker           // from the loop anyway.
2324*9356374aSAndroid Build Coastguard Worker           if (pw_walk != h) {
2325*9356374aSAndroid Build Coastguard Worker             w_walk = pw_walk->next;
2326*9356374aSAndroid Build Coastguard Worker           }
2327*9356374aSAndroid Build Coastguard Worker         }
2328*9356374aSAndroid Build Coastguard Worker 
2329*9356374aSAndroid Build Coastguard Worker         continue;  // restart for(;;)-loop to wakeup w or to find more waiters
2330*9356374aSAndroid Build Coastguard Worker       }
2331*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_CHECK(pw->next == w, "pw not w's predecessor");
2332*9356374aSAndroid Build Coastguard Worker       // The first (and perhaps only) waiter we've chosen to wake is w, whose
2333*9356374aSAndroid Build Coastguard Worker       // predecessor is pw.  If w is a reader, we must wake all the other
2334*9356374aSAndroid Build Coastguard Worker       // waiters with wake==true as well.  We may also need to queue
2335*9356374aSAndroid Build Coastguard Worker       // ourselves if waitp != null.  The spinlock and the lock are still
2336*9356374aSAndroid Build Coastguard Worker       // held.
2337*9356374aSAndroid Build Coastguard Worker 
2338*9356374aSAndroid Build Coastguard Worker       // This traverses the list in [ pw->next, h ], where h is the head,
2339*9356374aSAndroid Build Coastguard Worker       // removing all elements with wake==true and placing them in the
2340*9356374aSAndroid Build Coastguard Worker       // singly-linked list wake_list.  Returns the new head.
2341*9356374aSAndroid Build Coastguard Worker       h = DequeueAllWakeable(h, pw, &wake_list);
2342*9356374aSAndroid Build Coastguard Worker 
2343*9356374aSAndroid Build Coastguard Worker       intptr_t nv = (v & kMuEvent) | kMuDesig;
2344*9356374aSAndroid Build Coastguard Worker       // assume no waiters left,
2345*9356374aSAndroid Build Coastguard Worker       // set kMuDesig for INV1a
2346*9356374aSAndroid Build Coastguard Worker 
2347*9356374aSAndroid Build Coastguard Worker       if (waitp != nullptr) {  // we must queue ourselves and sleep
2348*9356374aSAndroid Build Coastguard Worker         h = Enqueue(h, waitp, v, kMuIsCond);
2349*9356374aSAndroid Build Coastguard Worker         // h is new last waiter; could be null if we queued ourselves on a
2350*9356374aSAndroid Build Coastguard Worker         // CondVar
2351*9356374aSAndroid Build Coastguard Worker       }
2352*9356374aSAndroid Build Coastguard Worker 
2353*9356374aSAndroid Build Coastguard Worker       ABSL_RAW_CHECK(wake_list != kPerThreadSynchNull,
2354*9356374aSAndroid Build Coastguard Worker                      "unexpected empty wake list");
2355*9356374aSAndroid Build Coastguard Worker 
2356*9356374aSAndroid Build Coastguard Worker       if (h != nullptr) {  // there are waiters left
2357*9356374aSAndroid Build Coastguard Worker         h->readers = 0;
2358*9356374aSAndroid Build Coastguard Worker         h->maybe_unlocking = false;  // finished unlocking
2359*9356374aSAndroid Build Coastguard Worker         nv |= wr_wait | kMuWait | reinterpret_cast<intptr_t>(h);
2360*9356374aSAndroid Build Coastguard Worker       }
2361*9356374aSAndroid Build Coastguard Worker 
2362*9356374aSAndroid Build Coastguard Worker       // release both spinlock & lock
2363*9356374aSAndroid Build Coastguard Worker       // can release with a store because there were waiters
2364*9356374aSAndroid Build Coastguard Worker       mu_.store(nv, std::memory_order_release);
2365*9356374aSAndroid Build Coastguard Worker       break;  // out of for(;;)-loop
2366*9356374aSAndroid Build Coastguard Worker     }
2367*9356374aSAndroid Build Coastguard Worker     // aggressive here; no one can proceed till we do
2368*9356374aSAndroid Build Coastguard Worker     c = synchronization_internal::MutexDelay(c, AGGRESSIVE);
2369*9356374aSAndroid Build Coastguard Worker   }  // end of for(;;)-loop
2370*9356374aSAndroid Build Coastguard Worker 
2371*9356374aSAndroid Build Coastguard Worker   if (wake_list != kPerThreadSynchNull) {
2372*9356374aSAndroid Build Coastguard Worker     int64_t total_wait_cycles = 0;
2373*9356374aSAndroid Build Coastguard Worker     int64_t max_wait_cycles = 0;
2374*9356374aSAndroid Build Coastguard Worker     int64_t now = CycleClock::Now();
2375*9356374aSAndroid Build Coastguard Worker     do {
2376*9356374aSAndroid Build Coastguard Worker       // Profile lock contention events only if the waiter was trying to acquire
2377*9356374aSAndroid Build Coastguard Worker       // the lock, not waiting on a condition variable or Condition.
2378*9356374aSAndroid Build Coastguard Worker       if (!wake_list->cond_waiter) {
2379*9356374aSAndroid Build Coastguard Worker         int64_t cycles_waited =
2380*9356374aSAndroid Build Coastguard Worker             (now - wake_list->waitp->contention_start_cycles);
2381*9356374aSAndroid Build Coastguard Worker         total_wait_cycles += cycles_waited;
2382*9356374aSAndroid Build Coastguard Worker         if (max_wait_cycles == 0) max_wait_cycles = cycles_waited;
2383*9356374aSAndroid Build Coastguard Worker         wake_list->waitp->contention_start_cycles = now;
2384*9356374aSAndroid Build Coastguard Worker         wake_list->waitp->should_submit_contention_data = true;
2385*9356374aSAndroid Build Coastguard Worker       }
2386*9356374aSAndroid Build Coastguard Worker       wake_list = Wakeup(wake_list);  // wake waiters
2387*9356374aSAndroid Build Coastguard Worker     } while (wake_list != kPerThreadSynchNull);
2388*9356374aSAndroid Build Coastguard Worker     if (total_wait_cycles > 0) {
2389*9356374aSAndroid Build Coastguard Worker       mutex_tracer("slow release", this, total_wait_cycles);
2390*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
2391*9356374aSAndroid Build Coastguard Worker       submit_profile_data(total_wait_cycles);
2392*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
2393*9356374aSAndroid Build Coastguard Worker     }
2394*9356374aSAndroid Build Coastguard Worker   }
2395*9356374aSAndroid Build Coastguard Worker }
2396*9356374aSAndroid Build Coastguard Worker 
2397*9356374aSAndroid Build Coastguard Worker // Used by CondVar implementation to reacquire mutex after waking from
2398*9356374aSAndroid Build Coastguard Worker // condition variable.  This routine is used instead of Lock() because the
2399*9356374aSAndroid Build Coastguard Worker // waiting thread may have been moved from the condition variable queue to the
2400*9356374aSAndroid Build Coastguard Worker // mutex queue without a wakeup, by Trans().  In that case, when the thread is
2401*9356374aSAndroid Build Coastguard Worker // finally woken, the woken thread will believe it has been woken from the
2402*9356374aSAndroid Build Coastguard Worker // condition variable (i.e. its PC will be in when in the CondVar code), when
2403*9356374aSAndroid Build Coastguard Worker // in fact it has just been woken from the mutex.  Thus, it must enter the slow
2404*9356374aSAndroid Build Coastguard Worker // path of the mutex in the same state as if it had just woken from the mutex.
2405*9356374aSAndroid Build Coastguard Worker // That is, it must ensure to clear kMuDesig (INV1b).
Trans(MuHow how)2406*9356374aSAndroid Build Coastguard Worker void Mutex::Trans(MuHow how) {
2407*9356374aSAndroid Build Coastguard Worker   this->LockSlow(how, nullptr, kMuHasBlocked | kMuIsCond);
2408*9356374aSAndroid Build Coastguard Worker }
2409*9356374aSAndroid Build Coastguard Worker 
2410*9356374aSAndroid Build Coastguard Worker // Used by CondVar implementation to effectively wake thread w from the
2411*9356374aSAndroid Build Coastguard Worker // condition variable.  If this mutex is free, we simply wake the thread.
2412*9356374aSAndroid Build Coastguard Worker // It will later acquire the mutex with high probability.  Otherwise, we
2413*9356374aSAndroid Build Coastguard Worker // enqueue thread w on this mutex.
Fer(PerThreadSynch * w)2414*9356374aSAndroid Build Coastguard Worker void Mutex::Fer(PerThreadSynch* w) {
2415*9356374aSAndroid Build Coastguard Worker   SchedulingGuard::ScopedDisable disable_rescheduling;
2416*9356374aSAndroid Build Coastguard Worker   int c = 0;
2417*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(w->waitp->cond == nullptr,
2418*9356374aSAndroid Build Coastguard Worker                  "Mutex::Fer while waiting on Condition");
2419*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(w->waitp->cv_word == nullptr,
2420*9356374aSAndroid Build Coastguard Worker                  "Mutex::Fer with pending CondVar queueing");
2421*9356374aSAndroid Build Coastguard Worker   // The CondVar timeout is not relevant for the Mutex wait.
2422*9356374aSAndroid Build Coastguard Worker   w->waitp->timeout = {};
2423*9356374aSAndroid Build Coastguard Worker   for (;;) {
2424*9356374aSAndroid Build Coastguard Worker     intptr_t v = mu_.load(std::memory_order_relaxed);
2425*9356374aSAndroid Build Coastguard Worker     // Note: must not queue if the mutex is unlocked (nobody will wake it).
2426*9356374aSAndroid Build Coastguard Worker     // For example, we can have only kMuWait (conditional) or maybe
2427*9356374aSAndroid Build Coastguard Worker     // kMuWait|kMuWrWait.
2428*9356374aSAndroid Build Coastguard Worker     // conflicting != 0 implies that the waking thread cannot currently take
2429*9356374aSAndroid Build Coastguard Worker     // the mutex, which in turn implies that someone else has it and can wake
2430*9356374aSAndroid Build Coastguard Worker     // us if we queue.
2431*9356374aSAndroid Build Coastguard Worker     const intptr_t conflicting =
2432*9356374aSAndroid Build Coastguard Worker         kMuWriter | (w->waitp->how == kShared ? 0 : kMuReader);
2433*9356374aSAndroid Build Coastguard Worker     if ((v & conflicting) == 0) {
2434*9356374aSAndroid Build Coastguard Worker       w->next = nullptr;
2435*9356374aSAndroid Build Coastguard Worker       w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
2436*9356374aSAndroid Build Coastguard Worker       IncrementSynchSem(this, w);
2437*9356374aSAndroid Build Coastguard Worker       return;
2438*9356374aSAndroid Build Coastguard Worker     } else {
2439*9356374aSAndroid Build Coastguard Worker       if ((v & (kMuSpin | kMuWait)) == 0) {  // no waiters
2440*9356374aSAndroid Build Coastguard Worker         // This thread tries to become the one and only waiter.
2441*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* new_h =
2442*9356374aSAndroid Build Coastguard Worker             Enqueue(nullptr, w->waitp, v, kMuIsCond | kMuIsFer);
2443*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(new_h != nullptr,
2444*9356374aSAndroid Build Coastguard Worker                        "Enqueue failed");  // we must queue ourselves
2445*9356374aSAndroid Build Coastguard Worker         if (mu_.compare_exchange_strong(
2446*9356374aSAndroid Build Coastguard Worker                 v, reinterpret_cast<intptr_t>(new_h) | (v & kMuLow) | kMuWait,
2447*9356374aSAndroid Build Coastguard Worker                 std::memory_order_release, std::memory_order_relaxed)) {
2448*9356374aSAndroid Build Coastguard Worker           return;
2449*9356374aSAndroid Build Coastguard Worker         }
2450*9356374aSAndroid Build Coastguard Worker       } else if ((v & kMuSpin) == 0 &&
2451*9356374aSAndroid Build Coastguard Worker                  mu_.compare_exchange_strong(v, v | kMuSpin | kMuWait)) {
2452*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* h = GetPerThreadSynch(v);
2453*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* new_h = Enqueue(h, w->waitp, v, kMuIsCond | kMuIsFer);
2454*9356374aSAndroid Build Coastguard Worker         ABSL_RAW_CHECK(new_h != nullptr,
2455*9356374aSAndroid Build Coastguard Worker                        "Enqueue failed");  // we must queue ourselves
2456*9356374aSAndroid Build Coastguard Worker         do {
2457*9356374aSAndroid Build Coastguard Worker           v = mu_.load(std::memory_order_relaxed);
2458*9356374aSAndroid Build Coastguard Worker         } while (!mu_.compare_exchange_weak(
2459*9356374aSAndroid Build Coastguard Worker             v,
2460*9356374aSAndroid Build Coastguard Worker             (v & kMuLow & ~kMuSpin) | kMuWait |
2461*9356374aSAndroid Build Coastguard Worker                 reinterpret_cast<intptr_t>(new_h),
2462*9356374aSAndroid Build Coastguard Worker             std::memory_order_release, std::memory_order_relaxed));
2463*9356374aSAndroid Build Coastguard Worker         return;
2464*9356374aSAndroid Build Coastguard Worker       }
2465*9356374aSAndroid Build Coastguard Worker     }
2466*9356374aSAndroid Build Coastguard Worker     c = synchronization_internal::MutexDelay(c, GENTLE);
2467*9356374aSAndroid Build Coastguard Worker   }
2468*9356374aSAndroid Build Coastguard Worker }
2469*9356374aSAndroid Build Coastguard Worker 
AssertHeld() const2470*9356374aSAndroid Build Coastguard Worker void Mutex::AssertHeld() const {
2471*9356374aSAndroid Build Coastguard Worker   if ((mu_.load(std::memory_order_relaxed) & kMuWriter) == 0) {
2472*9356374aSAndroid Build Coastguard Worker     SynchEvent* e = GetSynchEvent(this);
2473*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_LOG(FATAL, "thread should hold write lock on Mutex %p %s",
2474*9356374aSAndroid Build Coastguard Worker                  static_cast<const void*>(this), (e == nullptr ? "" : e->name));
2475*9356374aSAndroid Build Coastguard Worker   }
2476*9356374aSAndroid Build Coastguard Worker }
2477*9356374aSAndroid Build Coastguard Worker 
AssertReaderHeld() const2478*9356374aSAndroid Build Coastguard Worker void Mutex::AssertReaderHeld() const {
2479*9356374aSAndroid Build Coastguard Worker   if ((mu_.load(std::memory_order_relaxed) & (kMuReader | kMuWriter)) == 0) {
2480*9356374aSAndroid Build Coastguard Worker     SynchEvent* e = GetSynchEvent(this);
2481*9356374aSAndroid Build Coastguard Worker     ABSL_RAW_LOG(FATAL,
2482*9356374aSAndroid Build Coastguard Worker                  "thread should hold at least a read lock on Mutex %p %s",
2483*9356374aSAndroid Build Coastguard Worker                  static_cast<const void*>(this), (e == nullptr ? "" : e->name));
2484*9356374aSAndroid Build Coastguard Worker   }
2485*9356374aSAndroid Build Coastguard Worker }
2486*9356374aSAndroid Build Coastguard Worker 
2487*9356374aSAndroid Build Coastguard Worker // -------------------------------- condition variables
2488*9356374aSAndroid Build Coastguard Worker static const intptr_t kCvSpin = 0x0001L;   // spinlock protects waiter list
2489*9356374aSAndroid Build Coastguard Worker static const intptr_t kCvEvent = 0x0002L;  // record events
2490*9356374aSAndroid Build Coastguard Worker 
2491*9356374aSAndroid Build Coastguard Worker static const intptr_t kCvLow = 0x0003L;  // low order bits of CV
2492*9356374aSAndroid Build Coastguard Worker 
2493*9356374aSAndroid Build Coastguard Worker // Hack to make constant values available to gdb pretty printer
2494*9356374aSAndroid Build Coastguard Worker enum {
2495*9356374aSAndroid Build Coastguard Worker   kGdbCvSpin = kCvSpin,
2496*9356374aSAndroid Build Coastguard Worker   kGdbCvEvent = kCvEvent,
2497*9356374aSAndroid Build Coastguard Worker   kGdbCvLow = kCvLow,
2498*9356374aSAndroid Build Coastguard Worker };
2499*9356374aSAndroid Build Coastguard Worker 
2500*9356374aSAndroid Build Coastguard Worker static_assert(PerThreadSynch::kAlignment > kCvLow,
2501*9356374aSAndroid Build Coastguard Worker               "PerThreadSynch::kAlignment must be greater than kCvLow");
2502*9356374aSAndroid Build Coastguard Worker 
EnableDebugLog(const char * name)2503*9356374aSAndroid Build Coastguard Worker void CondVar::EnableDebugLog(const char* name) {
2504*9356374aSAndroid Build Coastguard Worker   SynchEvent* e = EnsureSynchEvent(&this->cv_, name, kCvEvent, kCvSpin);
2505*9356374aSAndroid Build Coastguard Worker   e->log = true;
2506*9356374aSAndroid Build Coastguard Worker   UnrefSynchEvent(e);
2507*9356374aSAndroid Build Coastguard Worker }
2508*9356374aSAndroid Build Coastguard Worker 
2509*9356374aSAndroid Build Coastguard Worker // Remove thread s from the list of waiters on this condition variable.
Remove(PerThreadSynch * s)2510*9356374aSAndroid Build Coastguard Worker void CondVar::Remove(PerThreadSynch* s) {
2511*9356374aSAndroid Build Coastguard Worker   SchedulingGuard::ScopedDisable disable_rescheduling;
2512*9356374aSAndroid Build Coastguard Worker   intptr_t v;
2513*9356374aSAndroid Build Coastguard Worker   int c = 0;
2514*9356374aSAndroid Build Coastguard Worker   for (v = cv_.load(std::memory_order_relaxed);;
2515*9356374aSAndroid Build Coastguard Worker        v = cv_.load(std::memory_order_relaxed)) {
2516*9356374aSAndroid Build Coastguard Worker     if ((v & kCvSpin) == 0 &&  // attempt to acquire spinlock
2517*9356374aSAndroid Build Coastguard Worker         cv_.compare_exchange_strong(v, v | kCvSpin, std::memory_order_acquire,
2518*9356374aSAndroid Build Coastguard Worker                                     std::memory_order_relaxed)) {
2519*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);
2520*9356374aSAndroid Build Coastguard Worker       if (h != nullptr) {
2521*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* w = h;
2522*9356374aSAndroid Build Coastguard Worker         while (w->next != s && w->next != h) {  // search for thread
2523*9356374aSAndroid Build Coastguard Worker           w = w->next;
2524*9356374aSAndroid Build Coastguard Worker         }
2525*9356374aSAndroid Build Coastguard Worker         if (w->next == s) {  // found thread; remove it
2526*9356374aSAndroid Build Coastguard Worker           w->next = s->next;
2527*9356374aSAndroid Build Coastguard Worker           if (h == s) {
2528*9356374aSAndroid Build Coastguard Worker             h = (w == s) ? nullptr : w;
2529*9356374aSAndroid Build Coastguard Worker           }
2530*9356374aSAndroid Build Coastguard Worker           s->next = nullptr;
2531*9356374aSAndroid Build Coastguard Worker           s->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
2532*9356374aSAndroid Build Coastguard Worker         }
2533*9356374aSAndroid Build Coastguard Worker       }
2534*9356374aSAndroid Build Coastguard Worker       // release spinlock
2535*9356374aSAndroid Build Coastguard Worker       cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h),
2536*9356374aSAndroid Build Coastguard Worker                 std::memory_order_release);
2537*9356374aSAndroid Build Coastguard Worker       return;
2538*9356374aSAndroid Build Coastguard Worker     } else {
2539*9356374aSAndroid Build Coastguard Worker       // try again after a delay
2540*9356374aSAndroid Build Coastguard Worker       c = synchronization_internal::MutexDelay(c, GENTLE);
2541*9356374aSAndroid Build Coastguard Worker     }
2542*9356374aSAndroid Build Coastguard Worker   }
2543*9356374aSAndroid Build Coastguard Worker }
2544*9356374aSAndroid Build Coastguard Worker 
2545*9356374aSAndroid Build Coastguard Worker // Queue thread waitp->thread on condition variable word cv_word using
2546*9356374aSAndroid Build Coastguard Worker // wait parameters waitp.
2547*9356374aSAndroid Build Coastguard Worker // We split this into a separate routine, rather than simply doing it as part
2548*9356374aSAndroid Build Coastguard Worker // of WaitCommon().  If we were to queue ourselves on the condition variable
2549*9356374aSAndroid Build Coastguard Worker // before calling Mutex::UnlockSlow(), the Mutex code might be re-entered (via
2550*9356374aSAndroid Build Coastguard Worker // the logging code, or via a Condition function) and might potentially attempt
2551*9356374aSAndroid Build Coastguard Worker // to block this thread.  That would be a problem if the thread were already on
2552*9356374aSAndroid Build Coastguard Worker // a condition variable waiter queue.  Thus, we use the waitp->cv_word to tell
2553*9356374aSAndroid Build Coastguard Worker // the unlock code to call CondVarEnqueue() to queue the thread on the condition
2554*9356374aSAndroid Build Coastguard Worker // variable queue just before the mutex is to be unlocked, and (most
2555*9356374aSAndroid Build Coastguard Worker // importantly) after any call to an external routine that might re-enter the
2556*9356374aSAndroid Build Coastguard Worker // mutex code.
CondVarEnqueue(SynchWaitParams * waitp)2557*9356374aSAndroid Build Coastguard Worker static void CondVarEnqueue(SynchWaitParams* waitp) {
2558*9356374aSAndroid Build Coastguard Worker   // This thread might be transferred to the Mutex queue by Fer() when
2559*9356374aSAndroid Build Coastguard Worker   // we are woken.  To make sure that is what happens, Enqueue() doesn't
2560*9356374aSAndroid Build Coastguard Worker   // call CondVarEnqueue() again but instead uses its normal code.  We
2561*9356374aSAndroid Build Coastguard Worker   // must do this before we queue ourselves so that cv_word will be null
2562*9356374aSAndroid Build Coastguard Worker   // when seen by the dequeuer, who may wish immediately to requeue
2563*9356374aSAndroid Build Coastguard Worker   // this thread on another queue.
2564*9356374aSAndroid Build Coastguard Worker   std::atomic<intptr_t>* cv_word = waitp->cv_word;
2565*9356374aSAndroid Build Coastguard Worker   waitp->cv_word = nullptr;
2566*9356374aSAndroid Build Coastguard Worker 
2567*9356374aSAndroid Build Coastguard Worker   intptr_t v = cv_word->load(std::memory_order_relaxed);
2568*9356374aSAndroid Build Coastguard Worker   int c = 0;
2569*9356374aSAndroid Build Coastguard Worker   while ((v & kCvSpin) != 0 ||  // acquire spinlock
2570*9356374aSAndroid Build Coastguard Worker          !cv_word->compare_exchange_weak(v, v | kCvSpin,
2571*9356374aSAndroid Build Coastguard Worker                                          std::memory_order_acquire,
2572*9356374aSAndroid Build Coastguard Worker                                          std::memory_order_relaxed)) {
2573*9356374aSAndroid Build Coastguard Worker     c = synchronization_internal::MutexDelay(c, GENTLE);
2574*9356374aSAndroid Build Coastguard Worker     v = cv_word->load(std::memory_order_relaxed);
2575*9356374aSAndroid Build Coastguard Worker   }
2576*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be");
2577*9356374aSAndroid Build Coastguard Worker   waitp->thread->waitp = waitp;  // prepare ourselves for waiting
2578*9356374aSAndroid Build Coastguard Worker   PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);
2579*9356374aSAndroid Build Coastguard Worker   if (h == nullptr) {  // add this thread to waiter list
2580*9356374aSAndroid Build Coastguard Worker     waitp->thread->next = waitp->thread;
2581*9356374aSAndroid Build Coastguard Worker   } else {
2582*9356374aSAndroid Build Coastguard Worker     waitp->thread->next = h->next;
2583*9356374aSAndroid Build Coastguard Worker     h->next = waitp->thread;
2584*9356374aSAndroid Build Coastguard Worker   }
2585*9356374aSAndroid Build Coastguard Worker   waitp->thread->state.store(PerThreadSynch::kQueued,
2586*9356374aSAndroid Build Coastguard Worker                              std::memory_order_relaxed);
2587*9356374aSAndroid Build Coastguard Worker   cv_word->store((v & kCvEvent) | reinterpret_cast<intptr_t>(waitp->thread),
2588*9356374aSAndroid Build Coastguard Worker                  std::memory_order_release);
2589*9356374aSAndroid Build Coastguard Worker }
2590*9356374aSAndroid Build Coastguard Worker 
WaitCommon(Mutex * mutex,KernelTimeout t)2591*9356374aSAndroid Build Coastguard Worker bool CondVar::WaitCommon(Mutex* mutex, KernelTimeout t) {
2592*9356374aSAndroid Build Coastguard Worker   bool rc = false;  // return value; true iff we timed-out
2593*9356374aSAndroid Build Coastguard Worker 
2594*9356374aSAndroid Build Coastguard Worker   intptr_t mutex_v = mutex->mu_.load(std::memory_order_relaxed);
2595*9356374aSAndroid Build Coastguard Worker   Mutex::MuHow mutex_how = ((mutex_v & kMuWriter) != 0) ? kExclusive : kShared;
2596*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_UNLOCK(mutex, TsanFlags(mutex_how));
2597*9356374aSAndroid Build Coastguard Worker 
2598*9356374aSAndroid Build Coastguard Worker   // maybe trace this call
2599*9356374aSAndroid Build Coastguard Worker   intptr_t v = cv_.load(std::memory_order_relaxed);
2600*9356374aSAndroid Build Coastguard Worker   cond_var_tracer("Wait", this);
2601*9356374aSAndroid Build Coastguard Worker   if ((v & kCvEvent) != 0) {
2602*9356374aSAndroid Build Coastguard Worker     PostSynchEvent(this, SYNCH_EV_WAIT);
2603*9356374aSAndroid Build Coastguard Worker   }
2604*9356374aSAndroid Build Coastguard Worker 
2605*9356374aSAndroid Build Coastguard Worker   // Release mu and wait on condition variable.
2606*9356374aSAndroid Build Coastguard Worker   SynchWaitParams waitp(mutex_how, nullptr, t, mutex,
2607*9356374aSAndroid Build Coastguard Worker                         Synch_GetPerThreadAnnotated(mutex), &cv_);
2608*9356374aSAndroid Build Coastguard Worker   // UnlockSlow() will call CondVarEnqueue() just before releasing the
2609*9356374aSAndroid Build Coastguard Worker   // Mutex, thus queuing this thread on the condition variable.  See
2610*9356374aSAndroid Build Coastguard Worker   // CondVarEnqueue() for the reasons.
2611*9356374aSAndroid Build Coastguard Worker   mutex->UnlockSlow(&waitp);
2612*9356374aSAndroid Build Coastguard Worker 
2613*9356374aSAndroid Build Coastguard Worker   // wait for signal
2614*9356374aSAndroid Build Coastguard Worker   while (waitp.thread->state.load(std::memory_order_acquire) ==
2615*9356374aSAndroid Build Coastguard Worker          PerThreadSynch::kQueued) {
2616*9356374aSAndroid Build Coastguard Worker     if (!Mutex::DecrementSynchSem(mutex, waitp.thread, t)) {
2617*9356374aSAndroid Build Coastguard Worker       // DecrementSynchSem returned due to timeout.
2618*9356374aSAndroid Build Coastguard Worker       // Now we will either (1) remove ourselves from the wait list in Remove
2619*9356374aSAndroid Build Coastguard Worker       // below, in which case Remove will set thread.state = kAvailable and
2620*9356374aSAndroid Build Coastguard Worker       // we will not call DecrementSynchSem again; or (2) Signal/SignalAll
2621*9356374aSAndroid Build Coastguard Worker       // has removed us concurrently and is calling Wakeup, which will set
2622*9356374aSAndroid Build Coastguard Worker       // thread.state = kAvailable and post to the semaphore.
2623*9356374aSAndroid Build Coastguard Worker       // It's important to reset the timeout for the case (2) because otherwise
2624*9356374aSAndroid Build Coastguard Worker       // we can live-lock in this loop since DecrementSynchSem will always
2625*9356374aSAndroid Build Coastguard Worker       // return immediately due to timeout, but Signal/SignalAll is not
2626*9356374aSAndroid Build Coastguard Worker       // necessary set thread.state = kAvailable yet (and is not scheduled
2627*9356374aSAndroid Build Coastguard Worker       // due to thread priorities or other scheduler artifacts).
2628*9356374aSAndroid Build Coastguard Worker       // Note this could also be resolved if Signal/SignalAll would set
2629*9356374aSAndroid Build Coastguard Worker       // thread.state = kAvailable while holding the wait list spin lock.
2630*9356374aSAndroid Build Coastguard Worker       // But this can't be easily done for SignalAll since it grabs the whole
2631*9356374aSAndroid Build Coastguard Worker       // wait list with a single compare-exchange and does not really grab
2632*9356374aSAndroid Build Coastguard Worker       // the spin lock.
2633*9356374aSAndroid Build Coastguard Worker       t = KernelTimeout::Never();
2634*9356374aSAndroid Build Coastguard Worker       this->Remove(waitp.thread);
2635*9356374aSAndroid Build Coastguard Worker       rc = true;
2636*9356374aSAndroid Build Coastguard Worker     }
2637*9356374aSAndroid Build Coastguard Worker   }
2638*9356374aSAndroid Build Coastguard Worker 
2639*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(waitp.thread->waitp != nullptr, "not waiting when should be");
2640*9356374aSAndroid Build Coastguard Worker   waitp.thread->waitp = nullptr;  // cleanup
2641*9356374aSAndroid Build Coastguard Worker 
2642*9356374aSAndroid Build Coastguard Worker   // maybe trace this call
2643*9356374aSAndroid Build Coastguard Worker   cond_var_tracer("Unwait", this);
2644*9356374aSAndroid Build Coastguard Worker   if ((v & kCvEvent) != 0) {
2645*9356374aSAndroid Build Coastguard Worker     PostSynchEvent(this, SYNCH_EV_WAIT_RETURNING);
2646*9356374aSAndroid Build Coastguard Worker   }
2647*9356374aSAndroid Build Coastguard Worker 
2648*9356374aSAndroid Build Coastguard Worker   // From synchronization point of view Wait is unlock of the mutex followed
2649*9356374aSAndroid Build Coastguard Worker   // by lock of the mutex. We've annotated start of unlock in the beginning
2650*9356374aSAndroid Build Coastguard Worker   // of the function. Now, finish unlock and annotate lock of the mutex.
2651*9356374aSAndroid Build Coastguard Worker   // (Trans is effectively lock).
2652*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_UNLOCK(mutex, TsanFlags(mutex_how));
2653*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_LOCK(mutex, TsanFlags(mutex_how));
2654*9356374aSAndroid Build Coastguard Worker   mutex->Trans(mutex_how);  // Reacquire mutex
2655*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_LOCK(mutex, TsanFlags(mutex_how), 0);
2656*9356374aSAndroid Build Coastguard Worker   return rc;
2657*9356374aSAndroid Build Coastguard Worker }
2658*9356374aSAndroid Build Coastguard Worker 
Signal()2659*9356374aSAndroid Build Coastguard Worker void CondVar::Signal() {
2660*9356374aSAndroid Build Coastguard Worker   SchedulingGuard::ScopedDisable disable_rescheduling;
2661*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
2662*9356374aSAndroid Build Coastguard Worker   intptr_t v;
2663*9356374aSAndroid Build Coastguard Worker   int c = 0;
2664*9356374aSAndroid Build Coastguard Worker   for (v = cv_.load(std::memory_order_relaxed); v != 0;
2665*9356374aSAndroid Build Coastguard Worker        v = cv_.load(std::memory_order_relaxed)) {
2666*9356374aSAndroid Build Coastguard Worker     if ((v & kCvSpin) == 0 &&  // attempt to acquire spinlock
2667*9356374aSAndroid Build Coastguard Worker         cv_.compare_exchange_strong(v, v | kCvSpin, std::memory_order_acquire,
2668*9356374aSAndroid Build Coastguard Worker                                     std::memory_order_relaxed)) {
2669*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);
2670*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* w = nullptr;
2671*9356374aSAndroid Build Coastguard Worker       if (h != nullptr) {  // remove first waiter
2672*9356374aSAndroid Build Coastguard Worker         w = h->next;
2673*9356374aSAndroid Build Coastguard Worker         if (w == h) {
2674*9356374aSAndroid Build Coastguard Worker           h = nullptr;
2675*9356374aSAndroid Build Coastguard Worker         } else {
2676*9356374aSAndroid Build Coastguard Worker           h->next = w->next;
2677*9356374aSAndroid Build Coastguard Worker         }
2678*9356374aSAndroid Build Coastguard Worker       }
2679*9356374aSAndroid Build Coastguard Worker       // release spinlock
2680*9356374aSAndroid Build Coastguard Worker       cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h),
2681*9356374aSAndroid Build Coastguard Worker                 std::memory_order_release);
2682*9356374aSAndroid Build Coastguard Worker       if (w != nullptr) {
2683*9356374aSAndroid Build Coastguard Worker         w->waitp->cvmu->Fer(w);  // wake waiter, if there was one
2684*9356374aSAndroid Build Coastguard Worker         cond_var_tracer("Signal wakeup", this);
2685*9356374aSAndroid Build Coastguard Worker       }
2686*9356374aSAndroid Build Coastguard Worker       if ((v & kCvEvent) != 0) {
2687*9356374aSAndroid Build Coastguard Worker         PostSynchEvent(this, SYNCH_EV_SIGNAL);
2688*9356374aSAndroid Build Coastguard Worker       }
2689*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2690*9356374aSAndroid Build Coastguard Worker       return;
2691*9356374aSAndroid Build Coastguard Worker     } else {
2692*9356374aSAndroid Build Coastguard Worker       c = synchronization_internal::MutexDelay(c, GENTLE);
2693*9356374aSAndroid Build Coastguard Worker     }
2694*9356374aSAndroid Build Coastguard Worker   }
2695*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2696*9356374aSAndroid Build Coastguard Worker }
2697*9356374aSAndroid Build Coastguard Worker 
SignalAll()2698*9356374aSAndroid Build Coastguard Worker void CondVar::SignalAll() {
2699*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
2700*9356374aSAndroid Build Coastguard Worker   intptr_t v;
2701*9356374aSAndroid Build Coastguard Worker   int c = 0;
2702*9356374aSAndroid Build Coastguard Worker   for (v = cv_.load(std::memory_order_relaxed); v != 0;
2703*9356374aSAndroid Build Coastguard Worker        v = cv_.load(std::memory_order_relaxed)) {
2704*9356374aSAndroid Build Coastguard Worker     // empty the list if spinlock free
2705*9356374aSAndroid Build Coastguard Worker     // We do this by simply setting the list to empty using
2706*9356374aSAndroid Build Coastguard Worker     // compare and swap.   We then have the entire list in our hands,
2707*9356374aSAndroid Build Coastguard Worker     // which cannot be changing since we grabbed it while no one
2708*9356374aSAndroid Build Coastguard Worker     // held the lock.
2709*9356374aSAndroid Build Coastguard Worker     if ((v & kCvSpin) == 0 &&
2710*9356374aSAndroid Build Coastguard Worker         cv_.compare_exchange_strong(v, v & kCvEvent, std::memory_order_acquire,
2711*9356374aSAndroid Build Coastguard Worker                                     std::memory_order_relaxed)) {
2712*9356374aSAndroid Build Coastguard Worker       PerThreadSynch* h = reinterpret_cast<PerThreadSynch*>(v & ~kCvLow);
2713*9356374aSAndroid Build Coastguard Worker       if (h != nullptr) {
2714*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* w;
2715*9356374aSAndroid Build Coastguard Worker         PerThreadSynch* n = h->next;
2716*9356374aSAndroid Build Coastguard Worker         do {  // for every thread, wake it up
2717*9356374aSAndroid Build Coastguard Worker           w = n;
2718*9356374aSAndroid Build Coastguard Worker           n = n->next;
2719*9356374aSAndroid Build Coastguard Worker           w->waitp->cvmu->Fer(w);
2720*9356374aSAndroid Build Coastguard Worker         } while (w != h);
2721*9356374aSAndroid Build Coastguard Worker         cond_var_tracer("SignalAll wakeup", this);
2722*9356374aSAndroid Build Coastguard Worker       }
2723*9356374aSAndroid Build Coastguard Worker       if ((v & kCvEvent) != 0) {
2724*9356374aSAndroid Build Coastguard Worker         PostSynchEvent(this, SYNCH_EV_SIGNALALL);
2725*9356374aSAndroid Build Coastguard Worker       }
2726*9356374aSAndroid Build Coastguard Worker       ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2727*9356374aSAndroid Build Coastguard Worker       return;
2728*9356374aSAndroid Build Coastguard Worker     } else {
2729*9356374aSAndroid Build Coastguard Worker       // try again after a delay
2730*9356374aSAndroid Build Coastguard Worker       c = synchronization_internal::MutexDelay(c, GENTLE);
2731*9356374aSAndroid Build Coastguard Worker     }
2732*9356374aSAndroid Build Coastguard Worker   }
2733*9356374aSAndroid Build Coastguard Worker   ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2734*9356374aSAndroid Build Coastguard Worker }
2735*9356374aSAndroid Build Coastguard Worker 
Release()2736*9356374aSAndroid Build Coastguard Worker void ReleasableMutexLock::Release() {
2737*9356374aSAndroid Build Coastguard Worker   ABSL_RAW_CHECK(this->mu_ != nullptr,
2738*9356374aSAndroid Build Coastguard Worker                  "ReleasableMutexLock::Release may only be called once");
2739*9356374aSAndroid Build Coastguard Worker   this->mu_->Unlock();
2740*9356374aSAndroid Build Coastguard Worker   this->mu_ = nullptr;
2741*9356374aSAndroid Build Coastguard Worker }
2742*9356374aSAndroid Build Coastguard Worker 
2743*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_THREAD_SANITIZER
2744*9356374aSAndroid Build Coastguard Worker extern "C" void __tsan_read1(void* addr);
2745*9356374aSAndroid Build Coastguard Worker #else
2746*9356374aSAndroid Build Coastguard Worker #define __tsan_read1(addr)  // do nothing if TSan not enabled
2747*9356374aSAndroid Build Coastguard Worker #endif
2748*9356374aSAndroid Build Coastguard Worker 
2749*9356374aSAndroid Build Coastguard Worker // A function that just returns its argument, dereferenced
Dereference(void * arg)2750*9356374aSAndroid Build Coastguard Worker static bool Dereference(void* arg) {
2751*9356374aSAndroid Build Coastguard Worker   // ThreadSanitizer does not instrument this file for memory accesses.
2752*9356374aSAndroid Build Coastguard Worker   // This function dereferences a user variable that can participate
2753*9356374aSAndroid Build Coastguard Worker   // in a data race, so we need to manually tell TSan about this memory access.
2754*9356374aSAndroid Build Coastguard Worker   __tsan_read1(arg);
2755*9356374aSAndroid Build Coastguard Worker   return *(static_cast<bool*>(arg));
2756*9356374aSAndroid Build Coastguard Worker }
2757*9356374aSAndroid Build Coastguard Worker 
2758*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT const Condition Condition::kTrue;
2759*9356374aSAndroid Build Coastguard Worker 
Condition(bool (* func)(void *),void * arg)2760*9356374aSAndroid Build Coastguard Worker Condition::Condition(bool (*func)(void*), void* arg)
2761*9356374aSAndroid Build Coastguard Worker     : eval_(&CallVoidPtrFunction), arg_(arg) {
2762*9356374aSAndroid Build Coastguard Worker   static_assert(sizeof(&func) <= sizeof(callback_),
2763*9356374aSAndroid Build Coastguard Worker                 "An overlarge function pointer passed to Condition.");
2764*9356374aSAndroid Build Coastguard Worker   StoreCallback(func);
2765*9356374aSAndroid Build Coastguard Worker }
2766*9356374aSAndroid Build Coastguard Worker 
CallVoidPtrFunction(const Condition * c)2767*9356374aSAndroid Build Coastguard Worker bool Condition::CallVoidPtrFunction(const Condition* c) {
2768*9356374aSAndroid Build Coastguard Worker   using FunctionPointer = bool (*)(void*);
2769*9356374aSAndroid Build Coastguard Worker   FunctionPointer function_pointer;
2770*9356374aSAndroid Build Coastguard Worker   std::memcpy(&function_pointer, c->callback_, sizeof(function_pointer));
2771*9356374aSAndroid Build Coastguard Worker   return (*function_pointer)(c->arg_);
2772*9356374aSAndroid Build Coastguard Worker }
2773*9356374aSAndroid Build Coastguard Worker 
Condition(const bool * cond)2774*9356374aSAndroid Build Coastguard Worker Condition::Condition(const bool* cond)
2775*9356374aSAndroid Build Coastguard Worker     : eval_(CallVoidPtrFunction),
2776*9356374aSAndroid Build Coastguard Worker       // const_cast is safe since Dereference does not modify arg
2777*9356374aSAndroid Build Coastguard Worker       arg_(const_cast<bool*>(cond)) {
2778*9356374aSAndroid Build Coastguard Worker   using FunctionPointer = bool (*)(void*);
2779*9356374aSAndroid Build Coastguard Worker   const FunctionPointer dereference = Dereference;
2780*9356374aSAndroid Build Coastguard Worker   StoreCallback(dereference);
2781*9356374aSAndroid Build Coastguard Worker }
2782*9356374aSAndroid Build Coastguard Worker 
Eval() const2783*9356374aSAndroid Build Coastguard Worker bool Condition::Eval() const { return (*this->eval_)(this); }
2784*9356374aSAndroid Build Coastguard Worker 
GuaranteedEqual(const Condition * a,const Condition * b)2785*9356374aSAndroid Build Coastguard Worker bool Condition::GuaranteedEqual(const Condition* a, const Condition* b) {
2786*9356374aSAndroid Build Coastguard Worker   if (a == nullptr || b == nullptr) {
2787*9356374aSAndroid Build Coastguard Worker     return a == b;
2788*9356374aSAndroid Build Coastguard Worker   }
2789*9356374aSAndroid Build Coastguard Worker   // Check equality of the representative fields.
2790*9356374aSAndroid Build Coastguard Worker   return a->eval_ == b->eval_ && a->arg_ == b->arg_ &&
2791*9356374aSAndroid Build Coastguard Worker          !memcmp(a->callback_, b->callback_, sizeof(a->callback_));
2792*9356374aSAndroid Build Coastguard Worker }
2793*9356374aSAndroid Build Coastguard Worker 
2794*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
2795*9356374aSAndroid Build Coastguard Worker }  // namespace absl
2796