23 #include <type_traits>
26 #include "gtest/gtest.h"
27 #include "absl/base/attributes.h"
28 #include "absl/base/config.h"
29 #include "absl/base/internal/low_level_scheduling.h"
30 #include "absl/base/internal/scheduling_mode.h"
31 #include "absl/base/internal/spinlock.h"
32 #include "absl/base/internal/sysinfo.h"
33 #include "absl/base/macros.h"
34 #include "absl/synchronization/blocking_counter.h"
35 #include "absl/synchronization/notification.h"
42 namespace base_internal {
58 static constexpr
int kArrayLength = 10;
70 a -=
b;
a -= c;
a ^= (c >> 13);
71 b -= c;
b -=
a;
b ^= (
a << 8);
72 c -=
a; c -=
b; c ^= (
b >> 13);
73 a -=
b;
a -= c;
a ^= (c >> 12);
74 b -= c;
b -=
a;
b ^= (
a << 16);
75 c -=
a; c -=
b; c ^= (
b >> 5);
76 a -=
b;
a -= c;
a ^= (c >> 3);
77 b -= c;
b -=
a;
b ^= (
a << 10);
78 c -=
a; c -=
b; c ^= (
b >> 15);
82 static void TestFunction(
int thread_salt, SpinLock* spinlock) {
84 SpinLockHolder h(spinlock);
85 for (
int j = 0; j < kArrayLength; j++) {
86 const int index = (j + thread_salt) % kArrayLength;
88 std::this_thread::yield();
93 static void ThreadedTest(SpinLock* spinlock) {
94 std::vector<std::thread>
threads;
103 SpinLockHolder
h(spinlock);
104 for (
int i = 1;
i < kArrayLength;
i++) {
109 #ifndef ABSL_HAVE_THREAD_SANITIZER
110 static_assert(std::is_trivially_destructible<SpinLock>(),
"");
113 TEST(SpinLock, StackNonCooperativeDisablesScheduling) {
120 TEST(SpinLock, StaticNonCooperativeDisablesScheduling) {
121 static_noncooperative_spinlock.Lock();
123 static_noncooperative_spinlock.Unlock();
126 TEST(SpinLock, WaitCyclesEncoding) {
130 const uint32_t kSpinLockSleeper = 8;
134 const int kMaxCyclesShift =
145 std::default_random_engine generator;
147 std::uniform_int_distribution<uint64_t> time_distribution(
149 std::uniform_int_distribution<uint64_t> cycle_distribution(0, kMaxCycles);
151 for (
int i = 0;
i < 100;
i++) {
153 int64_t cycles = cycle_distribution(generator);
156 EXPECT_EQ(0, lock_value & kLockwordReservedMask);
158 EXPECT_EQ(0, decoded & kProfileTimestampMask);
159 EXPECT_EQ(cycles & ~kProfileTimestampMask, decoded);
168 EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask,
176 EXPECT_NE(sleeper_value, kSpinLockSleeper);
182 uint64_t expected_max_value_decoded = kMaxCycles & ~kProfileTimestampMask;
183 EXPECT_EQ(expected_max_value_decoded, max_value_decoded);
190 EXPECT_EQ(expected_max_value_decoded, after_max_value_decoded);
196 EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
199 TEST(SpinLockWithThreads, StackSpinLock) {
201 ThreadedTest(&spinlock);
204 TEST(SpinLockWithThreads, StackCooperativeSpinLock) {
206 ThreadedTest(&spinlock);
209 TEST(SpinLockWithThreads, StackNonCooperativeSpinLock) {
211 ThreadedTest(&spinlock);
214 TEST(SpinLockWithThreads, StaticCooperativeSpinLock) {
215 ThreadedTest(&static_cooperative_spinlock);
218 TEST(SpinLockWithThreads, StaticNonCooperativeSpinLock) {
219 ThreadedTest(&static_noncooperative_spinlock);
222 TEST(SpinLockWithThreads, DoesNotDeadlock) {
224 static void NotifyThenLock(Notification* locked, SpinLock* spinlock,
225 BlockingCounter*
b) {
226 locked->WaitForNotification();
228 SpinLockHolder
l(spinlock);
231 static void LockThenWait(Notification* locked, SpinLock* spinlock,
232 BlockingCounter*
b) {
233 SpinLockHolder
l(spinlock);
238 static void DeadlockTest(SpinLock* spinlock,
int num_spinners) {
240 BlockingCounter
counter(num_spinners);
241 std::vector<std::thread>
threads;
245 for (
int i = 0;
i < num_spinners; ++
i) {
256 SpinLock stack_cooperative_spinlock(
259 Helper::DeadlockTest(&stack_cooperative_spinlock,
261 Helper::DeadlockTest(&stack_noncooperative_spinlock,
263 Helper::DeadlockTest(&static_cooperative_spinlock,
265 Helper::DeadlockTest(&static_noncooperative_spinlock,