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 // A bunch of threads repeatedly hash an array of ints protected by a
16*9356374aSAndroid Build Coastguard Worker // spinlock. If the spinlock is working properly, all elements of the
17*9356374aSAndroid Build Coastguard Worker // array should be equal at the end of the test.
18*9356374aSAndroid Build Coastguard Worker
19*9356374aSAndroid Build Coastguard Worker #include <cstdint>
20*9356374aSAndroid Build Coastguard Worker #include <limits>
21*9356374aSAndroid Build Coastguard Worker #include <random>
22*9356374aSAndroid Build Coastguard Worker #include <thread> // NOLINT(build/c++11)
23*9356374aSAndroid Build Coastguard Worker #include <type_traits>
24*9356374aSAndroid Build Coastguard Worker #include <vector>
25*9356374aSAndroid Build Coastguard Worker
26*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
27*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
28*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
29*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/low_level_scheduling.h"
30*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/scheduling_mode.h"
31*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/spinlock.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/sysinfo.h"
33*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/blocking_counter.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/notification.h"
36*9356374aSAndroid Build Coastguard Worker
37*9356374aSAndroid Build Coastguard Worker constexpr uint32_t kNumThreads = 10;
38*9356374aSAndroid Build Coastguard Worker constexpr int32_t kIters = 1000;
39*9356374aSAndroid Build Coastguard Worker
40*9356374aSAndroid Build Coastguard Worker namespace absl {
41*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
42*9356374aSAndroid Build Coastguard Worker namespace base_internal {
43*9356374aSAndroid Build Coastguard Worker
44*9356374aSAndroid Build Coastguard Worker // This is defined outside of anonymous namespace so that it can be
45*9356374aSAndroid Build Coastguard Worker // a friend of SpinLock to access protected methods for testing.
46*9356374aSAndroid Build Coastguard Worker struct SpinLockTest {
EncodeWaitCyclesabsl::base_internal::SpinLockTest47*9356374aSAndroid Build Coastguard Worker static uint32_t EncodeWaitCycles(int64_t wait_start_time,
48*9356374aSAndroid Build Coastguard Worker int64_t wait_end_time) {
49*9356374aSAndroid Build Coastguard Worker return SpinLock::EncodeWaitCycles(wait_start_time, wait_end_time);
50*9356374aSAndroid Build Coastguard Worker }
DecodeWaitCyclesabsl::base_internal::SpinLockTest51*9356374aSAndroid Build Coastguard Worker static int64_t DecodeWaitCycles(uint32_t lock_value) {
52*9356374aSAndroid Build Coastguard Worker return SpinLock::DecodeWaitCycles(lock_value);
53*9356374aSAndroid Build Coastguard Worker }
54*9356374aSAndroid Build Coastguard Worker
IsCooperativeabsl::base_internal::SpinLockTest55*9356374aSAndroid Build Coastguard Worker static bool IsCooperative(const SpinLock& l) { return l.IsCooperative(); }
56*9356374aSAndroid Build Coastguard Worker };
57*9356374aSAndroid Build Coastguard Worker
58*9356374aSAndroid Build Coastguard Worker namespace {
59*9356374aSAndroid Build Coastguard Worker
60*9356374aSAndroid Build Coastguard Worker static constexpr size_t kArrayLength = 10;
61*9356374aSAndroid Build Coastguard Worker static uint32_t values[kArrayLength];
62*9356374aSAndroid Build Coastguard Worker
63*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT static SpinLock static_cooperative_spinlock(
64*9356374aSAndroid Build Coastguard Worker absl::kConstInit, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
65*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT static SpinLock static_noncooperative_spinlock(
66*9356374aSAndroid Build Coastguard Worker absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
67*9356374aSAndroid Build Coastguard Worker
68*9356374aSAndroid Build Coastguard Worker // Simple integer hash function based on the public domain lookup2 hash.
69*9356374aSAndroid Build Coastguard Worker // http://burtleburtle.net/bob/c/lookup2.c
Hash32(uint32_t a,uint32_t c)70*9356374aSAndroid Build Coastguard Worker static uint32_t Hash32(uint32_t a, uint32_t c) {
71*9356374aSAndroid Build Coastguard Worker uint32_t b = 0x9e3779b9UL; // The golden ratio; an arbitrary value.
72*9356374aSAndroid Build Coastguard Worker a -= b; a -= c; a ^= (c >> 13);
73*9356374aSAndroid Build Coastguard Worker b -= c; b -= a; b ^= (a << 8);
74*9356374aSAndroid Build Coastguard Worker c -= a; c -= b; c ^= (b >> 13);
75*9356374aSAndroid Build Coastguard Worker a -= b; a -= c; a ^= (c >> 12);
76*9356374aSAndroid Build Coastguard Worker b -= c; b -= a; b ^= (a << 16);
77*9356374aSAndroid Build Coastguard Worker c -= a; c -= b; c ^= (b >> 5);
78*9356374aSAndroid Build Coastguard Worker a -= b; a -= c; a ^= (c >> 3);
79*9356374aSAndroid Build Coastguard Worker b -= c; b -= a; b ^= (a << 10);
80*9356374aSAndroid Build Coastguard Worker c -= a; c -= b; c ^= (b >> 15);
81*9356374aSAndroid Build Coastguard Worker return c;
82*9356374aSAndroid Build Coastguard Worker }
83*9356374aSAndroid Build Coastguard Worker
TestFunction(uint32_t thread_salt,SpinLock * spinlock)84*9356374aSAndroid Build Coastguard Worker static void TestFunction(uint32_t thread_salt, SpinLock* spinlock) {
85*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < kIters; i++) {
86*9356374aSAndroid Build Coastguard Worker SpinLockHolder h(spinlock);
87*9356374aSAndroid Build Coastguard Worker for (size_t j = 0; j < kArrayLength; j++) {
88*9356374aSAndroid Build Coastguard Worker const size_t index = (j + thread_salt) % kArrayLength;
89*9356374aSAndroid Build Coastguard Worker values[index] = Hash32(values[index], thread_salt);
90*9356374aSAndroid Build Coastguard Worker std::this_thread::yield();
91*9356374aSAndroid Build Coastguard Worker }
92*9356374aSAndroid Build Coastguard Worker }
93*9356374aSAndroid Build Coastguard Worker }
94*9356374aSAndroid Build Coastguard Worker
ThreadedTest(SpinLock * spinlock)95*9356374aSAndroid Build Coastguard Worker static void ThreadedTest(SpinLock* spinlock) {
96*9356374aSAndroid Build Coastguard Worker std::vector<std::thread> threads;
97*9356374aSAndroid Build Coastguard Worker threads.reserve(kNumThreads);
98*9356374aSAndroid Build Coastguard Worker for (uint32_t i = 0; i < kNumThreads; ++i) {
99*9356374aSAndroid Build Coastguard Worker threads.push_back(std::thread(TestFunction, i, spinlock));
100*9356374aSAndroid Build Coastguard Worker }
101*9356374aSAndroid Build Coastguard Worker for (auto& thread : threads) {
102*9356374aSAndroid Build Coastguard Worker thread.join();
103*9356374aSAndroid Build Coastguard Worker }
104*9356374aSAndroid Build Coastguard Worker
105*9356374aSAndroid Build Coastguard Worker SpinLockHolder h(spinlock);
106*9356374aSAndroid Build Coastguard Worker for (size_t i = 1; i < kArrayLength; i++) {
107*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(values[0], values[i]);
108*9356374aSAndroid Build Coastguard Worker }
109*9356374aSAndroid Build Coastguard Worker }
110*9356374aSAndroid Build Coastguard Worker
111*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HAVE_THREAD_SANITIZER
112*9356374aSAndroid Build Coastguard Worker static_assert(std::is_trivially_destructible<SpinLock>(), "");
113*9356374aSAndroid Build Coastguard Worker #endif
114*9356374aSAndroid Build Coastguard Worker
TEST(SpinLock,StackNonCooperativeDisablesScheduling)115*9356374aSAndroid Build Coastguard Worker TEST(SpinLock, StackNonCooperativeDisablesScheduling) {
116*9356374aSAndroid Build Coastguard Worker SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);
117*9356374aSAndroid Build Coastguard Worker spinlock.Lock();
118*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed());
119*9356374aSAndroid Build Coastguard Worker spinlock.Unlock();
120*9356374aSAndroid Build Coastguard Worker }
121*9356374aSAndroid Build Coastguard Worker
TEST(SpinLock,StaticNonCooperativeDisablesScheduling)122*9356374aSAndroid Build Coastguard Worker TEST(SpinLock, StaticNonCooperativeDisablesScheduling) {
123*9356374aSAndroid Build Coastguard Worker static_noncooperative_spinlock.Lock();
124*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(base_internal::SchedulingGuard::ReschedulingIsAllowed());
125*9356374aSAndroid Build Coastguard Worker static_noncooperative_spinlock.Unlock();
126*9356374aSAndroid Build Coastguard Worker }
127*9356374aSAndroid Build Coastguard Worker
TEST(SpinLock,WaitCyclesEncoding)128*9356374aSAndroid Build Coastguard Worker TEST(SpinLock, WaitCyclesEncoding) {
129*9356374aSAndroid Build Coastguard Worker // These are implementation details not exported by SpinLock.
130*9356374aSAndroid Build Coastguard Worker const int kProfileTimestampShift = 7;
131*9356374aSAndroid Build Coastguard Worker const int kLockwordReservedShift = 3;
132*9356374aSAndroid Build Coastguard Worker const uint32_t kSpinLockSleeper = 8;
133*9356374aSAndroid Build Coastguard Worker
134*9356374aSAndroid Build Coastguard Worker // We should be able to encode up to (1^kMaxCycleBits - 1) without clamping
135*9356374aSAndroid Build Coastguard Worker // but the lower kProfileTimestampShift will be dropped.
136*9356374aSAndroid Build Coastguard Worker const int kMaxCyclesShift =
137*9356374aSAndroid Build Coastguard Worker 32 - kLockwordReservedShift + kProfileTimestampShift;
138*9356374aSAndroid Build Coastguard Worker const int64_t kMaxCycles = (int64_t{1} << kMaxCyclesShift) - 1;
139*9356374aSAndroid Build Coastguard Worker
140*9356374aSAndroid Build Coastguard Worker // These bits should be zero after encoding.
141*9356374aSAndroid Build Coastguard Worker const uint32_t kLockwordReservedMask = (1 << kLockwordReservedShift) - 1;
142*9356374aSAndroid Build Coastguard Worker
143*9356374aSAndroid Build Coastguard Worker // These bits are dropped when wait cycles are encoded.
144*9356374aSAndroid Build Coastguard Worker const int64_t kProfileTimestampMask = (1 << kProfileTimestampShift) - 1;
145*9356374aSAndroid Build Coastguard Worker
146*9356374aSAndroid Build Coastguard Worker // Test a bunch of random values
147*9356374aSAndroid Build Coastguard Worker std::default_random_engine generator;
148*9356374aSAndroid Build Coastguard Worker // Shift to avoid overflow below.
149*9356374aSAndroid Build Coastguard Worker std::uniform_int_distribution<int64_t> time_distribution(
150*9356374aSAndroid Build Coastguard Worker 0, std::numeric_limits<int64_t>::max() >> 3);
151*9356374aSAndroid Build Coastguard Worker std::uniform_int_distribution<int64_t> cycle_distribution(0, kMaxCycles);
152*9356374aSAndroid Build Coastguard Worker
153*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < 100; i++) {
154*9356374aSAndroid Build Coastguard Worker int64_t start_time = time_distribution(generator);
155*9356374aSAndroid Build Coastguard Worker int64_t cycles = cycle_distribution(generator);
156*9356374aSAndroid Build Coastguard Worker int64_t end_time = start_time + cycles;
157*9356374aSAndroid Build Coastguard Worker uint32_t lock_value = SpinLockTest::EncodeWaitCycles(start_time, end_time);
158*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(0u, lock_value & kLockwordReservedMask);
159*9356374aSAndroid Build Coastguard Worker int64_t decoded = SpinLockTest::DecodeWaitCycles(lock_value);
160*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(0, decoded & kProfileTimestampMask);
161*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(cycles & ~kProfileTimestampMask, decoded);
162*9356374aSAndroid Build Coastguard Worker }
163*9356374aSAndroid Build Coastguard Worker
164*9356374aSAndroid Build Coastguard Worker // Test corner cases
165*9356374aSAndroid Build Coastguard Worker int64_t start_time = time_distribution(generator);
166*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(kSpinLockSleeper,
167*9356374aSAndroid Build Coastguard Worker SpinLockTest::EncodeWaitCycles(start_time, start_time));
168*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(0));
169*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(kLockwordReservedMask));
170*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask,
171*9356374aSAndroid Build Coastguard Worker SpinLockTest::DecodeWaitCycles(~kLockwordReservedMask));
172*9356374aSAndroid Build Coastguard Worker
173*9356374aSAndroid Build Coastguard Worker // Check that we cannot produce kSpinLockSleeper during encoding.
174*9356374aSAndroid Build Coastguard Worker int64_t sleeper_cycles =
175*9356374aSAndroid Build Coastguard Worker kSpinLockSleeper << (kProfileTimestampShift - kLockwordReservedShift);
176*9356374aSAndroid Build Coastguard Worker uint32_t sleeper_value =
177*9356374aSAndroid Build Coastguard Worker SpinLockTest::EncodeWaitCycles(start_time, start_time + sleeper_cycles);
178*9356374aSAndroid Build Coastguard Worker EXPECT_NE(sleeper_value, kSpinLockSleeper);
179*9356374aSAndroid Build Coastguard Worker
180*9356374aSAndroid Build Coastguard Worker // Test clamping
181*9356374aSAndroid Build Coastguard Worker uint32_t max_value =
182*9356374aSAndroid Build Coastguard Worker SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles);
183*9356374aSAndroid Build Coastguard Worker int64_t max_value_decoded = SpinLockTest::DecodeWaitCycles(max_value);
184*9356374aSAndroid Build Coastguard Worker int64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask;
185*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(expected_max_value_decoded, max_value_decoded);
186*9356374aSAndroid Build Coastguard Worker
187*9356374aSAndroid Build Coastguard Worker const int64_t step = (1 << kProfileTimestampShift);
188*9356374aSAndroid Build Coastguard Worker uint32_t after_max_value =
189*9356374aSAndroid Build Coastguard Worker SpinLockTest::EncodeWaitCycles(start_time, start_time + kMaxCycles + step);
190*9356374aSAndroid Build Coastguard Worker int64_t after_max_value_decoded =
191*9356374aSAndroid Build Coastguard Worker SpinLockTest::DecodeWaitCycles(after_max_value);
192*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(expected_max_value_decoded, after_max_value_decoded);
193*9356374aSAndroid Build Coastguard Worker
194*9356374aSAndroid Build Coastguard Worker uint32_t before_max_value = SpinLockTest::EncodeWaitCycles(
195*9356374aSAndroid Build Coastguard Worker start_time, start_time + kMaxCycles - step);
196*9356374aSAndroid Build Coastguard Worker int64_t before_max_value_decoded =
197*9356374aSAndroid Build Coastguard Worker SpinLockTest::DecodeWaitCycles(before_max_value);
198*9356374aSAndroid Build Coastguard Worker EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
199*9356374aSAndroid Build Coastguard Worker }
200*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockWithThreads,StackSpinLock)201*9356374aSAndroid Build Coastguard Worker TEST(SpinLockWithThreads, StackSpinLock) {
202*9356374aSAndroid Build Coastguard Worker SpinLock spinlock;
203*9356374aSAndroid Build Coastguard Worker ThreadedTest(&spinlock);
204*9356374aSAndroid Build Coastguard Worker }
205*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockWithThreads,StackCooperativeSpinLock)206*9356374aSAndroid Build Coastguard Worker TEST(SpinLockWithThreads, StackCooperativeSpinLock) {
207*9356374aSAndroid Build Coastguard Worker SpinLock spinlock(base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
208*9356374aSAndroid Build Coastguard Worker ThreadedTest(&spinlock);
209*9356374aSAndroid Build Coastguard Worker }
210*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockWithThreads,StackNonCooperativeSpinLock)211*9356374aSAndroid Build Coastguard Worker TEST(SpinLockWithThreads, StackNonCooperativeSpinLock) {
212*9356374aSAndroid Build Coastguard Worker SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);
213*9356374aSAndroid Build Coastguard Worker ThreadedTest(&spinlock);
214*9356374aSAndroid Build Coastguard Worker }
215*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockWithThreads,StaticCooperativeSpinLock)216*9356374aSAndroid Build Coastguard Worker TEST(SpinLockWithThreads, StaticCooperativeSpinLock) {
217*9356374aSAndroid Build Coastguard Worker ThreadedTest(&static_cooperative_spinlock);
218*9356374aSAndroid Build Coastguard Worker }
219*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockWithThreads,StaticNonCooperativeSpinLock)220*9356374aSAndroid Build Coastguard Worker TEST(SpinLockWithThreads, StaticNonCooperativeSpinLock) {
221*9356374aSAndroid Build Coastguard Worker ThreadedTest(&static_noncooperative_spinlock);
222*9356374aSAndroid Build Coastguard Worker }
223*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockWithThreads,DoesNotDeadlock)224*9356374aSAndroid Build Coastguard Worker TEST(SpinLockWithThreads, DoesNotDeadlock) {
225*9356374aSAndroid Build Coastguard Worker struct Helper {
226*9356374aSAndroid Build Coastguard Worker static void NotifyThenLock(Notification* locked, SpinLock* spinlock,
227*9356374aSAndroid Build Coastguard Worker BlockingCounter* b) {
228*9356374aSAndroid Build Coastguard Worker locked->WaitForNotification(); // Wait for LockThenWait() to hold "s".
229*9356374aSAndroid Build Coastguard Worker b->DecrementCount();
230*9356374aSAndroid Build Coastguard Worker SpinLockHolder l(spinlock);
231*9356374aSAndroid Build Coastguard Worker }
232*9356374aSAndroid Build Coastguard Worker
233*9356374aSAndroid Build Coastguard Worker static void LockThenWait(Notification* locked, SpinLock* spinlock,
234*9356374aSAndroid Build Coastguard Worker BlockingCounter* b) {
235*9356374aSAndroid Build Coastguard Worker SpinLockHolder l(spinlock);
236*9356374aSAndroid Build Coastguard Worker locked->Notify();
237*9356374aSAndroid Build Coastguard Worker b->Wait();
238*9356374aSAndroid Build Coastguard Worker }
239*9356374aSAndroid Build Coastguard Worker
240*9356374aSAndroid Build Coastguard Worker static void DeadlockTest(SpinLock* spinlock, int num_spinners) {
241*9356374aSAndroid Build Coastguard Worker Notification locked;
242*9356374aSAndroid Build Coastguard Worker BlockingCounter counter(num_spinners);
243*9356374aSAndroid Build Coastguard Worker std::vector<std::thread> threads;
244*9356374aSAndroid Build Coastguard Worker
245*9356374aSAndroid Build Coastguard Worker threads.push_back(
246*9356374aSAndroid Build Coastguard Worker std::thread(Helper::LockThenWait, &locked, spinlock, &counter));
247*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < num_spinners; ++i) {
248*9356374aSAndroid Build Coastguard Worker threads.push_back(
249*9356374aSAndroid Build Coastguard Worker std::thread(Helper::NotifyThenLock, &locked, spinlock, &counter));
250*9356374aSAndroid Build Coastguard Worker }
251*9356374aSAndroid Build Coastguard Worker
252*9356374aSAndroid Build Coastguard Worker for (auto& thread : threads) {
253*9356374aSAndroid Build Coastguard Worker thread.join();
254*9356374aSAndroid Build Coastguard Worker }
255*9356374aSAndroid Build Coastguard Worker }
256*9356374aSAndroid Build Coastguard Worker };
257*9356374aSAndroid Build Coastguard Worker
258*9356374aSAndroid Build Coastguard Worker SpinLock stack_cooperative_spinlock(
259*9356374aSAndroid Build Coastguard Worker base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
260*9356374aSAndroid Build Coastguard Worker SpinLock stack_noncooperative_spinlock(base_internal::SCHEDULE_KERNEL_ONLY);
261*9356374aSAndroid Build Coastguard Worker Helper::DeadlockTest(&stack_cooperative_spinlock,
262*9356374aSAndroid Build Coastguard Worker base_internal::NumCPUs() * 2);
263*9356374aSAndroid Build Coastguard Worker Helper::DeadlockTest(&stack_noncooperative_spinlock,
264*9356374aSAndroid Build Coastguard Worker base_internal::NumCPUs() * 2);
265*9356374aSAndroid Build Coastguard Worker Helper::DeadlockTest(&static_cooperative_spinlock,
266*9356374aSAndroid Build Coastguard Worker base_internal::NumCPUs() * 2);
267*9356374aSAndroid Build Coastguard Worker Helper::DeadlockTest(&static_noncooperative_spinlock,
268*9356374aSAndroid Build Coastguard Worker base_internal::NumCPUs() * 2);
269*9356374aSAndroid Build Coastguard Worker }
270*9356374aSAndroid Build Coastguard Worker
TEST(SpinLockTest,IsCooperative)271*9356374aSAndroid Build Coastguard Worker TEST(SpinLockTest, IsCooperative) {
272*9356374aSAndroid Build Coastguard Worker SpinLock default_constructor;
273*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(SpinLockTest::IsCooperative(default_constructor));
274*9356374aSAndroid Build Coastguard Worker
275*9356374aSAndroid Build Coastguard Worker SpinLock cooperative(base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
276*9356374aSAndroid Build Coastguard Worker EXPECT_TRUE(SpinLockTest::IsCooperative(cooperative));
277*9356374aSAndroid Build Coastguard Worker
278*9356374aSAndroid Build Coastguard Worker SpinLock kernel_only(base_internal::SCHEDULE_KERNEL_ONLY);
279*9356374aSAndroid Build Coastguard Worker EXPECT_FALSE(SpinLockTest::IsCooperative(kernel_only));
280*9356374aSAndroid Build Coastguard Worker }
281*9356374aSAndroid Build Coastguard Worker
282*9356374aSAndroid Build Coastguard Worker } // namespace
283*9356374aSAndroid Build Coastguard Worker } // namespace base_internal
284*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
285*9356374aSAndroid Build Coastguard Worker } // namespace absl
286