1*9356374aSAndroid Build Coastguard Worker //
2*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
3*9356374aSAndroid Build Coastguard Worker //
4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*9356374aSAndroid Build Coastguard Worker //
8*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
9*9356374aSAndroid Build Coastguard Worker //
10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*9356374aSAndroid Build Coastguard Worker // limitations under the License.
15*9356374aSAndroid Build Coastguard Worker //
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker // Most users requiring mutual exclusion should use Mutex.
18*9356374aSAndroid Build Coastguard Worker // SpinLock is provided for use in two situations:
19*9356374aSAndroid Build Coastguard Worker // - for use by Abseil internal code that Mutex itself depends on
20*9356374aSAndroid Build Coastguard Worker // - for async signal safety (see below)
21*9356374aSAndroid Build Coastguard Worker
22*9356374aSAndroid Build Coastguard Worker // SpinLock with a base_internal::SchedulingMode::SCHEDULE_KERNEL_ONLY is async
23*9356374aSAndroid Build Coastguard Worker // signal safe. If a spinlock is used within a signal handler, all code that
24*9356374aSAndroid Build Coastguard Worker // acquires the lock must ensure that the signal cannot arrive while they are
25*9356374aSAndroid Build Coastguard Worker // holding the lock. Typically, this is done by blocking the signal.
26*9356374aSAndroid Build Coastguard Worker //
27*9356374aSAndroid Build Coastguard Worker // Threads waiting on a SpinLock may be woken in an arbitrary order.
28*9356374aSAndroid Build Coastguard Worker
29*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
30*9356374aSAndroid Build Coastguard Worker #define ABSL_BASE_INTERNAL_SPINLOCK_H_
31*9356374aSAndroid Build Coastguard Worker
32*9356374aSAndroid Build Coastguard Worker #include <atomic>
33*9356374aSAndroid Build Coastguard Worker #include <cstdint>
34*9356374aSAndroid Build Coastguard Worker
35*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/base/const_init.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/base/dynamic_annotations.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/low_level_scheduling.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/raw_logging.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/scheduling_mode.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/tsan_mutex_interface.h"
42*9356374aSAndroid Build Coastguard Worker #include "absl/base/thread_annotations.h"
43*9356374aSAndroid Build Coastguard Worker
44*9356374aSAndroid Build Coastguard Worker namespace tcmalloc {
45*9356374aSAndroid Build Coastguard Worker namespace tcmalloc_internal {
46*9356374aSAndroid Build Coastguard Worker
47*9356374aSAndroid Build Coastguard Worker class AllocationGuardSpinLockHolder;
48*9356374aSAndroid Build Coastguard Worker
49*9356374aSAndroid Build Coastguard Worker } // namespace tcmalloc_internal
50*9356374aSAndroid Build Coastguard Worker } // namespace tcmalloc
51*9356374aSAndroid Build Coastguard Worker
52*9356374aSAndroid Build Coastguard Worker namespace absl {
53*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
54*9356374aSAndroid Build Coastguard Worker namespace base_internal {
55*9356374aSAndroid Build Coastguard Worker
56*9356374aSAndroid Build Coastguard Worker class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock {
57*9356374aSAndroid Build Coastguard Worker public:
SpinLock()58*9356374aSAndroid Build Coastguard Worker SpinLock() : lockword_(kSpinLockCooperative) {
59*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
60*9356374aSAndroid Build Coastguard Worker }
61*9356374aSAndroid Build Coastguard Worker
62*9356374aSAndroid Build Coastguard Worker // Constructors that allow non-cooperative spinlocks to be created for use
63*9356374aSAndroid Build Coastguard Worker // inside thread schedulers. Normal clients should not use these.
64*9356374aSAndroid Build Coastguard Worker explicit SpinLock(base_internal::SchedulingMode mode);
65*9356374aSAndroid Build Coastguard Worker
66*9356374aSAndroid Build Coastguard Worker // Constructor for global SpinLock instances. See absl/base/const_init.h.
SpinLock(absl::ConstInitType,base_internal::SchedulingMode mode)67*9356374aSAndroid Build Coastguard Worker constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
68*9356374aSAndroid Build Coastguard Worker : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
69*9356374aSAndroid Build Coastguard Worker
70*9356374aSAndroid Build Coastguard Worker // For global SpinLock instances prefer trivial destructor when possible.
71*9356374aSAndroid Build Coastguard Worker // Default but non-trivial destructor in some build configurations causes an
72*9356374aSAndroid Build Coastguard Worker // extra static initializer.
73*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
~SpinLock()74*9356374aSAndroid Build Coastguard Worker ~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
75*9356374aSAndroid Build Coastguard Worker #else
76*9356374aSAndroid Build Coastguard Worker ~SpinLock() = default;
77*9356374aSAndroid Build Coastguard Worker #endif
78*9356374aSAndroid Build Coastguard Worker
79*9356374aSAndroid Build Coastguard Worker // Acquire this SpinLock.
Lock()80*9356374aSAndroid Build Coastguard Worker inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
81*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
82*9356374aSAndroid Build Coastguard Worker if (!TryLockImpl()) {
83*9356374aSAndroid Build Coastguard Worker SlowLock();
84*9356374aSAndroid Build Coastguard Worker }
85*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
86*9356374aSAndroid Build Coastguard Worker }
87*9356374aSAndroid Build Coastguard Worker
88*9356374aSAndroid Build Coastguard Worker // Try to acquire this SpinLock without blocking and return true if the
89*9356374aSAndroid Build Coastguard Worker // acquisition was successful. If the lock was not acquired, false is
90*9356374aSAndroid Build Coastguard Worker // returned. If this SpinLock is free at the time of the call, TryLock
91*9356374aSAndroid Build Coastguard Worker // will return true with high probability.
TryLock()92*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline bool TryLock()
93*9356374aSAndroid Build Coastguard Worker ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
94*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
95*9356374aSAndroid Build Coastguard Worker bool res = TryLockImpl();
96*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_POST_LOCK(
97*9356374aSAndroid Build Coastguard Worker this, __tsan_mutex_try_lock | (res ? 0 : __tsan_mutex_try_lock_failed),
98*9356374aSAndroid Build Coastguard Worker 0);
99*9356374aSAndroid Build Coastguard Worker return res;
100*9356374aSAndroid Build Coastguard Worker }
101*9356374aSAndroid Build Coastguard Worker
102*9356374aSAndroid Build Coastguard Worker // Release this SpinLock, which must be held by the calling thread.
Unlock()103*9356374aSAndroid Build Coastguard Worker inline void Unlock() ABSL_UNLOCK_FUNCTION() {
104*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
105*9356374aSAndroid Build Coastguard Worker uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
106*9356374aSAndroid Build Coastguard Worker lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
107*9356374aSAndroid Build Coastguard Worker std::memory_order_release);
108*9356374aSAndroid Build Coastguard Worker
109*9356374aSAndroid Build Coastguard Worker if ((lock_value & kSpinLockDisabledScheduling) != 0) {
110*9356374aSAndroid Build Coastguard Worker base_internal::SchedulingGuard::EnableRescheduling(true);
111*9356374aSAndroid Build Coastguard Worker }
112*9356374aSAndroid Build Coastguard Worker if ((lock_value & kWaitTimeMask) != 0) {
113*9356374aSAndroid Build Coastguard Worker // Collect contentionz profile info, and speed the wakeup of any waiter.
114*9356374aSAndroid Build Coastguard Worker // The wait_cycles value indicates how long this thread spent waiting
115*9356374aSAndroid Build Coastguard Worker // for the lock.
116*9356374aSAndroid Build Coastguard Worker SlowUnlock(lock_value);
117*9356374aSAndroid Build Coastguard Worker }
118*9356374aSAndroid Build Coastguard Worker ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);
119*9356374aSAndroid Build Coastguard Worker }
120*9356374aSAndroid Build Coastguard Worker
121*9356374aSAndroid Build Coastguard Worker // Determine if the lock is held. When the lock is held by the invoking
122*9356374aSAndroid Build Coastguard Worker // thread, true will always be returned. Intended to be used as
123*9356374aSAndroid Build Coastguard Worker // CHECK(lock.IsHeld()).
IsHeld()124*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT inline bool IsHeld() const {
125*9356374aSAndroid Build Coastguard Worker return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
126*9356374aSAndroid Build Coastguard Worker }
127*9356374aSAndroid Build Coastguard Worker
128*9356374aSAndroid Build Coastguard Worker // Return immediately if this thread holds the SpinLock exclusively.
129*9356374aSAndroid Build Coastguard Worker // Otherwise, report an error by crashing with a diagnostic.
AssertHeld()130*9356374aSAndroid Build Coastguard Worker inline void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK() {
131*9356374aSAndroid Build Coastguard Worker if (!IsHeld()) {
132*9356374aSAndroid Build Coastguard Worker ABSL_RAW_LOG(FATAL, "thread should hold the lock on SpinLock");
133*9356374aSAndroid Build Coastguard Worker }
134*9356374aSAndroid Build Coastguard Worker }
135*9356374aSAndroid Build Coastguard Worker
136*9356374aSAndroid Build Coastguard Worker protected:
137*9356374aSAndroid Build Coastguard Worker // These should not be exported except for testing.
138*9356374aSAndroid Build Coastguard Worker
139*9356374aSAndroid Build Coastguard Worker // Store number of cycles between wait_start_time and wait_end_time in a
140*9356374aSAndroid Build Coastguard Worker // lock value.
141*9356374aSAndroid Build Coastguard Worker static uint32_t EncodeWaitCycles(int64_t wait_start_time,
142*9356374aSAndroid Build Coastguard Worker int64_t wait_end_time);
143*9356374aSAndroid Build Coastguard Worker
144*9356374aSAndroid Build Coastguard Worker // Extract number of wait cycles in a lock value.
145*9356374aSAndroid Build Coastguard Worker static int64_t DecodeWaitCycles(uint32_t lock_value);
146*9356374aSAndroid Build Coastguard Worker
147*9356374aSAndroid Build Coastguard Worker // Provide access to protected method above. Use for testing only.
148*9356374aSAndroid Build Coastguard Worker friend struct SpinLockTest;
149*9356374aSAndroid Build Coastguard Worker friend class tcmalloc::tcmalloc_internal::AllocationGuardSpinLockHolder;
150*9356374aSAndroid Build Coastguard Worker
151*9356374aSAndroid Build Coastguard Worker private:
152*9356374aSAndroid Build Coastguard Worker // lockword_ is used to store the following:
153*9356374aSAndroid Build Coastguard Worker //
154*9356374aSAndroid Build Coastguard Worker // bit[0] encodes whether a lock is being held.
155*9356374aSAndroid Build Coastguard Worker // bit[1] encodes whether a lock uses cooperative scheduling.
156*9356374aSAndroid Build Coastguard Worker // bit[2] encodes whether the current lock holder disabled scheduling when
157*9356374aSAndroid Build Coastguard Worker // acquiring the lock. Only set when kSpinLockHeld is also set.
158*9356374aSAndroid Build Coastguard Worker // bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
159*9356374aSAndroid Build Coastguard Worker // This is set by the lock holder to indicate how long it waited on
160*9356374aSAndroid Build Coastguard Worker // the lock before eventually acquiring it. The number of cycles is
161*9356374aSAndroid Build Coastguard Worker // encoded as a 29-bit unsigned int, or in the case that the current
162*9356374aSAndroid Build Coastguard Worker // holder did not wait but another waiter is queued, the LSB
163*9356374aSAndroid Build Coastguard Worker // (kSpinLockSleeper) is set. The implementation does not explicitly
164*9356374aSAndroid Build Coastguard Worker // track the number of queued waiters beyond this. It must always be
165*9356374aSAndroid Build Coastguard Worker // assumed that waiters may exist if the current holder was required to
166*9356374aSAndroid Build Coastguard Worker // queue.
167*9356374aSAndroid Build Coastguard Worker //
168*9356374aSAndroid Build Coastguard Worker // Invariant: if the lock is not held, the value is either 0 or
169*9356374aSAndroid Build Coastguard Worker // kSpinLockCooperative.
170*9356374aSAndroid Build Coastguard Worker static constexpr uint32_t kSpinLockHeld = 1;
171*9356374aSAndroid Build Coastguard Worker static constexpr uint32_t kSpinLockCooperative = 2;
172*9356374aSAndroid Build Coastguard Worker static constexpr uint32_t kSpinLockDisabledScheduling = 4;
173*9356374aSAndroid Build Coastguard Worker static constexpr uint32_t kSpinLockSleeper = 8;
174*9356374aSAndroid Build Coastguard Worker // Includes kSpinLockSleeper.
175*9356374aSAndroid Build Coastguard Worker static constexpr uint32_t kWaitTimeMask =
176*9356374aSAndroid Build Coastguard Worker ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling);
177*9356374aSAndroid Build Coastguard Worker
178*9356374aSAndroid Build Coastguard Worker // Returns true if the provided scheduling mode is cooperative.
IsCooperative(base_internal::SchedulingMode scheduling_mode)179*9356374aSAndroid Build Coastguard Worker static constexpr bool IsCooperative(
180*9356374aSAndroid Build Coastguard Worker base_internal::SchedulingMode scheduling_mode) {
181*9356374aSAndroid Build Coastguard Worker return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
182*9356374aSAndroid Build Coastguard Worker }
183*9356374aSAndroid Build Coastguard Worker
IsCooperative()184*9356374aSAndroid Build Coastguard Worker bool IsCooperative() const {
185*9356374aSAndroid Build Coastguard Worker return lockword_.load(std::memory_order_relaxed) & kSpinLockCooperative;
186*9356374aSAndroid Build Coastguard Worker }
187*9356374aSAndroid Build Coastguard Worker
188*9356374aSAndroid Build Coastguard Worker uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
189*9356374aSAndroid Build Coastguard Worker void SlowLock() ABSL_ATTRIBUTE_COLD;
190*9356374aSAndroid Build Coastguard Worker void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
191*9356374aSAndroid Build Coastguard Worker uint32_t SpinLoop();
192*9356374aSAndroid Build Coastguard Worker
TryLockImpl()193*9356374aSAndroid Build Coastguard Worker inline bool TryLockImpl() {
194*9356374aSAndroid Build Coastguard Worker uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
195*9356374aSAndroid Build Coastguard Worker return (TryLockInternal(lock_value, 0) & kSpinLockHeld) == 0;
196*9356374aSAndroid Build Coastguard Worker }
197*9356374aSAndroid Build Coastguard Worker
198*9356374aSAndroid Build Coastguard Worker std::atomic<uint32_t> lockword_;
199*9356374aSAndroid Build Coastguard Worker
200*9356374aSAndroid Build Coastguard Worker SpinLock(const SpinLock&) = delete;
201*9356374aSAndroid Build Coastguard Worker SpinLock& operator=(const SpinLock&) = delete;
202*9356374aSAndroid Build Coastguard Worker };
203*9356374aSAndroid Build Coastguard Worker
204*9356374aSAndroid Build Coastguard Worker // Corresponding locker object that arranges to acquire a spinlock for
205*9356374aSAndroid Build Coastguard Worker // the duration of a C++ scope.
206*9356374aSAndroid Build Coastguard Worker //
207*9356374aSAndroid Build Coastguard Worker // TODO(b/176172494): Use only [[nodiscard]] when baseline is raised.
208*9356374aSAndroid Build Coastguard Worker // TODO(b/6695610): Remove forward declaration when #ifdef is no longer needed.
209*9356374aSAndroid Build Coastguard Worker #if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard)
210*9356374aSAndroid Build Coastguard Worker class [[nodiscard]] SpinLockHolder;
211*9356374aSAndroid Build Coastguard Worker #else
212*9356374aSAndroid Build Coastguard Worker class ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI SpinLockHolder;
213*9356374aSAndroid Build Coastguard Worker #endif
214*9356374aSAndroid Build Coastguard Worker
215*9356374aSAndroid Build Coastguard Worker class ABSL_SCOPED_LOCKABLE SpinLockHolder {
216*9356374aSAndroid Build Coastguard Worker public:
SpinLockHolder(SpinLock * l)217*9356374aSAndroid Build Coastguard Worker inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
218*9356374aSAndroid Build Coastguard Worker : lock_(l) {
219*9356374aSAndroid Build Coastguard Worker l->Lock();
220*9356374aSAndroid Build Coastguard Worker }
ABSL_UNLOCK_FUNCTION()221*9356374aSAndroid Build Coastguard Worker inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); }
222*9356374aSAndroid Build Coastguard Worker
223*9356374aSAndroid Build Coastguard Worker SpinLockHolder(const SpinLockHolder&) = delete;
224*9356374aSAndroid Build Coastguard Worker SpinLockHolder& operator=(const SpinLockHolder&) = delete;
225*9356374aSAndroid Build Coastguard Worker
226*9356374aSAndroid Build Coastguard Worker private:
227*9356374aSAndroid Build Coastguard Worker SpinLock* lock_;
228*9356374aSAndroid Build Coastguard Worker };
229*9356374aSAndroid Build Coastguard Worker
230*9356374aSAndroid Build Coastguard Worker // Register a hook for profiling support.
231*9356374aSAndroid Build Coastguard Worker //
232*9356374aSAndroid Build Coastguard Worker // The function pointer registered here will be called whenever a spinlock is
233*9356374aSAndroid Build Coastguard Worker // contended. The callback is given an opaque handle to the contended spinlock
234*9356374aSAndroid Build Coastguard Worker // and the number of wait cycles. This is thread-safe, but only a single
235*9356374aSAndroid Build Coastguard Worker // profiler can be registered. It is an error to call this function multiple
236*9356374aSAndroid Build Coastguard Worker // times with different arguments.
237*9356374aSAndroid Build Coastguard Worker void RegisterSpinLockProfiler(void (*fn)(const void* lock,
238*9356374aSAndroid Build Coastguard Worker int64_t wait_cycles));
239*9356374aSAndroid Build Coastguard Worker
240*9356374aSAndroid Build Coastguard Worker //------------------------------------------------------------------------------
241*9356374aSAndroid Build Coastguard Worker // Public interface ends here.
242*9356374aSAndroid Build Coastguard Worker //------------------------------------------------------------------------------
243*9356374aSAndroid Build Coastguard Worker
244*9356374aSAndroid Build Coastguard Worker // If (result & kSpinLockHeld) == 0, then *this was successfully locked.
245*9356374aSAndroid Build Coastguard Worker // Otherwise, returns last observed value for lockword_.
TryLockInternal(uint32_t lock_value,uint32_t wait_cycles)246*9356374aSAndroid Build Coastguard Worker inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
247*9356374aSAndroid Build Coastguard Worker uint32_t wait_cycles) {
248*9356374aSAndroid Build Coastguard Worker if ((lock_value & kSpinLockHeld) != 0) {
249*9356374aSAndroid Build Coastguard Worker return lock_value;
250*9356374aSAndroid Build Coastguard Worker }
251*9356374aSAndroid Build Coastguard Worker
252*9356374aSAndroid Build Coastguard Worker uint32_t sched_disabled_bit = 0;
253*9356374aSAndroid Build Coastguard Worker if ((lock_value & kSpinLockCooperative) == 0) {
254*9356374aSAndroid Build Coastguard Worker // For non-cooperative locks we must make sure we mark ourselves as
255*9356374aSAndroid Build Coastguard Worker // non-reschedulable before we attempt to CompareAndSwap.
256*9356374aSAndroid Build Coastguard Worker if (base_internal::SchedulingGuard::DisableRescheduling()) {
257*9356374aSAndroid Build Coastguard Worker sched_disabled_bit = kSpinLockDisabledScheduling;
258*9356374aSAndroid Build Coastguard Worker }
259*9356374aSAndroid Build Coastguard Worker }
260*9356374aSAndroid Build Coastguard Worker
261*9356374aSAndroid Build Coastguard Worker if (!lockword_.compare_exchange_strong(
262*9356374aSAndroid Build Coastguard Worker lock_value,
263*9356374aSAndroid Build Coastguard Worker kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit,
264*9356374aSAndroid Build Coastguard Worker std::memory_order_acquire, std::memory_order_relaxed)) {
265*9356374aSAndroid Build Coastguard Worker base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0);
266*9356374aSAndroid Build Coastguard Worker }
267*9356374aSAndroid Build Coastguard Worker
268*9356374aSAndroid Build Coastguard Worker return lock_value;
269*9356374aSAndroid Build Coastguard Worker }
270*9356374aSAndroid Build Coastguard Worker
271*9356374aSAndroid Build Coastguard Worker } // namespace base_internal
272*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
273*9356374aSAndroid Build Coastguard Worker } // namespace absl
274*9356374aSAndroid Build Coastguard Worker
275*9356374aSAndroid Build Coastguard Worker #endif // ABSL_BASE_INTERNAL_SPINLOCK_H_
276