00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/synchronization/mutex.h"
00016
00017 #ifdef WIN32
00018 #include <windows.h>
00019 #endif
00020
00021 #include <algorithm>
00022 #include <atomic>
00023 #include <cstdlib>
00024 #include <functional>
00025 #include <memory>
00026 #include <random>
00027 #include <string>
00028 #include <thread>
00029 #include <vector>
00030
00031 #include "gtest/gtest.h"
00032 #include "absl/base/attributes.h"
00033 #include "absl/base/internal/raw_logging.h"
00034 #include "absl/base/internal/sysinfo.h"
00035 #include "absl/memory/memory.h"
00036 #include "absl/synchronization/internal/thread_pool.h"
00037 #include "absl/time/clock.h"
00038 #include "absl/time/time.h"
00039
00040 namespace {
00041
00042
00043 static constexpr bool kExtendedTest = false;
00044
00045 std::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool(
00046 int threads) {
00047 return absl::make_unique<absl::synchronization_internal::ThreadPool>(threads);
00048 }
00049
00050 std::unique_ptr<absl::synchronization_internal::ThreadPool>
00051 CreateDefaultPool() {
00052 return CreatePool(kExtendedTest ? 32 : 10);
00053 }
00054
00055
00056
00057 static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,
00058 absl::Duration after,
00059 const std::function<void()> &func) {
00060 tp->Schedule([func, after] {
00061 absl::SleepFor(after);
00062 func();
00063 });
00064 }
00065
00066 struct TestContext {
00067 int iterations;
00068 int threads;
00069 int g0;
00070 int g1;
00071 absl::Mutex mu;
00072 absl::CondVar cv;
00073 };
00074
00075
00076 static std::atomic<bool> invariant_checked;
00077
00078 static bool GetInvariantChecked() {
00079 return invariant_checked.load(std::memory_order_relaxed);
00080 }
00081
00082 static void SetInvariantChecked(bool new_value) {
00083 invariant_checked.store(new_value, std::memory_order_relaxed);
00084 }
00085
00086 static void CheckSumG0G1(void *v) {
00087 TestContext *cxt = static_cast<TestContext *>(v);
00088 ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in CheckSumG0G1");
00089 SetInvariantChecked(true);
00090 }
00091
00092 static void TestMu(TestContext *cxt, int c) {
00093 for (int i = 0; i != cxt->iterations; i++) {
00094 absl::MutexLock l(&cxt->mu);
00095 int a = cxt->g0 + 1;
00096 cxt->g0 = a;
00097 cxt->g1--;
00098 }
00099 }
00100
00101 static void TestTry(TestContext *cxt, int c) {
00102 for (int i = 0; i != cxt->iterations; i++) {
00103 do {
00104 std::this_thread::yield();
00105 } while (!cxt->mu.TryLock());
00106 int a = cxt->g0 + 1;
00107 cxt->g0 = a;
00108 cxt->g1--;
00109 cxt->mu.Unlock();
00110 }
00111 }
00112
00113 static void TestR20ms(TestContext *cxt, int c) {
00114 for (int i = 0; i != cxt->iterations; i++) {
00115 absl::ReaderMutexLock l(&cxt->mu);
00116 absl::SleepFor(absl::Milliseconds(20));
00117 cxt->mu.AssertReaderHeld();
00118 }
00119 }
00120
00121 static void TestRW(TestContext *cxt, int c) {
00122 if ((c & 1) == 0) {
00123 for (int i = 0; i != cxt->iterations; i++) {
00124 absl::WriterMutexLock l(&cxt->mu);
00125 cxt->g0++;
00126 cxt->g1--;
00127 cxt->mu.AssertHeld();
00128 cxt->mu.AssertReaderHeld();
00129 }
00130 } else {
00131 for (int i = 0; i != cxt->iterations; i++) {
00132 absl::ReaderMutexLock l(&cxt->mu);
00133 ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in TestRW");
00134 cxt->mu.AssertReaderHeld();
00135 }
00136 }
00137 }
00138
00139 struct MyContext {
00140 int target;
00141 TestContext *cxt;
00142 bool MyTurn();
00143 };
00144
00145 bool MyContext::MyTurn() {
00146 TestContext *cxt = this->cxt;
00147 return cxt->g0 == this->target || cxt->g0 == cxt->iterations;
00148 }
00149
00150 static void TestAwait(TestContext *cxt, int c) {
00151 MyContext mc;
00152 mc.target = c;
00153 mc.cxt = cxt;
00154 absl::MutexLock l(&cxt->mu);
00155 cxt->mu.AssertHeld();
00156 while (cxt->g0 < cxt->iterations) {
00157 cxt->mu.Await(absl::Condition(&mc, &MyContext::MyTurn));
00158 ABSL_RAW_CHECK(mc.MyTurn(), "Error in TestAwait");
00159 cxt->mu.AssertHeld();
00160 if (cxt->g0 < cxt->iterations) {
00161 int a = cxt->g0 + 1;
00162 cxt->g0 = a;
00163 mc.target += cxt->threads;
00164 }
00165 }
00166 }
00167
00168 static void TestSignalAll(TestContext *cxt, int c) {
00169 int target = c;
00170 absl::MutexLock l(&cxt->mu);
00171 cxt->mu.AssertHeld();
00172 while (cxt->g0 < cxt->iterations) {
00173 while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
00174 cxt->cv.Wait(&cxt->mu);
00175 }
00176 if (cxt->g0 < cxt->iterations) {
00177 int a = cxt->g0 + 1;
00178 cxt->g0 = a;
00179 cxt->cv.SignalAll();
00180 target += cxt->threads;
00181 }
00182 }
00183 }
00184
00185 static void TestSignal(TestContext *cxt, int c) {
00186 ABSL_RAW_CHECK(cxt->threads == 2, "TestSignal should use 2 threads");
00187 int target = c;
00188 absl::MutexLock l(&cxt->mu);
00189 cxt->mu.AssertHeld();
00190 while (cxt->g0 < cxt->iterations) {
00191 while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
00192 cxt->cv.Wait(&cxt->mu);
00193 }
00194 if (cxt->g0 < cxt->iterations) {
00195 int a = cxt->g0 + 1;
00196 cxt->g0 = a;
00197 cxt->cv.Signal();
00198 target += cxt->threads;
00199 }
00200 }
00201 }
00202
00203 static void TestCVTimeout(TestContext *cxt, int c) {
00204 int target = c;
00205 absl::MutexLock l(&cxt->mu);
00206 cxt->mu.AssertHeld();
00207 while (cxt->g0 < cxt->iterations) {
00208 while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
00209 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));
00210 }
00211 if (cxt->g0 < cxt->iterations) {
00212 int a = cxt->g0 + 1;
00213 cxt->g0 = a;
00214 cxt->cv.SignalAll();
00215 target += cxt->threads;
00216 }
00217 }
00218 }
00219
00220 static bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; }
00221
00222 static void TestTime(TestContext *cxt, int c, bool use_cv) {
00223 ABSL_RAW_CHECK(cxt->iterations == 1, "TestTime should only use 1 iteration");
00224 ABSL_RAW_CHECK(cxt->threads > 2, "TestTime should use more than 2 threads");
00225 const bool kFalse = false;
00226 absl::Condition false_cond(&kFalse);
00227 absl::Condition g0ge2(G0GE2, cxt);
00228 if (c == 0) {
00229 absl::MutexLock l(&cxt->mu);
00230
00231 absl::Time start = absl::Now();
00232 if (use_cv) {
00233 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00234 } else {
00235 ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00236 "TestTime failed");
00237 }
00238 absl::Duration elapsed = absl::Now() - start;
00239 ABSL_RAW_CHECK(
00240 absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
00241 "TestTime failed");
00242 ABSL_RAW_CHECK(cxt->g0 == 1, "TestTime failed");
00243
00244 start = absl::Now();
00245 if (use_cv) {
00246 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00247 } else {
00248 ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00249 "TestTime failed");
00250 }
00251 elapsed = absl::Now() - start;
00252 ABSL_RAW_CHECK(
00253 absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
00254 "TestTime failed");
00255 cxt->g0++;
00256 if (use_cv) {
00257 cxt->cv.Signal();
00258 }
00259
00260 start = absl::Now();
00261 if (use_cv) {
00262 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(4));
00263 } else {
00264 ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(4)),
00265 "TestTime failed");
00266 }
00267 elapsed = absl::Now() - start;
00268 ABSL_RAW_CHECK(
00269 absl::Seconds(3.9) <= elapsed && elapsed <= absl::Seconds(6.0),
00270 "TestTime failed");
00271 ABSL_RAW_CHECK(cxt->g0 >= 3, "TestTime failed");
00272
00273 start = absl::Now();
00274 if (use_cv) {
00275 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00276 } else {
00277 ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00278 "TestTime failed");
00279 }
00280 elapsed = absl::Now() - start;
00281 ABSL_RAW_CHECK(
00282 absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
00283 "TestTime failed");
00284 if (use_cv) {
00285 cxt->cv.SignalAll();
00286 }
00287
00288 start = absl::Now();
00289 if (use_cv) {
00290 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00291 } else {
00292 ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00293 "TestTime failed");
00294 }
00295 elapsed = absl::Now() - start;
00296 ABSL_RAW_CHECK(absl::Seconds(0.9) <= elapsed &&
00297 elapsed <= absl::Seconds(2.0), "TestTime failed");
00298 ABSL_RAW_CHECK(cxt->g0 == cxt->threads, "TestTime failed");
00299
00300 } else if (c == 1) {
00301 absl::MutexLock l(&cxt->mu);
00302 const absl::Time start = absl::Now();
00303 if (use_cv) {
00304 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Milliseconds(500));
00305 } else {
00306 ABSL_RAW_CHECK(
00307 !cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)),
00308 "TestTime failed");
00309 }
00310 const absl::Duration elapsed = absl::Now() - start;
00311 ABSL_RAW_CHECK(
00312 absl::Seconds(0.4) <= elapsed && elapsed <= absl::Seconds(0.9),
00313 "TestTime failed");
00314 cxt->g0++;
00315 } else if (c == 2) {
00316 absl::MutexLock l(&cxt->mu);
00317 if (use_cv) {
00318 while (cxt->g0 < 2) {
00319 cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));
00320 }
00321 } else {
00322 ABSL_RAW_CHECK(cxt->mu.AwaitWithTimeout(g0ge2, absl::Seconds(100)),
00323 "TestTime failed");
00324 }
00325 cxt->g0++;
00326 } else {
00327 absl::MutexLock l(&cxt->mu);
00328 if (use_cv) {
00329 while (cxt->g0 < 2) {
00330 cxt->cv.Wait(&cxt->mu);
00331 }
00332 } else {
00333 cxt->mu.Await(g0ge2);
00334 }
00335 cxt->g0++;
00336 }
00337 }
00338
00339 static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }
00340
00341 static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }
00342
00343 static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,
00344 const std::function<void(int)>& cb) {
00345 mu->Lock();
00346 int c = (*c0)++;
00347 mu->Unlock();
00348 cb(c);
00349 absl::MutexLock l(mu);
00350 (*c1)++;
00351 cv->Signal();
00352 }
00353
00354
00355 static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),
00356 int threads, int iterations, int operations) {
00357 absl::Mutex mu2;
00358 absl::CondVar cv2;
00359 int c0 = 0;
00360 int c1 = 0;
00361 cxt->g0 = 0;
00362 cxt->g1 = 0;
00363 cxt->iterations = iterations;
00364 cxt->threads = threads;
00365 absl::synchronization_internal::ThreadPool tp(threads);
00366 for (int i = 0; i != threads; i++) {
00367 tp.Schedule(std::bind(&EndTest, &c0, &c1, &mu2, &cv2,
00368 std::function<void(int)>(
00369 std::bind(test, cxt, std::placeholders::_1))));
00370 }
00371 mu2.Lock();
00372 while (c1 != threads) {
00373 cv2.Wait(&mu2);
00374 }
00375 mu2.Unlock();
00376 return cxt->g0;
00377 }
00378
00379
00380 static int RunTest(void (*test)(TestContext *cxt, int), int threads,
00381 int iterations, int operations) {
00382 TestContext cxt;
00383 return RunTestCommon(&cxt, test, threads, iterations, operations);
00384 }
00385
00386
00387
00388
00389
00390 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
00391 static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),
00392 int threads, int iterations,
00393 int operations,
00394 void (*invariant)(void *)) {
00395 absl::EnableMutexInvariantDebugging(true);
00396 SetInvariantChecked(false);
00397 TestContext cxt;
00398 cxt.mu.EnableInvariantDebugging(invariant, &cxt);
00399 int ret = RunTestCommon(&cxt, test, threads, iterations, operations);
00400 ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked");
00401 absl::EnableMutexInvariantDebugging(false);
00402 return ret;
00403 }
00404 #endif
00405
00406
00407
00408 struct TimeoutBugStruct {
00409 absl::Mutex mu;
00410 bool a;
00411 int a_waiter_count;
00412 };
00413
00414 static void WaitForA(TimeoutBugStruct *x) {
00415 x->mu.LockWhen(absl::Condition(&x->a));
00416 x->a_waiter_count--;
00417 x->mu.Unlock();
00418 }
00419
00420 static bool NoAWaiters(TimeoutBugStruct *x) { return x->a_waiter_count == 0; }
00421
00422
00423
00424 TEST(Mutex, CondVarWaitSignalsAwait) {
00425
00426 struct {
00427 absl::Mutex barrier_mu;
00428 bool barrier GUARDED_BY(barrier_mu) = false;
00429
00430 absl::Mutex release_mu;
00431 bool release GUARDED_BY(release_mu) = false;
00432 absl::CondVar released_cv;
00433 } state;
00434
00435 auto pool = CreateDefaultPool();
00436
00437
00438
00439 pool->Schedule([&state] {
00440 state.release_mu.Lock();
00441
00442 state.barrier_mu.Lock();
00443 state.barrier = true;
00444 state.barrier_mu.Unlock();
00445
00446 state.release_mu.Await(absl::Condition(&state.release));
00447 state.released_cv.Signal();
00448 state.release_mu.Unlock();
00449 });
00450
00451 state.barrier_mu.LockWhen(absl::Condition(&state.barrier));
00452 state.barrier_mu.Unlock();
00453 state.release_mu.Lock();
00454
00455
00456
00457
00458 state.release = true;
00459 state.released_cv.Wait(&state.release_mu);
00460 state.release_mu.Unlock();
00461 }
00462
00463
00464
00465 TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {
00466
00467 struct {
00468 absl::Mutex barrier_mu;
00469 bool barrier GUARDED_BY(barrier_mu) = false;
00470
00471 absl::Mutex release_mu;
00472 bool release GUARDED_BY(release_mu) = false;
00473 absl::CondVar released_cv;
00474 } state;
00475
00476 auto pool = CreateDefaultPool();
00477
00478
00479
00480 pool->Schedule([&state] {
00481 state.release_mu.Lock();
00482
00483 state.barrier_mu.Lock();
00484 state.barrier = true;
00485 state.barrier_mu.Unlock();
00486
00487 state.release_mu.Await(absl::Condition(&state.release));
00488 state.released_cv.Signal();
00489 state.release_mu.Unlock();
00490 });
00491
00492 state.barrier_mu.LockWhen(absl::Condition(&state.barrier));
00493 state.barrier_mu.Unlock();
00494 state.release_mu.Lock();
00495
00496
00497
00498
00499 state.release = true;
00500 EXPECT_TRUE(
00501 !state.released_cv.WaitWithTimeout(&state.release_mu, absl::Seconds(10)))
00502 << "; Unrecoverable test failure: CondVar::WaitWithTimeout did not "
00503 "unblock the absl::Mutex::Await call in another thread.";
00504
00505 state.release_mu.Unlock();
00506 }
00507
00508
00509 TEST(Mutex, MutexTimeoutBug) {
00510 auto tp = CreateDefaultPool();
00511
00512 TimeoutBugStruct x;
00513 x.a = false;
00514 x.a_waiter_count = 2;
00515 tp->Schedule(std::bind(&WaitForA, &x));
00516 tp->Schedule(std::bind(&WaitForA, &x));
00517 absl::SleepFor(absl::Seconds(1));
00518
00519
00520
00521
00522
00523 bool always_false = false;
00524 x.mu.LockWhenWithTimeout(absl::Condition(&always_false),
00525 absl::Milliseconds(500));
00526
00527
00528
00529 x.a = true;
00530 x.mu.Await(absl::Condition(&NoAWaiters, &x));
00531 x.mu.Unlock();
00532 }
00533
00534 struct CondVarWaitDeadlock : testing::TestWithParam<int> {
00535 absl::Mutex mu;
00536 absl::CondVar cv;
00537 bool cond1 = false;
00538 bool cond2 = false;
00539 bool read_lock1;
00540 bool read_lock2;
00541 bool signal_unlocked;
00542
00543 CondVarWaitDeadlock() {
00544 read_lock1 = GetParam() & (1 << 0);
00545 read_lock2 = GetParam() & (1 << 1);
00546 signal_unlocked = GetParam() & (1 << 2);
00547 }
00548
00549 void Waiter1() {
00550 if (read_lock1) {
00551 mu.ReaderLock();
00552 while (!cond1) {
00553 cv.Wait(&mu);
00554 }
00555 mu.ReaderUnlock();
00556 } else {
00557 mu.Lock();
00558 while (!cond1) {
00559 cv.Wait(&mu);
00560 }
00561 mu.Unlock();
00562 }
00563 }
00564
00565 void Waiter2() {
00566 if (read_lock2) {
00567 mu.ReaderLockWhen(absl::Condition(&cond2));
00568 mu.ReaderUnlock();
00569 } else {
00570 mu.LockWhen(absl::Condition(&cond2));
00571 mu.Unlock();
00572 }
00573 }
00574 };
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 TEST_P(CondVarWaitDeadlock, Test) {
00586 auto waiter1 = CreatePool(1);
00587 auto waiter2 = CreatePool(1);
00588 waiter1->Schedule([this] { this->Waiter1(); });
00589 waiter2->Schedule([this] { this->Waiter2(); });
00590
00591
00592 absl::SleepFor(absl::Milliseconds(100));
00593
00594
00595 mu.Lock();
00596 cond1 = true;
00597 if (signal_unlocked) {
00598 mu.Unlock();
00599 cv.Signal();
00600 } else {
00601 cv.Signal();
00602 mu.Unlock();
00603 }
00604 waiter1.reset();
00605
00606
00607 mu.Lock();
00608 cond2 = true;
00609 mu.Unlock();
00610 waiter2.reset();
00611 }
00612
00613 INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
00614 ::testing::Range(0, 8),
00615 ::testing::PrintToStringParamName());
00616
00617
00618
00619
00620
00621
00622
00623 struct DequeueAllWakeableBugStruct {
00624 absl::Mutex mu;
00625 absl::Mutex mu2;
00626 int unfinished_count;
00627 bool done1;
00628 int finished_count;
00629 bool done2;
00630 };
00631
00632
00633 static void AcquireAsReader(DequeueAllWakeableBugStruct *x) {
00634 x->mu.ReaderLock();
00635 x->mu2.Lock();
00636 x->unfinished_count--;
00637 x->done1 = (x->unfinished_count == 0);
00638 x->mu2.Unlock();
00639
00640 absl::SleepFor(absl::Seconds(2));
00641 x->mu.ReaderUnlock();
00642
00643 x->mu2.Lock();
00644 x->finished_count--;
00645 x->done2 = (x->finished_count == 0);
00646 x->mu2.Unlock();
00647 }
00648
00649
00650 TEST(Mutex, MutexReaderWakeupBug) {
00651 auto tp = CreateDefaultPool();
00652
00653 DequeueAllWakeableBugStruct x;
00654 x.unfinished_count = 2;
00655 x.done1 = false;
00656 x.finished_count = 2;
00657 x.done2 = false;
00658 x.mu.Lock();
00659
00660 tp->Schedule(std::bind(&AcquireAsReader, &x));
00661 tp->Schedule(std::bind(&AcquireAsReader, &x));
00662 absl::SleepFor(absl::Seconds(1));
00663 x.mu.Unlock();
00664
00665
00666 EXPECT_TRUE(
00667 x.mu2.LockWhenWithTimeout(absl::Condition(&x.done1), absl::Seconds(10)));
00668 x.mu2.Unlock();
00669
00670 EXPECT_TRUE(
00671 x.mu2.LockWhenWithTimeout(absl::Condition(&x.done2), absl::Seconds(10)));
00672 x.mu2.Unlock();
00673 }
00674
00675 struct LockWhenTestStruct {
00676 absl::Mutex mu1;
00677 bool cond = false;
00678
00679 absl::Mutex mu2;
00680 bool waiting = false;
00681 };
00682
00683 static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
00684 s->mu2.Lock();
00685 s->waiting = true;
00686 s->mu2.Unlock();
00687 return s->cond;
00688 }
00689
00690 static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
00691 s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));
00692 s->mu1.Unlock();
00693 }
00694
00695 TEST(Mutex, LockWhen) {
00696 LockWhenTestStruct s;
00697
00698 std::thread t(LockWhenTestWaitForIsCond, &s);
00699 s.mu2.LockWhen(absl::Condition(&s.waiting));
00700 s.mu2.Unlock();
00701
00702 s.mu1.Lock();
00703 s.cond = true;
00704 s.mu1.Unlock();
00705
00706 t.join();
00707 }
00708
00709
00710
00711
00712 #if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 struct ReaderDecrementBugStruct {
00724 bool cond;
00725 int done;
00726 absl::Mutex mu;
00727
00728 bool waiting_on_cond;
00729 bool have_reader_lock;
00730 bool complete;
00731 absl::Mutex mu2;
00732 };
00733
00734
00735 static bool IsCond(void *v) {
00736 ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
00737 x->mu2.Lock();
00738 x->waiting_on_cond = true;
00739 x->mu2.Unlock();
00740 return x->cond;
00741 }
00742
00743
00744 static bool AllDone(void *v) {
00745 ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
00746 return x->done == 0;
00747 }
00748
00749
00750 static void WaitForCond(ReaderDecrementBugStruct *x) {
00751 absl::Mutex dummy;
00752 absl::MutexLock l(&dummy);
00753 x->mu.LockWhen(absl::Condition(&IsCond, x));
00754 x->done--;
00755 x->mu.Unlock();
00756 }
00757
00758
00759 static void GetReadLock(ReaderDecrementBugStruct *x) {
00760 x->mu.ReaderLock();
00761 x->mu2.Lock();
00762 x->have_reader_lock = true;
00763 x->mu2.Await(absl::Condition(&x->complete));
00764 x->mu2.Unlock();
00765 x->mu.ReaderUnlock();
00766 x->mu.Lock();
00767 x->done--;
00768 x->mu.Unlock();
00769 }
00770
00771
00772
00773 TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
00774 ReaderDecrementBugStruct x;
00775 x.cond = false;
00776 x.waiting_on_cond = false;
00777 x.have_reader_lock = false;
00778 x.complete = false;
00779 x.done = 2;
00780
00781
00782 std::thread thread1(WaitForCond, &x);
00783 x.mu2.LockWhen(absl::Condition(&x.waiting_on_cond));
00784 x.mu2.Unlock();
00785
00786
00787 std::thread thread2(GetReadLock, &x);
00788 x.mu2.LockWhen(absl::Condition(&x.have_reader_lock));
00789 x.mu2.Unlock();
00790
00791
00792 x.mu.ReaderLock();
00793 x.mu.ReaderUnlock();
00794
00795
00796
00797 x.mu.AssertReaderHeld();
00798
00799
00800 x.mu2.Lock();
00801 x.complete = true;
00802 x.mu2.Unlock();
00803
00804
00805
00806 x.mu.Lock();
00807 x.cond = true;
00808 x.mu.Await(absl::Condition(&AllDone, &x));
00809 x.mu.Unlock();
00810
00811 thread1.join();
00812 thread2.join();
00813 }
00814 #endif // !ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
00815
00816
00817
00818 #ifdef THREAD_SANITIZER
00819
00820 TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
00821 #else
00822 TEST(Mutex, LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
00823 #endif
00824 for (int i = 0; i != 10; i++) {
00825
00826 const int kNumLocks = 10;
00827 auto mu = absl::make_unique<absl::Mutex[]>(kNumLocks);
00828 for (int j = 0; j != kNumLocks; j++) {
00829 if ((j % 2) == 0) {
00830 mu[j].WriterLock();
00831 } else {
00832 mu[j].ReaderLock();
00833 }
00834 }
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
00850 int *running) {
00851 std::random_device dev;
00852 std::mt19937 gen(dev());
00853 std::uniform_int_distribution<int> random_millis(0, 15);
00854 mu->ReaderLock();
00855 while (*running == 3) {
00856 absl::SleepFor(absl::Milliseconds(random_millis(gen)));
00857 cv->WaitWithTimeout(mu, absl::Milliseconds(random_millis(gen)));
00858 }
00859 mu->ReaderUnlock();
00860 mu->Lock();
00861 (*running)--;
00862 mu->Unlock();
00863 }
00864
00865 struct True {
00866 template <class... Args>
00867 bool operator()(Args...) const {
00868 return true;
00869 }
00870 };
00871
00872 struct DerivedTrue : True {};
00873
00874 TEST(Mutex, FunctorCondition) {
00875 {
00876 True f;
00877 EXPECT_TRUE(absl::Condition(&f).Eval());
00878 }
00879
00880 {
00881 DerivedTrue g;
00882 EXPECT_TRUE(absl::Condition(&g).Eval());
00883 }
00884
00885 {
00886 int value = 3;
00887 auto is_zero = [&value] { return value == 0; };
00888 absl::Condition c(&is_zero);
00889 EXPECT_FALSE(c.Eval());
00890 value = 0;
00891 EXPECT_TRUE(c.Eval());
00892 }
00893
00894 {
00895 int value = 0;
00896 auto is_positive = std::bind(std::less<int>(), 0, std::cref(value));
00897 absl::Condition c(&is_positive);
00898 EXPECT_FALSE(c.Eval());
00899 value = 1;
00900 EXPECT_TRUE(c.Eval());
00901 }
00902
00903 {
00904 int value = 3;
00905 std::function<bool()> is_zero = [&value] { return value == 0; };
00906 absl::Condition c(&is_zero);
00907 EXPECT_FALSE(c.Eval());
00908 value = 0;
00909 EXPECT_TRUE(c.Eval());
00910 }
00911 }
00912
00913 static bool IntIsZero(int *x) { return *x == 0; }
00914
00915
00916
00917 TEST(Mutex, TestReaderOnCondVar) {
00918 auto tp = CreateDefaultPool();
00919 absl::Mutex mu;
00920 absl::CondVar cv;
00921 int running = 3;
00922 tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
00923 tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
00924 absl::SleepFor(absl::Seconds(2));
00925 mu.Lock();
00926 running--;
00927 mu.Await(absl::Condition(&IntIsZero, &running));
00928 mu.Unlock();
00929 }
00930
00931
00932 struct AcquireFromConditionStruct {
00933 absl::Mutex mu0;
00934 int value;
00935 bool done;
00936 absl::Mutex mu1;
00937 absl::CondVar cv;
00938
00939 };
00940
00941 static bool ConditionWithAcquire(AcquireFromConditionStruct *x) {
00942 x->value++;
00943
00944 if (x->value == 2 || x->value == 3) {
00945
00946
00947
00948
00949 bool always_false = false;
00950 x->mu1.LockWhenWithTimeout(absl::Condition(&always_false),
00951 absl::Milliseconds(100));
00952 x->mu1.Unlock();
00953 }
00954 ABSL_RAW_CHECK(x->value < 4, "should not be invoked a fourth time");
00955
00956
00957 return x->value == 2 || x->value == 3;
00958 }
00959
00960 static void WaitForCond2(AcquireFromConditionStruct *x) {
00961
00962 x->mu0.LockWhen(absl::Condition(&ConditionWithAcquire, x));
00963 x->done = true;
00964 x->mu0.Unlock();
00965 }
00966
00967
00968 TEST(Mutex, AcquireFromCondition) {
00969 auto tp = CreateDefaultPool();
00970
00971 AcquireFromConditionStruct x;
00972 x.value = 0;
00973 x.done = false;
00974 tp->Schedule(
00975 std::bind(&WaitForCond2, &x));
00976
00977
00978 absl::SleepFor(absl::Milliseconds(500));
00979
00980 x.mu0.Lock();
00981 x.cv.WaitWithTimeout(&x.mu0, absl::Milliseconds(500));
00982
00983
00984
00985 x.mu0.Unlock();
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 x.mu0.LockWhen(absl::Condition(&x.done));
01001 x.mu0.Unlock();
01002 }
01003
01004
01005 #if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
01006
01007 TEST(Mutex, DeadlockDetector) {
01008 absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01009
01010
01011 absl::Mutex m1;
01012 absl::Mutex m2;
01013 absl::Mutex m3;
01014 absl::Mutex m4;
01015
01016 m1.Lock();
01017 m2.Lock();
01018 m3.Lock();
01019 m3.Unlock();
01020 m2.Unlock();
01021
01022 m1.ForgetDeadlockInfo();
01023 m2.Lock();
01024 m3.Lock();
01025 m4.Lock();
01026 m3.Unlock();
01027 m2.Unlock();
01028 m4.Unlock();
01029 m1.Unlock();
01030 }
01031
01032
01033
01034
01035 class ScopedDisableBazelTestWarnings {
01036 public:
01037 ScopedDisableBazelTestWarnings() {
01038 #ifdef WIN32
01039 char file[MAX_PATH];
01040 if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
01041 warnings_output_file_ = file;
01042 SetEnvironmentVariableA(kVarName, nullptr);
01043 }
01044 #else
01045 const char *file = getenv(kVarName);
01046 if (file != nullptr) {
01047 warnings_output_file_ = file;
01048 unsetenv(kVarName);
01049 }
01050 #endif
01051 }
01052
01053 ~ScopedDisableBazelTestWarnings() {
01054 if (!warnings_output_file_.empty()) {
01055 #ifdef WIN32
01056 SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
01057 #else
01058 setenv(kVarName, warnings_output_file_.c_str(), 0);
01059 #endif
01060 }
01061 }
01062
01063 private:
01064 static const char kVarName[];
01065 std::string warnings_output_file_;
01066 };
01067 const char ScopedDisableBazelTestWarnings::kVarName[] =
01068 "TEST_WARNINGS_OUTPUT_FILE";
01069
01070 #ifdef THREAD_SANITIZER
01071
01072 TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
01073 #else
01074 TEST(Mutex, DeadlockDetectorBazelWarning) {
01075 #endif
01076 absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);
01077
01078
01079
01080 ScopedDisableBazelTestWarnings disable_bazel_test_warnings;
01081
01082 absl::Mutex mu0;
01083 absl::Mutex mu1;
01084 bool got_mu0 = mu0.TryLock();
01085 mu1.Lock();
01086 if (got_mu0) {
01087 mu0.Unlock();
01088 }
01089 if (mu0.TryLock()) {
01090 mu0.Unlock();
01091 }
01092 mu0.Lock();
01093
01094 mu0.Unlock();
01095 mu1.Unlock();
01096
01097 absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01098 }
01099
01100
01101
01102
01103
01104 TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
01105
01106
01107
01108 const int n_locks = 1 << 17;
01109 auto array_of_locks = absl::make_unique<absl::Mutex[]>(n_locks);
01110 for (int i = 0; i < n_locks; i++) {
01111 int end = std::min(n_locks, i + 5);
01112
01113 for (int j = i; j < end; j++) {
01114 array_of_locks[j].Lock();
01115 }
01116 for (int j = i; j < end; j++) {
01117 array_of_locks[j].Unlock();
01118 }
01119 }
01120 }
01121
01122 #ifdef THREAD_SANITIZER
01123
01124 TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
01125 #else
01126 TEST(Mutex, DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
01127 #endif
01128
01129
01130
01131 absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01132
01133 absl::Mutex *a = new absl::Mutex;
01134
01135 absl::Mutex b, c;
01136
01137
01138 a->Lock();
01139
01140
01141 b.Lock();
01142 b.Unlock();
01143
01144
01145
01146
01147
01148
01149 absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
01150 delete a;
01151 absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01152
01153
01154
01155
01156
01157 c.Lock();
01158 c.Unlock();
01159 }
01160 #endif // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
01161
01162
01163
01164
01165
01166
01167
01168
01169 static absl::Duration TimeoutTestAllowedSchedulingDelay() {
01170
01171
01172 return absl::Milliseconds(150);
01173 }
01174
01175
01176
01177 ABSL_MUST_USE_RESULT
01178 static bool DelayIsWithinBounds(absl::Duration expected_delay,
01179 absl::Duration actual_delay) {
01180 bool pass = true;
01181
01182
01183
01184
01185 if (actual_delay < expected_delay) {
01186 ABSL_RAW_LOG(WARNING,
01187 "Actual delay %s was too short, expected %s (difference %s)",
01188 absl::FormatDuration(actual_delay).c_str(),
01189 absl::FormatDuration(expected_delay).c_str(),
01190 absl::FormatDuration(actual_delay - expected_delay).c_str());
01191 pass = false;
01192 }
01193
01194
01195
01196
01197 absl::Duration tolerance = expected_delay <= absl::ZeroDuration()
01198 ? absl::Milliseconds(10)
01199 : TimeoutTestAllowedSchedulingDelay();
01200 if (actual_delay > expected_delay + tolerance) {
01201 ABSL_RAW_LOG(WARNING,
01202 "Actual delay %s was too long, expected %s (difference %s)",
01203 absl::FormatDuration(actual_delay).c_str(),
01204 absl::FormatDuration(expected_delay).c_str(),
01205 absl::FormatDuration(actual_delay - expected_delay).c_str());
01206 pass = false;
01207 }
01208 return pass;
01209 }
01210
01211
01212 struct TimeoutTestParam {
01213
01214 const char *from_file;
01215 int from_line;
01216
01217
01218
01219 bool use_absolute_deadline;
01220
01221
01222
01223 absl::Duration wait_timeout;
01224
01225
01226
01227
01228
01229
01230 absl::Duration satisfy_condition_delay;
01231
01232
01233
01234
01235 bool expected_result;
01236
01237
01238
01239
01240 absl::Duration expected_delay;
01241 };
01242
01243
01244 std::ostream &operator<<(std::ostream &os, const TimeoutTestParam ¶m) {
01245 return os << "from: " << param.from_file << ":" << param.from_line
01246 << " use_absolute_deadline: "
01247 << (param.use_absolute_deadline ? "true" : "false")
01248 << " wait_timeout: " << param.wait_timeout
01249 << " satisfy_condition_delay: " << param.satisfy_condition_delay
01250 << " expected_result: "
01251 << (param.expected_result ? "true" : "false")
01252 << " expected_delay: " << param.expected_delay;
01253 }
01254
01255 std::string FormatString(const TimeoutTestParam ¶m) {
01256 std::ostringstream os;
01257 os << param;
01258 return os.str();
01259 }
01260
01261
01262
01263
01264
01265 static void RunAfterDelay(absl::Duration delay,
01266 absl::synchronization_internal::ThreadPool *pool,
01267 const std::function<void()> &callback) {
01268 if (delay <= absl::ZeroDuration()) {
01269 callback();
01270 } else if (delay != absl::InfiniteDuration()) {
01271 ScheduleAfter(pool, delay, callback);
01272 }
01273 }
01274
01275 class TimeoutTest : public ::testing::Test,
01276 public ::testing::WithParamInterface<TimeoutTestParam> {};
01277
01278 std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {
01279
01280
01281
01282 const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay();
01283 const absl::Duration never = absl::InfiniteDuration();
01284 const absl::Duration negative = -absl::InfiniteDuration();
01285 const absl::Duration immediate = absl::ZeroDuration();
01286
01287
01288
01289 std::vector<TimeoutTestParam> values;
01290 for (bool use_absolute_deadline : {false, true}) {
01291
01292
01293
01294
01295 values.push_back(TimeoutTestParam{
01296 __FILE__, __LINE__, use_absolute_deadline,
01297 negative,
01298 immediate,
01299 true,
01300 immediate,
01301 });
01302
01303
01304 values.push_back(TimeoutTestParam{
01305 __FILE__, __LINE__, use_absolute_deadline,
01306 negative,
01307 finite,
01308 false,
01309 immediate
01310 });
01311
01312
01313 values.push_back(TimeoutTestParam{
01314 __FILE__, __LINE__, use_absolute_deadline,
01315 negative,
01316 never,
01317 false,
01318 immediate
01319 });
01320
01321
01322
01323
01324
01325 values.push_back(TimeoutTestParam{
01326 __FILE__, __LINE__, use_absolute_deadline,
01327 never,
01328 immediate,
01329 true,
01330 immediate
01331 });
01332
01333
01334 values.push_back(TimeoutTestParam{
01335 __FILE__, __LINE__, use_absolute_deadline,
01336 never,
01337 finite,
01338 true,
01339 finite,
01340 });
01341
01342
01343
01344
01345
01346 values.push_back(TimeoutTestParam{
01347 __FILE__, __LINE__, use_absolute_deadline,
01348 never,
01349 immediate,
01350 true,
01351 immediate
01352 });
01353
01354
01355 values.push_back(TimeoutTestParam{
01356 __FILE__, __LINE__, use_absolute_deadline,
01357 finite * 2,
01358 finite,
01359 true,
01360 finite
01361 });
01362
01363
01364 values.push_back(TimeoutTestParam{
01365 __FILE__, __LINE__, use_absolute_deadline,
01366 finite,
01367 finite * 2,
01368 false,
01369 finite
01370 });
01371
01372
01373 values.push_back(TimeoutTestParam{
01374 __FILE__, __LINE__, use_absolute_deadline,
01375 finite,
01376 never,
01377 false,
01378 finite
01379 });
01380 }
01381 return values;
01382 }
01383
01384
01385 INSTANTIATE_TEST_SUITE_P(All, TimeoutTest,
01386 testing::ValuesIn(MakeTimeoutTestParamValues()));
01387
01388 TEST_P(TimeoutTest, Await) {
01389 const TimeoutTestParam params = GetParam();
01390 ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01391
01392
01393
01394
01395 for (int attempt = 1;; ++attempt) {
01396 ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01397
01398 absl::Mutex mu;
01399 bool value = false;
01400
01401 std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01402 CreateDefaultPool();
01403 RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01404 absl::MutexLock l(&mu);
01405 value = true;
01406 });
01407
01408 absl::MutexLock lock(&mu);
01409 absl::Time start_time = absl::Now();
01410 absl::Condition cond(&value);
01411 bool result =
01412 params.use_absolute_deadline
01413 ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout)
01414 : mu.AwaitWithTimeout(cond, params.wait_timeout);
01415 if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01416 EXPECT_EQ(params.expected_result, result);
01417 break;
01418 }
01419 }
01420 }
01421
01422 TEST_P(TimeoutTest, LockWhen) {
01423 const TimeoutTestParam params = GetParam();
01424 ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01425
01426
01427
01428
01429 for (int attempt = 1;; ++attempt) {
01430 ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01431
01432 absl::Mutex mu;
01433 bool value = false;
01434
01435 std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01436 CreateDefaultPool();
01437 RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01438 absl::MutexLock l(&mu);
01439 value = true;
01440 });
01441
01442 absl::Time start_time = absl::Now();
01443 absl::Condition cond(&value);
01444 bool result =
01445 params.use_absolute_deadline
01446 ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout)
01447 : mu.LockWhenWithTimeout(cond, params.wait_timeout);
01448 mu.Unlock();
01449
01450 if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01451 EXPECT_EQ(params.expected_result, result);
01452 break;
01453 }
01454 }
01455 }
01456
01457 TEST_P(TimeoutTest, ReaderLockWhen) {
01458 const TimeoutTestParam params = GetParam();
01459 ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01460
01461
01462
01463
01464 for (int attempt = 0;; ++attempt) {
01465 ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01466
01467 absl::Mutex mu;
01468 bool value = false;
01469
01470 std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01471 CreateDefaultPool();
01472 RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01473 absl::MutexLock l(&mu);
01474 value = true;
01475 });
01476
01477 absl::Time start_time = absl::Now();
01478 bool result =
01479 params.use_absolute_deadline
01480 ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value),
01481 start_time + params.wait_timeout)
01482 : mu.ReaderLockWhenWithTimeout(absl::Condition(&value),
01483 params.wait_timeout);
01484 mu.ReaderUnlock();
01485
01486 if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01487 EXPECT_EQ(params.expected_result, result);
01488 break;
01489 }
01490 }
01491 }
01492
01493 TEST_P(TimeoutTest, Wait) {
01494 const TimeoutTestParam params = GetParam();
01495 ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01496
01497
01498
01499
01500 for (int attempt = 0;; ++attempt) {
01501 ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01502
01503 absl::Mutex mu;
01504 bool value = false;
01505 absl::CondVar cv;
01506
01507 std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01508 CreateDefaultPool();
01509 RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01510 absl::MutexLock l(&mu);
01511 value = true;
01512 cv.Signal();
01513 });
01514
01515 absl::MutexLock lock(&mu);
01516 absl::Time start_time = absl::Now();
01517 absl::Duration timeout = params.wait_timeout;
01518 absl::Time deadline = start_time + timeout;
01519 while (!value) {
01520 if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline)
01521 : cv.WaitWithTimeout(&mu, timeout)) {
01522 break;
01523 }
01524 timeout = deadline - absl::Now();
01525 }
01526 bool result = value;
01527
01528 if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01529 EXPECT_EQ(params.expected_result, result);
01530 break;
01531 }
01532 }
01533 }
01534
01535 TEST(Mutex, Logging) {
01536
01537 absl::Mutex logged_mutex;
01538 logged_mutex.EnableDebugLog("fido_mutex");
01539 absl::CondVar logged_cv;
01540 logged_cv.EnableDebugLog("rover_cv");
01541 logged_mutex.Lock();
01542 logged_cv.WaitWithTimeout(&logged_mutex, absl::Milliseconds(20));
01543 logged_mutex.Unlock();
01544 logged_mutex.ReaderLock();
01545 logged_mutex.ReaderUnlock();
01546 logged_mutex.Lock();
01547 logged_mutex.Unlock();
01548 logged_cv.Signal();
01549 logged_cv.SignalAll();
01550 }
01551
01552
01553
01554
01555 static std::vector<int> AllThreadCountValues() {
01556 if (kExtendedTest) {
01557 return {2, 4, 8, 10, 16, 20, 24, 30, 32};
01558 }
01559 return {2, 4, 10};
01560 }
01561
01562
01563 class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};
01564
01565
01566 INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,
01567 ::testing::ValuesIn(AllThreadCountValues()),
01568 ::testing::PrintToStringParamName());
01569
01570
01571
01572 static int ScaleIterations(int x) {
01573
01574
01575
01576 #if defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
01577 return x / 10;
01578 #else
01579 return x;
01580 #endif
01581 }
01582
01583 TEST_P(MutexVariableThreadCountTest, Mutex) {
01584 int threads = GetParam();
01585 int iterations = ScaleIterations(10000000) / threads;
01586 int operations = threads * iterations;
01587 EXPECT_EQ(RunTest(&TestMu, threads, iterations, operations), operations);
01588 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
01589 iterations = std::min(iterations, 10);
01590 operations = threads * iterations;
01591 EXPECT_EQ(RunTestWithInvariantDebugging(&TestMu, threads, iterations,
01592 operations, CheckSumG0G1),
01593 operations);
01594 #endif
01595 }
01596
01597 TEST_P(MutexVariableThreadCountTest, Try) {
01598 int threads = GetParam();
01599 int iterations = 1000000 / threads;
01600 int operations = iterations * threads;
01601 EXPECT_EQ(RunTest(&TestTry, threads, iterations, operations), operations);
01602 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
01603 iterations = std::min(iterations, 10);
01604 operations = threads * iterations;
01605 EXPECT_EQ(RunTestWithInvariantDebugging(&TestTry, threads, iterations,
01606 operations, CheckSumG0G1),
01607 operations);
01608 #endif
01609 }
01610
01611 TEST_P(MutexVariableThreadCountTest, R20ms) {
01612 int threads = GetParam();
01613 int iterations = 100;
01614 int operations = iterations * threads;
01615 EXPECT_EQ(RunTest(&TestR20ms, threads, iterations, operations), 0);
01616 }
01617
01618 TEST_P(MutexVariableThreadCountTest, RW) {
01619 int threads = GetParam();
01620 int iterations = ScaleIterations(20000000) / threads;
01621 int operations = iterations * threads;
01622 EXPECT_EQ(RunTest(&TestRW, threads, iterations, operations), operations / 2);
01623 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
01624 iterations = std::min(iterations, 10);
01625 operations = threads * iterations;
01626 EXPECT_EQ(RunTestWithInvariantDebugging(&TestRW, threads, iterations,
01627 operations, CheckSumG0G1),
01628 operations / 2);
01629 #endif
01630 }
01631
01632 TEST_P(MutexVariableThreadCountTest, Await) {
01633 int threads = GetParam();
01634 int iterations = ScaleIterations(500000);
01635 int operations = iterations;
01636 EXPECT_EQ(RunTest(&TestAwait, threads, iterations, operations), operations);
01637 }
01638
01639 TEST_P(MutexVariableThreadCountTest, SignalAll) {
01640 int threads = GetParam();
01641 int iterations = 200000 / threads;
01642 int operations = iterations;
01643 EXPECT_EQ(RunTest(&TestSignalAll, threads, iterations, operations),
01644 operations);
01645 }
01646
01647 TEST(Mutex, Signal) {
01648 int threads = 2;
01649 int iterations = 200000;
01650 int operations = iterations;
01651 EXPECT_EQ(RunTest(&TestSignal, threads, iterations, operations), operations);
01652 }
01653
01654 TEST(Mutex, Timed) {
01655 int threads = 10;
01656 int iterations = 1000;
01657 int operations = iterations;
01658 EXPECT_EQ(RunTest(&TestCVTimeout, threads, iterations, operations),
01659 operations);
01660 }
01661
01662 TEST(Mutex, CVTime) {
01663 int threads = 10;
01664 int iterations = 1;
01665 EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1),
01666 threads * iterations);
01667 }
01668
01669 TEST(Mutex, MuTime) {
01670 int threads = 10;
01671 int iterations = 1;
01672 EXPECT_EQ(RunTest(&TestMuTime, threads, iterations, 1), threads * iterations);
01673 }
01674
01675 }