15 #include "absl/synchronization/mutex.h"
31 #include "gtest/gtest.h"
32 #include "absl/base/attributes.h"
33 #include "absl/base/config.h"
34 #include "absl/base/internal/raw_logging.h"
35 #include "absl/base/internal/sysinfo.h"
36 #include "absl/memory/memory.h"
37 #include "absl/synchronization/internal/thread_pool.h"
38 #include "absl/time/clock.h"
39 #include "absl/time/time.h"
44 static constexpr
bool kExtendedTest =
false;
46 std::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool(
48 return absl::make_unique<absl::synchronization_internal::ThreadPool>(
threads);
51 std::unique_ptr<absl::synchronization_internal::ThreadPool>
53 return CreatePool(kExtendedTest ? 32 : 10);
77 static std::atomic<bool> invariant_checked;
79 static bool GetInvariantChecked() {
80 return invariant_checked.load(std::memory_order_relaxed);
83 static void SetInvariantChecked(
bool new_value) {
84 invariant_checked.store(new_value, std::memory_order_relaxed);
87 static void CheckSumG0G1(
void *
v) {
90 SetInvariantChecked(
true);
94 for (
int i = 0;
i != cxt->iterations;
i++) {
103 for (
int i = 0;
i != cxt->iterations;
i++) {
105 std::this_thread::yield();
106 }
while (!cxt->mu.TryLock());
115 for (
int i = 0;
i != cxt->iterations;
i++) {
118 cxt->mu.AssertReaderHeld();
124 for (
int i = 0;
i != cxt->iterations;
i++) {
128 cxt->mu.AssertHeld();
129 cxt->mu.AssertReaderHeld();
132 for (
int i = 0;
i != cxt->iterations;
i++) {
135 cxt->mu.AssertReaderHeld();
146 bool MyContext::MyTurn() {
148 return cxt->g0 == this->
target || cxt->g0 == cxt->iterations;
156 cxt->mu.AssertHeld();
157 while (cxt->g0 < cxt->iterations) {
160 cxt->mu.AssertHeld();
161 if (cxt->g0 < cxt->iterations) {
164 mc.target += cxt->threads;
172 cxt->mu.AssertHeld();
173 while (cxt->g0 < cxt->iterations) {
174 while (cxt->g0 !=
target && cxt->g0 != cxt->iterations) {
175 cxt->cv.Wait(&cxt->mu);
177 if (cxt->g0 < cxt->iterations) {
187 ABSL_RAW_CHECK(cxt->threads == 2,
"TestSignal should use 2 threads");
190 cxt->mu.AssertHeld();
191 while (cxt->g0 < cxt->iterations) {
192 while (cxt->g0 !=
target && cxt->g0 != cxt->iterations) {
193 cxt->cv.Wait(&cxt->mu);
195 if (cxt->g0 < cxt->iterations) {
207 cxt->mu.AssertHeld();
208 while (cxt->g0 < cxt->iterations) {
209 while (cxt->g0 !=
target && cxt->g0 != cxt->iterations) {
212 if (cxt->g0 < cxt->iterations) {
221 static bool G0GE2(
TestContext *cxt) {
return cxt->g0 >= 2; }
223 static void TestTime(
TestContext *cxt,
int c,
bool use_cv) {
224 ABSL_RAW_CHECK(cxt->iterations == 1,
"TestTime should only use 1 iteration");
225 ABSL_RAW_CHECK(cxt->threads > 2,
"TestTime should use more than 2 threads");
226 const bool kFalse =
false;
319 while (cxt->g0 < 2) {
330 while (cxt->g0 < 2) {
331 cxt->cv.Wait(&cxt->mu);
334 cxt->mu.Await(g0ge2);
340 static void TestMuTime(
TestContext *cxt,
int c) { TestTime(cxt,
c,
false); }
342 static void TestCVTime(
TestContext *cxt,
int c) { TestTime(cxt,
c,
true); }
357 int threads,
int iterations,
int operations) {
364 cxt->iterations = iterations;
368 tp.
Schedule(std::bind(&EndTest, &c0, &
c1, &mu2, &cv2,
370 std::bind(
test, cxt, std::placeholders::_1))));
382 int iterations,
int operations) {
384 return RunTestCommon(&cxt,
test,
threads, iterations, operations);
391 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
392 static int RunTestWithInvariantDebugging(
void (*
test)(
TestContext *cxt,
int),
397 SetInvariantChecked(
false);
399 cxt.mu.EnableInvariantDebugging(
invariant, &cxt);
400 int ret = RunTestCommon(&cxt,
test,
threads, iterations, operations);
409 struct TimeoutBugStruct {
415 static void WaitForA(TimeoutBugStruct *
x) {
421 static bool NoAWaiters(TimeoutBugStruct *
x) {
return x->a_waiter_count == 0; }
436 auto pool = CreateDefaultPool();
441 state.release_mu.Lock();
443 state.barrier_mu.Lock();
444 state.barrier =
true;
445 state.barrier_mu.Unlock();
448 state.released_cv.Signal();
449 state.release_mu.Unlock();
453 state.barrier_mu.Unlock();
454 state.release_mu.Lock();
459 state.release =
true;
461 state.release_mu.Unlock();
466 TEST(
Mutex, CondVarWaitWithTimeoutSignalsAwait) {
477 auto pool = CreateDefaultPool();
482 state.release_mu.Lock();
484 state.barrier_mu.Lock();
485 state.barrier =
true;
486 state.barrier_mu.Unlock();
489 state.released_cv.Signal();
490 state.release_mu.Unlock();
494 state.barrier_mu.Unlock();
495 state.release_mu.Lock();
500 state.release =
true;
503 <<
"; Unrecoverable test failure: CondVar::WaitWithTimeout did not "
504 "unblock the absl::Mutex::Await call in another thread.";
506 state.release_mu.Unlock();
511 auto tp = CreateDefaultPool();
515 x.a_waiter_count = 2;
524 bool always_false =
false;
542 bool signal_unlocked;
544 CondVarWaitDeadlock() {
547 signal_unlocked =
GetParam() & (1 << 2);
587 auto waiter1 = CreatePool(1);
588 auto waiter2 = CreatePool(1);
589 waiter1->Schedule([
this] { this->Waiter1(); });
590 waiter2->Schedule([
this] { this->Waiter2(); });
598 if (signal_unlocked) {
624 struct DequeueAllWakeableBugStruct {
627 int unfinished_count;
634 static void AcquireAsReader(DequeueAllWakeableBugStruct *
x) {
637 x->unfinished_count--;
638 x->done1 = (
x->unfinished_count == 0);
642 x->mu.ReaderUnlock();
646 x->done2 = (
x->finished_count == 0);
652 auto tp = CreateDefaultPool();
654 DequeueAllWakeableBugStruct
x;
655 x.unfinished_count = 2;
657 x.finished_count = 2;
661 tp->
Schedule(std::bind(&AcquireAsReader, &
x));
662 tp->
Schedule(std::bind(&AcquireAsReader, &
x));
676 struct LockWhenTestStruct {
681 bool waiting =
false;
684 static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
691 static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
697 LockWhenTestStruct
s;
716 bool (*cond_eq_10)(
int *) = [](
int *
p) {
return *
p == 10; };
717 bool (*cond_lt_10)(
int *) = [](
int *
p) {
return *
p < 10; };
747 #if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
758 struct ReaderDecrementBugStruct {
763 bool waiting_on_cond;
764 bool have_reader_lock;
770 static bool IsCond(
void *
v) {
771 ReaderDecrementBugStruct *
x =
reinterpret_cast<ReaderDecrementBugStruct *
>(
v);
773 x->waiting_on_cond =
true;
779 static bool AllDone(
void *
v) {
780 ReaderDecrementBugStruct *
x =
reinterpret_cast<ReaderDecrementBugStruct *
>(
v);
785 static void WaitForCond(ReaderDecrementBugStruct *
x) {
794 static void GetReadLock(ReaderDecrementBugStruct *
x) {
797 x->have_reader_lock =
true;
800 x->mu.ReaderUnlock();
809 ReaderDecrementBugStruct
x;
811 x.waiting_on_cond =
false;
812 x.have_reader_lock =
false;
832 x.mu.AssertReaderHeld();
849 #endif // !ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
853 #ifdef ABSL_HAVE_THREAD_SANITIZER
859 for (
int i = 0;
i != 10;
i++) {
861 const int kNumLocks = 10;
862 auto mu = absl::make_unique<absl::Mutex[]>(kNumLocks);
863 for (
int j = 0;
j != kNumLocks;
j++) {
886 std::random_device dev;
887 std::mt19937
gen(dev());
888 std::uniform_int_distribution<int> random_millis(0, 15);
901 template <
class...
Args>
902 bool operator()(
Args...)
const {
907 struct DerivedTrue :
True {};
922 auto is_zero = [&
value] {
return value == 0; };
931 auto is_positive = std::bind(std::less<int>(), 0, std::cref(
value));
948 static bool IntIsZero(
int *
x) {
return *
x == 0; }
953 auto tp = CreateDefaultPool();
967 struct AcquireFromConditionStruct {
976 static bool ConditionWithAcquire(AcquireFromConditionStruct *
x) {
979 if (
x->value == 2 ||
x->value == 3) {
984 bool always_false =
false;
992 return x->value == 2 ||
x->value == 3;
995 static void WaitForCond2(AcquireFromConditionStruct *
x) {
1004 auto tp = CreateDefaultPool();
1006 AcquireFromConditionStruct
x;
1010 std::bind(&WaitForCond2, &
x));
1067 class ScopedDisableBazelTestWarnings {
1069 ScopedDisableBazelTestWarnings() {
1071 char file[MAX_PATH];
1072 if (GetEnvironmentVariableA(kVarName,
file,
sizeof(
file)) <
sizeof(
file)) {
1073 warnings_output_file_ =
file;
1074 SetEnvironmentVariableA(kVarName,
nullptr);
1078 if (
file !=
nullptr) {
1079 warnings_output_file_ =
file;
1085 ~ScopedDisableBazelTestWarnings() {
1086 if (!warnings_output_file_.empty()) {
1088 SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
1090 setenv(kVarName, warnings_output_file_.c_str(), 0);
1096 static const char kVarName[];
1099 const char ScopedDisableBazelTestWarnings::kVarName[] =
1100 "TEST_WARNINGS_OUTPUT_FILE";
1102 #ifdef ABSL_HAVE_THREAD_SANITIZER
1104 TEST(
Mutex, DISABLED_DeadlockDetectorBazelWarning) {
1106 TEST(
Mutex, DeadlockDetectorBazelWarning) {
1112 ScopedDisableBazelTestWarnings disable_bazel_test_warnings;
1140 const int n_locks = 1 << 17;
1141 auto array_of_locks = absl::make_unique<absl::Mutex[]>(n_locks);
1142 for (
int i = 0;
i < n_locks;
i++) {
1145 for (
int j =
i;
j <
end;
j++) {
1146 array_of_locks[
j].Lock();
1148 for (
int j =
i;
j <
end;
j++) {
1149 array_of_locks[
j].Unlock();
1154 #ifdef ABSL_HAVE_THREAD_SANITIZER
1216 if (actual_delay < expected_delay) {
1218 "Actual delay %s was too short, expected %s (difference %s)",
1230 : TimeoutTestAllowedSchedulingDelay();
1231 if (actual_delay > expected_delay + tolerance) {
1233 "Actual delay %s was too long, expected %s (difference %s)",
1243 struct TimeoutTestParam {
1245 const char *from_file;
1250 bool use_absolute_deadline;
1266 bool expected_result;
1275 std::ostream &
operator<<(std::ostream &os,
const TimeoutTestParam ¶m) {
1276 return os <<
"from: " << param.from_file <<
":" << param.from_line
1277 <<
" use_absolute_deadline: "
1278 << (param.use_absolute_deadline ?
"true" :
"false")
1279 <<
" wait_timeout: " << param.wait_timeout
1280 <<
" satisfy_condition_delay: " << param.satisfy_condition_delay
1281 <<
" expected_result: "
1282 << (param.expected_result ?
"true" :
"false")
1283 <<
" expected_delay: " << param.expected_delay;
1287 std::ostringstream os;
1309 std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {
1313 const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay();
1320 std::vector<TimeoutTestParam>
values;
1321 for (
bool use_absolute_deadline : {
false,
true}) {
1326 values.push_back(TimeoutTestParam{
1327 __FILE__, __LINE__, use_absolute_deadline,
1335 values.push_back(TimeoutTestParam{
1336 __FILE__, __LINE__, use_absolute_deadline,
1344 values.push_back(TimeoutTestParam{
1345 __FILE__, __LINE__, use_absolute_deadline,
1356 values.push_back(TimeoutTestParam{
1357 __FILE__, __LINE__, use_absolute_deadline,
1365 values.push_back(TimeoutTestParam{
1366 __FILE__, __LINE__, use_absolute_deadline,
1377 values.push_back(TimeoutTestParam{
1378 __FILE__, __LINE__, use_absolute_deadline,
1386 values.push_back(TimeoutTestParam{
1387 __FILE__, __LINE__, use_absolute_deadline,
1395 values.push_back(TimeoutTestParam{
1396 __FILE__, __LINE__, use_absolute_deadline,
1404 values.push_back(TimeoutTestParam{
1405 __FILE__, __LINE__, use_absolute_deadline,
1419 TEST_P(TimeoutTest, Await) {
1420 const TimeoutTestParam params = GetParam();
1426 for (
int attempt = 1;; ++attempt) {
1432 std::unique_ptr<absl::synchronization_internal::ThreadPool>
pool =
1433 CreateDefaultPool();
1434 RunAfterDelay(params.satisfy_condition_delay,
pool.get(), [&] {
1435 absl::MutexLock l(&mu);
1443 params.use_absolute_deadline
1445 :
mu.AwaitWithTimeout(
cond, params.wait_timeout);
1453 TEST_P(TimeoutTest, LockWhen) {
1454 const TimeoutTestParam params = GetParam();
1460 for (
int attempt = 1;; ++attempt) {
1466 std::unique_ptr<absl::synchronization_internal::ThreadPool>
pool =
1467 CreateDefaultPool();
1468 RunAfterDelay(params.satisfy_condition_delay,
pool.get(), [&] {
1469 absl::MutexLock l(&mu);
1476 params.use_absolute_deadline
1478 :
mu.LockWhenWithTimeout(
cond, params.wait_timeout);
1488 TEST_P(TimeoutTest, ReaderLockWhen) {
1489 const TimeoutTestParam params = GetParam();
1495 for (
int attempt = 0;; ++attempt) {
1501 std::unique_ptr<absl::synchronization_internal::ThreadPool>
pool =
1502 CreateDefaultPool();
1503 RunAfterDelay(params.satisfy_condition_delay,
pool.get(), [&] {
1504 absl::MutexLock l(&mu);
1510 params.use_absolute_deadline
1514 params.wait_timeout);
1524 TEST_P(TimeoutTest, Wait) {
1525 const TimeoutTestParam params = GetParam();
1531 for (
int attempt = 0;; ++attempt) {
1538 std::unique_ptr<absl::synchronization_internal::ThreadPool>
pool =
1539 CreateDefaultPool();
1540 RunAfterDelay(params.satisfy_condition_delay,
pool.get(), [&] {
1541 absl::MutexLock l(&mu);
1551 if (params.use_absolute_deadline ?
cv.WaitWithDeadline(&
mu, deadline)
1572 logged_mutex.
Lock();
1577 logged_mutex.
Lock();
1586 static std::vector<int> AllThreadCountValues() {
1587 if (kExtendedTest) {
1588 return {2, 4, 8, 10, 16, 20, 24, 30, 32};
1603 static int ScaleIterations(
int x) {
1607 #if defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
1616 int iterations = ScaleIterations(10000000) /
threads;
1617 int operations =
threads * iterations;
1619 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
1620 iterations =
std::min(iterations, 10);
1621 operations =
threads * iterations;
1623 operations, CheckSumG0G1),
1628 TEST_P(MutexVariableThreadCountTest, Try) {
1630 int iterations = 1000000 /
threads;
1631 int operations = iterations *
threads;
1633 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
1634 iterations =
std::min(iterations, 10);
1635 operations =
threads * iterations;
1637 operations, CheckSumG0G1),
1642 TEST_P(MutexVariableThreadCountTest, R20ms) {
1644 int iterations = 100;
1645 int operations = iterations *
threads;
1649 TEST_P(MutexVariableThreadCountTest, RW) {
1651 int iterations = ScaleIterations(20000000) /
threads;
1652 int operations = iterations *
threads;
1654 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
1655 iterations =
std::min(iterations, 10);
1656 operations =
threads * iterations;
1658 operations, CheckSumG0G1),
1663 TEST_P(MutexVariableThreadCountTest, Await) {
1665 int iterations = ScaleIterations(500000);
1666 int operations = iterations;
1670 TEST_P(MutexVariableThreadCountTest, SignalAll) {
1672 int iterations = 200000 /
threads;
1673 int operations = iterations;
1680 int iterations = 200000;
1681 int operations = iterations;
1687 int iterations = 1000;
1688 int operations = iterations;