mutex_test.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #ifdef WIN32
18 #include <windows.h>
19 #endif
20 
21 #include <algorithm>
22 #include <atomic>
23 #include <cstdlib>
24 #include <functional>
25 #include <memory>
26 #include <random>
27 #include <string>
28 #include <thread> // NOLINT(build/c++11)
29 #include <vector>
30 
31 #include "gtest/gtest.h"
32 #include "absl/base/attributes.h"
35 #include "absl/memory/memory.h"
37 #include "absl/time/clock.h"
38 #include "absl/time/time.h"
39 
40 namespace {
41 
42 // TODO(dmauro): Replace with a commandline flag.
43 static constexpr bool kExtendedTest = false;
44 
45 std::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool(
46  int threads) {
47  return absl::make_unique<absl::synchronization_internal::ThreadPool>(threads);
48 }
49 
50 std::unique_ptr<absl::synchronization_internal::ThreadPool>
51 CreateDefaultPool() {
52  return CreatePool(kExtendedTest ? 32 : 10);
53 }
54 
55 // Hack to schedule a function to run on a thread pool thread after a
56 // duration has elapsed.
57 static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,
58  absl::Duration after,
59  const std::function<void()> &func) {
60  tp->Schedule([func, after] {
61  absl::SleepFor(after);
62  func();
63  });
64 }
65 
66 struct TestContext {
67  int iterations;
68  int threads;
69  int g0; // global 0
70  int g1; // global 1
71  absl::Mutex mu;
72  absl::CondVar cv;
73 };
74 
75 // To test whether the invariant check call occurs
76 static std::atomic<bool> invariant_checked;
77 
78 static bool GetInvariantChecked() {
79  return invariant_checked.load(std::memory_order_relaxed);
80 }
81 
82 static void SetInvariantChecked(bool new_value) {
83  invariant_checked.store(new_value, std::memory_order_relaxed);
84 }
85 
86 static void CheckSumG0G1(void *v) {
87  TestContext *cxt = static_cast<TestContext *>(v);
88  ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in CheckSumG0G1");
89  SetInvariantChecked(true);
90 }
91 
92 static void TestMu(TestContext *cxt, int c) {
93  for (int i = 0; i != cxt->iterations; i++) {
94  absl::MutexLock l(&cxt->mu);
95  int a = cxt->g0 + 1;
96  cxt->g0 = a;
97  cxt->g1--;
98  }
99 }
100 
101 static void TestTry(TestContext *cxt, int c) {
102  for (int i = 0; i != cxt->iterations; i++) {
103  do {
104  std::this_thread::yield();
105  } while (!cxt->mu.TryLock());
106  int a = cxt->g0 + 1;
107  cxt->g0 = a;
108  cxt->g1--;
109  cxt->mu.Unlock();
110  }
111 }
112 
113 static void TestR20ms(TestContext *cxt, int c) {
114  for (int i = 0; i != cxt->iterations; i++) {
115  absl::ReaderMutexLock l(&cxt->mu);
117  cxt->mu.AssertReaderHeld();
118  }
119 }
120 
121 static void TestRW(TestContext *cxt, int c) {
122  if ((c & 1) == 0) {
123  for (int i = 0; i != cxt->iterations; i++) {
124  absl::WriterMutexLock l(&cxt->mu);
125  cxt->g0++;
126  cxt->g1--;
127  cxt->mu.AssertHeld();
128  cxt->mu.AssertReaderHeld();
129  }
130  } else {
131  for (int i = 0; i != cxt->iterations; i++) {
132  absl::ReaderMutexLock l(&cxt->mu);
133  ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in TestRW");
134  cxt->mu.AssertReaderHeld();
135  }
136  }
137 }
138 
139 struct MyContext {
140  int target;
141  TestContext *cxt;
142  bool MyTurn();
143 };
144 
145 bool MyContext::MyTurn() {
146  TestContext *cxt = this->cxt;
147  return cxt->g0 == this->target || cxt->g0 == cxt->iterations;
148 }
149 
150 static void TestAwait(TestContext *cxt, int c) {
151  MyContext mc;
152  mc.target = c;
153  mc.cxt = cxt;
154  absl::MutexLock l(&cxt->mu);
155  cxt->mu.AssertHeld();
156  while (cxt->g0 < cxt->iterations) {
157  cxt->mu.Await(absl::Condition(&mc, &MyContext::MyTurn));
158  ABSL_RAW_CHECK(mc.MyTurn(), "Error in TestAwait");
159  cxt->mu.AssertHeld();
160  if (cxt->g0 < cxt->iterations) {
161  int a = cxt->g0 + 1;
162  cxt->g0 = a;
163  mc.target += cxt->threads;
164  }
165  }
166 }
167 
168 static void TestSignalAll(TestContext *cxt, int c) {
169  int target = c;
170  absl::MutexLock l(&cxt->mu);
171  cxt->mu.AssertHeld();
172  while (cxt->g0 < cxt->iterations) {
173  while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
174  cxt->cv.Wait(&cxt->mu);
175  }
176  if (cxt->g0 < cxt->iterations) {
177  int a = cxt->g0 + 1;
178  cxt->g0 = a;
179  cxt->cv.SignalAll();
180  target += cxt->threads;
181  }
182  }
183 }
184 
185 static void TestSignal(TestContext *cxt, int c) {
186  ABSL_RAW_CHECK(cxt->threads == 2, "TestSignal should use 2 threads");
187  int target = c;
188  absl::MutexLock l(&cxt->mu);
189  cxt->mu.AssertHeld();
190  while (cxt->g0 < cxt->iterations) {
191  while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
192  cxt->cv.Wait(&cxt->mu);
193  }
194  if (cxt->g0 < cxt->iterations) {
195  int a = cxt->g0 + 1;
196  cxt->g0 = a;
197  cxt->cv.Signal();
198  target += cxt->threads;
199  }
200  }
201 }
202 
203 static void TestCVTimeout(TestContext *cxt, int c) {
204  int target = c;
205  absl::MutexLock l(&cxt->mu);
206  cxt->mu.AssertHeld();
207  while (cxt->g0 < cxt->iterations) {
208  while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
209  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));
210  }
211  if (cxt->g0 < cxt->iterations) {
212  int a = cxt->g0 + 1;
213  cxt->g0 = a;
214  cxt->cv.SignalAll();
215  target += cxt->threads;
216  }
217  }
218 }
219 
220 static bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; }
221 
222 static void TestTime(TestContext *cxt, int c, bool use_cv) {
223  ABSL_RAW_CHECK(cxt->iterations == 1, "TestTime should only use 1 iteration");
224  ABSL_RAW_CHECK(cxt->threads > 2, "TestTime should use more than 2 threads");
225  const bool kFalse = false;
226  absl::Condition false_cond(&kFalse);
227  absl::Condition g0ge2(G0GE2, cxt);
228  if (c == 0) {
229  absl::MutexLock l(&cxt->mu);
230 
231  absl::Time start = absl::Now();
232  if (use_cv) {
233  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
234  } else {
235  ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
236  "TestTime failed");
237  }
238  absl::Duration elapsed = absl::Now() - start;
240  absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
241  "TestTime failed");
242  ABSL_RAW_CHECK(cxt->g0 == 1, "TestTime failed");
243 
244  start = absl::Now();
245  if (use_cv) {
246  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
247  } else {
248  ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
249  "TestTime failed");
250  }
251  elapsed = absl::Now() - start;
253  absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
254  "TestTime failed");
255  cxt->g0++;
256  if (use_cv) {
257  cxt->cv.Signal();
258  }
259 
260  start = absl::Now();
261  if (use_cv) {
262  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(4));
263  } else {
264  ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(4)),
265  "TestTime failed");
266  }
267  elapsed = absl::Now() - start;
269  absl::Seconds(3.9) <= elapsed && elapsed <= absl::Seconds(6.0),
270  "TestTime failed");
271  ABSL_RAW_CHECK(cxt->g0 >= 3, "TestTime failed");
272 
273  start = absl::Now();
274  if (use_cv) {
275  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
276  } else {
277  ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
278  "TestTime failed");
279  }
280  elapsed = absl::Now() - start;
282  absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
283  "TestTime failed");
284  if (use_cv) {
285  cxt->cv.SignalAll();
286  }
287 
288  start = absl::Now();
289  if (use_cv) {
290  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
291  } else {
292  ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
293  "TestTime failed");
294  }
295  elapsed = absl::Now() - start;
296  ABSL_RAW_CHECK(absl::Seconds(0.9) <= elapsed &&
297  elapsed <= absl::Seconds(2.0), "TestTime failed");
298  ABSL_RAW_CHECK(cxt->g0 == cxt->threads, "TestTime failed");
299 
300  } else if (c == 1) {
301  absl::MutexLock l(&cxt->mu);
302  const absl::Time start = absl::Now();
303  if (use_cv) {
304  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Milliseconds(500));
305  } else {
307  !cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)),
308  "TestTime failed");
309  }
310  const absl::Duration elapsed = absl::Now() - start;
312  absl::Seconds(0.4) <= elapsed && elapsed <= absl::Seconds(0.9),
313  "TestTime failed");
314  cxt->g0++;
315  } else if (c == 2) {
316  absl::MutexLock l(&cxt->mu);
317  if (use_cv) {
318  while (cxt->g0 < 2) {
319  cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));
320  }
321  } else {
322  ABSL_RAW_CHECK(cxt->mu.AwaitWithTimeout(g0ge2, absl::Seconds(100)),
323  "TestTime failed");
324  }
325  cxt->g0++;
326  } else {
327  absl::MutexLock l(&cxt->mu);
328  if (use_cv) {
329  while (cxt->g0 < 2) {
330  cxt->cv.Wait(&cxt->mu);
331  }
332  } else {
333  cxt->mu.Await(g0ge2);
334  }
335  cxt->g0++;
336  }
337 }
338 
339 static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }
340 
341 static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }
342 
343 static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,
344  const std::function<void(int)>& cb) {
345  mu->Lock();
346  int c = (*c0)++;
347  mu->Unlock();
348  cb(c);
349  absl::MutexLock l(mu);
350  (*c1)++;
351  cv->Signal();
352 }
353 
354 // Code common to RunTest() and RunTestWithInvariantDebugging().
355 static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),
356  int threads, int iterations, int operations) {
357  absl::Mutex mu2;
358  absl::CondVar cv2;
359  int c0 = 0;
360  int c1 = 0;
361  cxt->g0 = 0;
362  cxt->g1 = 0;
363  cxt->iterations = iterations;
364  cxt->threads = threads;
366  for (int i = 0; i != threads; i++) {
367  tp.Schedule(std::bind(&EndTest, &c0, &c1, &mu2, &cv2,
368  std::function<void(int)>(
369  std::bind(test, cxt, std::placeholders::_1))));
370  }
371  mu2.Lock();
372  while (c1 != threads) {
373  cv2.Wait(&mu2);
374  }
375  mu2.Unlock();
376  return cxt->g0;
377 }
378 
379 // Basis for the parameterized tests configured below.
380 static int RunTest(void (*test)(TestContext *cxt, int), int threads,
381  int iterations, int operations) {
382  TestContext cxt;
383  return RunTestCommon(&cxt, test, threads, iterations, operations);
384 }
385 
386 // Like RunTest(), but sets an invariant on the tested Mutex and
387 // verifies that the invariant check happened. The invariant function
388 // will be passed the TestContext* as its arg and must call
389 // SetInvariantChecked(true);
390 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
391 static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),
392  int threads, int iterations,
393  int operations,
394  void (*invariant)(void *)) {
396  SetInvariantChecked(false);
397  TestContext cxt;
398  cxt.mu.EnableInvariantDebugging(invariant, &cxt);
399  int ret = RunTestCommon(&cxt, test, threads, iterations, operations);
400  ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked");
401  absl::EnableMutexInvariantDebugging(false); // Restore.
402  return ret;
403 }
404 #endif
405 
406 // --------------------------------------------------------
407 // Test for fix of bug in TryRemove()
408 struct TimeoutBugStruct {
409  absl::Mutex mu;
410  bool a;
411  int a_waiter_count;
412 };
413 
414 static void WaitForA(TimeoutBugStruct *x) {
415  x->mu.LockWhen(absl::Condition(&x->a));
416  x->a_waiter_count--;
417  x->mu.Unlock();
418 }
419 
420 static bool NoAWaiters(TimeoutBugStruct *x) { return x->a_waiter_count == 0; }
421 
422 // Test that a CondVar.Wait(&mutex) can un-block a call to mutex.Await() in
423 // another thread.
424 TEST(Mutex, CondVarWaitSignalsAwait) {
425  // Use a struct so the lock annotations apply.
426  struct {
427  absl::Mutex barrier_mu;
428  bool barrier GUARDED_BY(barrier_mu) = false;
429 
430  absl::Mutex release_mu;
431  bool release GUARDED_BY(release_mu) = false;
432  absl::CondVar released_cv;
433  } state;
434 
435  auto pool = CreateDefaultPool();
436 
437  // Thread A. Sets barrier, waits for release using Mutex::Await, then
438  // signals released_cv.
439  pool->Schedule([&state] {
440  state.release_mu.Lock();
441 
442  state.barrier_mu.Lock();
443  state.barrier = true;
444  state.barrier_mu.Unlock();
445 
446  state.release_mu.Await(absl::Condition(&state.release));
447  state.released_cv.Signal();
448  state.release_mu.Unlock();
449  });
450 
451  state.barrier_mu.LockWhen(absl::Condition(&state.barrier));
452  state.barrier_mu.Unlock();
453  state.release_mu.Lock();
454  // Thread A is now blocked on release by way of Mutex::Await().
455 
456  // Set release. Calling released_cv.Wait() should un-block thread A,
457  // which will signal released_cv. If not, the test will hang.
458  state.release = true;
459  state.released_cv.Wait(&state.release_mu);
460  state.release_mu.Unlock();
461 }
462 
463 // Test that a CondVar.WaitWithTimeout(&mutex) can un-block a call to
464 // mutex.Await() in another thread.
465 TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {
466  // Use a struct so the lock annotations apply.
467  struct {
468  absl::Mutex barrier_mu;
469  bool barrier GUARDED_BY(barrier_mu) = false;
470 
471  absl::Mutex release_mu;
472  bool release GUARDED_BY(release_mu) = false;
473  absl::CondVar released_cv;
474  } state;
475 
476  auto pool = CreateDefaultPool();
477 
478  // Thread A. Sets barrier, waits for release using Mutex::Await, then
479  // signals released_cv.
480  pool->Schedule([&state] {
481  state.release_mu.Lock();
482 
483  state.barrier_mu.Lock();
484  state.barrier = true;
485  state.barrier_mu.Unlock();
486 
487  state.release_mu.Await(absl::Condition(&state.release));
488  state.released_cv.Signal();
489  state.release_mu.Unlock();
490  });
491 
492  state.barrier_mu.LockWhen(absl::Condition(&state.barrier));
493  state.barrier_mu.Unlock();
494  state.release_mu.Lock();
495  // Thread A is now blocked on release by way of Mutex::Await().
496 
497  // Set release. Calling released_cv.Wait() should un-block thread A,
498  // which will signal released_cv. If not, the test will hang.
499  state.release = true;
500  EXPECT_TRUE(
501  !state.released_cv.WaitWithTimeout(&state.release_mu, absl::Seconds(10)))
502  << "; Unrecoverable test failure: CondVar::WaitWithTimeout did not "
503  "unblock the absl::Mutex::Await call in another thread.";
504 
505  state.release_mu.Unlock();
506 }
507 
508 // Test for regression of a bug in loop of TryRemove()
509 TEST(Mutex, MutexTimeoutBug) {
510  auto tp = CreateDefaultPool();
511 
512  TimeoutBugStruct x;
513  x.a = false;
514  x.a_waiter_count = 2;
515  tp->Schedule(std::bind(&WaitForA, &x));
516  tp->Schedule(std::bind(&WaitForA, &x));
517  absl::SleepFor(absl::Seconds(1)); // Allow first two threads to hang.
518  // The skip field of the second will point to the first because there are
519  // only two.
520 
521  // Now cause a thread waiting on an always-false to time out
522  // This would deadlock when the bug was present.
523  bool always_false = false;
524  x.mu.LockWhenWithTimeout(absl::Condition(&always_false),
525  absl::Milliseconds(500));
526 
527  // if we get here, the bug is not present. Cleanup the state.
528 
529  x.a = true; // wakeup the two waiters on A
530  x.mu.Await(absl::Condition(&NoAWaiters, &x)); // wait for them to exit
531  x.mu.Unlock();
532 }
533 
534 struct CondVarWaitDeadlock : testing::TestWithParam<int> {
535  absl::Mutex mu;
536  absl::CondVar cv;
537  bool cond1 = false;
538  bool cond2 = false;
539  bool read_lock1;
540  bool read_lock2;
541  bool signal_unlocked;
542 
543  CondVarWaitDeadlock() {
544  read_lock1 = GetParam() & (1 << 0);
545  read_lock2 = GetParam() & (1 << 1);
546  signal_unlocked = GetParam() & (1 << 2);
547  }
548 
549  void Waiter1() {
550  if (read_lock1) {
551  mu.ReaderLock();
552  while (!cond1) {
553  cv.Wait(&mu);
554  }
555  mu.ReaderUnlock();
556  } else {
557  mu.Lock();
558  while (!cond1) {
559  cv.Wait(&mu);
560  }
561  mu.Unlock();
562  }
563  }
564 
565  void Waiter2() {
566  if (read_lock2) {
567  mu.ReaderLockWhen(absl::Condition(&cond2));
568  mu.ReaderUnlock();
569  } else {
570  mu.LockWhen(absl::Condition(&cond2));
571  mu.Unlock();
572  }
573  }
574 };
575 
576 // Test for a deadlock bug in Mutex::Fer().
577 // The sequence of events that lead to the deadlock is:
578 // 1. waiter1 blocks on cv in read mode (mu bits = 0).
579 // 2. waiter2 blocks on mu in either mode (mu bits = kMuWait).
580 // 3. main thread locks mu, sets cond1, unlocks mu (mu bits = kMuWait).
581 // 4. main thread signals on cv and this eventually calls Mutex::Fer().
582 // Currently Fer wakes waiter1 since mu bits = kMuWait (mutex is unlocked).
583 // Before the bug fix Fer neither woke waiter1 nor queued it on mutex,
584 // which resulted in deadlock.
585 TEST_P(CondVarWaitDeadlock, Test) {
586  auto waiter1 = CreatePool(1);
587  auto waiter2 = CreatePool(1);
588  waiter1->Schedule([this] { this->Waiter1(); });
589  waiter2->Schedule([this] { this->Waiter2(); });
590 
591  // Wait while threads block (best-effort is fine).
593 
594  // Wake condwaiter.
595  mu.Lock();
596  cond1 = true;
597  if (signal_unlocked) {
598  mu.Unlock();
599  cv.Signal();
600  } else {
601  cv.Signal();
602  mu.Unlock();
603  }
604  waiter1.reset(); // "join" waiter1
605 
606  // Wake waiter.
607  mu.Lock();
608  cond2 = true;
609  mu.Unlock();
610  waiter2.reset(); // "join" waiter2
611 }
612 
613 INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
614  ::testing::Range(0, 8),
615  ::testing::PrintToStringParamName());
616 
617 // --------------------------------------------------------
618 // Test for fix of bug in DequeueAllWakeable()
619 // Bug was that if there was more than one waiting reader
620 // and all should be woken, the most recently blocked one
621 // would not be.
622 
623 struct DequeueAllWakeableBugStruct {
624  absl::Mutex mu;
625  absl::Mutex mu2; // protects all fields below
626  int unfinished_count; // count of unfinished readers; under mu2
627  bool done1; // unfinished_count == 0; under mu2
628  int finished_count; // count of finished readers, under mu2
629  bool done2; // finished_count == 0; under mu2
630 };
631 
632 // Test for regression of a bug in loop of DequeueAllWakeable()
633 static void AcquireAsReader(DequeueAllWakeableBugStruct *x) {
634  x->mu.ReaderLock();
635  x->mu2.Lock();
636  x->unfinished_count--;
637  x->done1 = (x->unfinished_count == 0);
638  x->mu2.Unlock();
639  // make sure that both readers acquired mu before we release it.
641  x->mu.ReaderUnlock();
642 
643  x->mu2.Lock();
644  x->finished_count--;
645  x->done2 = (x->finished_count == 0);
646  x->mu2.Unlock();
647 }
648 
649 // Test for regression of a bug in loop of DequeueAllWakeable()
650 TEST(Mutex, MutexReaderWakeupBug) {
651  auto tp = CreateDefaultPool();
652 
653  DequeueAllWakeableBugStruct x;
654  x.unfinished_count = 2;
655  x.done1 = false;
656  x.finished_count = 2;
657  x.done2 = false;
658  x.mu.Lock(); // acquire mu exclusively
659  // queue two thread that will block on reader locks on x.mu
660  tp->Schedule(std::bind(&AcquireAsReader, &x));
661  tp->Schedule(std::bind(&AcquireAsReader, &x));
662  absl::SleepFor(absl::Seconds(1)); // give time for reader threads to block
663  x.mu.Unlock(); // wake them up
664 
665  // both readers should finish promptly
666  EXPECT_TRUE(
667  x.mu2.LockWhenWithTimeout(absl::Condition(&x.done1), absl::Seconds(10)));
668  x.mu2.Unlock();
669 
670  EXPECT_TRUE(
671  x.mu2.LockWhenWithTimeout(absl::Condition(&x.done2), absl::Seconds(10)));
672  x.mu2.Unlock();
673 }
674 
675 struct LockWhenTestStruct {
676  absl::Mutex mu1;
677  bool cond = false;
678 
679  absl::Mutex mu2;
680  bool waiting = false;
681 };
682 
683 static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
684  s->mu2.Lock();
685  s->waiting = true;
686  s->mu2.Unlock();
687  return s->cond;
688 }
689 
690 static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
691  s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));
692  s->mu1.Unlock();
693 }
694 
695 TEST(Mutex, LockWhen) {
696  LockWhenTestStruct s;
697 
698  std::thread t(LockWhenTestWaitForIsCond, &s);
699  s.mu2.LockWhen(absl::Condition(&s.waiting));
700  s.mu2.Unlock();
701 
702  s.mu1.Lock();
703  s.cond = true;
704  s.mu1.Unlock();
705 
706  t.join();
707 }
708 
709 // --------------------------------------------------------
710 // The following test requires Mutex::ReaderLock to be a real shared
711 // lock, which is not the case in all builds.
712 #if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
713 
714 // Test for fix of bug in UnlockSlow() that incorrectly decremented the reader
715 // count when putting a thread to sleep waiting for a false condition when the
716 // lock was not held.
717 
718 // For this bug to strike, we make a thread wait on a free mutex with no
719 // waiters by causing its wakeup condition to be false. Then the
720 // next two acquirers must be readers. The bug causes the lock
721 // to be released when one reader unlocks, rather than both.
722 
723 struct ReaderDecrementBugStruct {
724  bool cond; // to delay first thread (under mu)
725  int done; // reference count (under mu)
726  absl::Mutex mu;
727 
728  bool waiting_on_cond; // under mu2
729  bool have_reader_lock; // under mu2
730  bool complete; // under mu2
731  absl::Mutex mu2; // > mu
732 };
733 
734 // L >= mu, L < mu_waiting_on_cond
735 static bool IsCond(void *v) {
736  ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
737  x->mu2.Lock();
738  x->waiting_on_cond = true;
739  x->mu2.Unlock();
740  return x->cond;
741 }
742 
743 // L >= mu
744 static bool AllDone(void *v) {
745  ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
746  return x->done == 0;
747 }
748 
749 // L={}
750 static void WaitForCond(ReaderDecrementBugStruct *x) {
751  absl::Mutex dummy;
752  absl::MutexLock l(&dummy);
753  x->mu.LockWhen(absl::Condition(&IsCond, x));
754  x->done--;
755  x->mu.Unlock();
756 }
757 
758 // L={}
759 static void GetReadLock(ReaderDecrementBugStruct *x) {
760  x->mu.ReaderLock();
761  x->mu2.Lock();
762  x->have_reader_lock = true;
763  x->mu2.Await(absl::Condition(&x->complete));
764  x->mu2.Unlock();
765  x->mu.ReaderUnlock();
766  x->mu.Lock();
767  x->done--;
768  x->mu.Unlock();
769 }
770 
771 // Test for reader counter being decremented incorrectly by waiter
772 // with false condition.
773 TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
774  ReaderDecrementBugStruct x;
775  x.cond = false;
776  x.waiting_on_cond = false;
777  x.have_reader_lock = false;
778  x.complete = false;
779  x.done = 2; // initial ref count
780 
781  // Run WaitForCond() and wait for it to sleep
782  std::thread thread1(WaitForCond, &x);
783  x.mu2.LockWhen(absl::Condition(&x.waiting_on_cond));
784  x.mu2.Unlock();
785 
786  // Run GetReadLock(), and wait for it to get the read lock
787  std::thread thread2(GetReadLock, &x);
788  x.mu2.LockWhen(absl::Condition(&x.have_reader_lock));
789  x.mu2.Unlock();
790 
791  // Get the reader lock ourselves, and release it.
792  x.mu.ReaderLock();
793  x.mu.ReaderUnlock();
794 
795  // The lock should be held in read mode by GetReadLock().
796  // If we have the bug, the lock will be free.
797  x.mu.AssertReaderHeld();
798 
799  // Wake up all the threads.
800  x.mu2.Lock();
801  x.complete = true;
802  x.mu2.Unlock();
803 
804  // TODO(delesley): turn on analysis once lock upgrading is supported.
805  // (This call upgrades the lock from shared to exclusive.)
806  x.mu.Lock();
807  x.cond = true;
808  x.mu.Await(absl::Condition(&AllDone, &x));
809  x.mu.Unlock();
810 
811  thread1.join();
812  thread2.join();
813 }
814 #endif // !ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
815 
816 // Test that we correctly handle the situation when a lock is
817 // held and then destroyed (w/o unlocking).
818 #ifdef THREAD_SANITIZER
819 // TSAN reports errors when locked Mutexes are destroyed.
820 TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
821 #else
822 TEST(Mutex, LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
823 #endif
824  for (int i = 0; i != 10; i++) {
825  // Create, lock and destroy 10 locks.
826  const int kNumLocks = 10;
827  auto mu = absl::make_unique<absl::Mutex[]>(kNumLocks);
828  for (int j = 0; j != kNumLocks; j++) {
829  if ((j % 2) == 0) {
830  mu[j].WriterLock();
831  } else {
832  mu[j].ReaderLock();
833  }
834  }
835  }
836 }
837 
838 // --------------------------------------------------------
839 // Test for bug with pattern of readers using a condvar. The bug was that if a
840 // reader went to sleep on a condition variable while one or more other readers
841 // held the lock, but there were no waiters, the reader count (held in the
842 // mutex word) would be lost. (This is because Enqueue() had at one time
843 // always placed the thread on the Mutex queue. Later (CL 4075610), to
844 // tolerate re-entry into Mutex from a Condition predicate, Enqueue() was
845 // changed so that it could also place a thread on a condition-variable. This
846 // introduced the case where Enqueue() returned with an empty queue, and this
847 // case was handled incorrectly in one place.)
848 
849 static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
850  int *running) {
851  std::random_device dev;
852  std::mt19937 gen(dev());
853  std::uniform_int_distribution<int> random_millis(0, 15);
854  mu->ReaderLock();
855  while (*running == 3) {
856  absl::SleepFor(absl::Milliseconds(random_millis(gen)));
857  cv->WaitWithTimeout(mu, absl::Milliseconds(random_millis(gen)));
858  }
859  mu->ReaderUnlock();
860  mu->Lock();
861  (*running)--;
862  mu->Unlock();
863 }
864 
865 struct True {
866  template <class... Args>
867  bool operator()(Args...) const {
868  return true;
869  }
870 };
871 
872 struct DerivedTrue : True {};
873 
874 TEST(Mutex, FunctorCondition) {
875  { // Variadic
876  True f;
877  EXPECT_TRUE(absl::Condition(&f).Eval());
878  }
879 
880  { // Inherited
881  DerivedTrue g;
882  EXPECT_TRUE(absl::Condition(&g).Eval());
883  }
884 
885  { // lambda
886  int value = 3;
887  auto is_zero = [&value] { return value == 0; };
888  absl::Condition c(&is_zero);
889  EXPECT_FALSE(c.Eval());
890  value = 0;
891  EXPECT_TRUE(c.Eval());
892  }
893 
894  { // bind
895  int value = 0;
896  auto is_positive = std::bind(std::less<int>(), 0, std::cref(value));
897  absl::Condition c(&is_positive);
898  EXPECT_FALSE(c.Eval());
899  value = 1;
900  EXPECT_TRUE(c.Eval());
901  }
902 
903  { // std::function
904  int value = 3;
905  std::function<bool()> is_zero = [&value] { return value == 0; };
906  absl::Condition c(&is_zero);
907  EXPECT_FALSE(c.Eval());
908  value = 0;
909  EXPECT_TRUE(c.Eval());
910  }
911 }
912 
913 static bool IntIsZero(int *x) { return *x == 0; }
914 
915 // Test for reader waiting condition variable when there are other readers
916 // but no waiters.
917 TEST(Mutex, TestReaderOnCondVar) {
918  auto tp = CreateDefaultPool();
919  absl::Mutex mu;
920  absl::CondVar cv;
921  int running = 3;
922  tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
923  tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
925  mu.Lock();
926  running--;
927  mu.Await(absl::Condition(&IntIsZero, &running));
928  mu.Unlock();
929 }
930 
931 // --------------------------------------------------------
932 struct AcquireFromConditionStruct {
933  absl::Mutex mu0; // protects value, done
934  int value; // times condition function is called; under mu0,
935  bool done; // done with test? under mu0
936  absl::Mutex mu1; // used to attempt to mess up state of mu0
937  absl::CondVar cv; // so the condition function can be invoked from
938  // CondVar::Wait().
939 };
940 
941 static bool ConditionWithAcquire(AcquireFromConditionStruct *x) {
942  x->value++; // count times this function is called
943 
944  if (x->value == 2 || x->value == 3) {
945  // On the second and third invocation of this function, sleep for 100ms,
946  // but with the side-effect of altering the state of a Mutex other than
947  // than one for which this is a condition. The spec now explicitly allows
948  // this side effect; previously it did not. it was illegal.
949  bool always_false = false;
950  x->mu1.LockWhenWithTimeout(absl::Condition(&always_false),
951  absl::Milliseconds(100));
952  x->mu1.Unlock();
953  }
954  ABSL_RAW_CHECK(x->value < 4, "should not be invoked a fourth time");
955 
956  // We arrange for the condition to return true on only the 2nd and 3rd calls.
957  return x->value == 2 || x->value == 3;
958 }
959 
960 static void WaitForCond2(AcquireFromConditionStruct *x) {
961  // wait for cond0 to become true
962  x->mu0.LockWhen(absl::Condition(&ConditionWithAcquire, x));
963  x->done = true;
964  x->mu0.Unlock();
965 }
966 
967 // Test for Condition whose function acquires other Mutexes
968 TEST(Mutex, AcquireFromCondition) {
969  auto tp = CreateDefaultPool();
970 
971  AcquireFromConditionStruct x;
972  x.value = 0;
973  x.done = false;
974  tp->Schedule(
975  std::bind(&WaitForCond2, &x)); // run WaitForCond2() in a thread T
976  // T will hang because the first invocation of ConditionWithAcquire() will
977  // return false.
978  absl::SleepFor(absl::Milliseconds(500)); // allow T time to hang
979 
980  x.mu0.Lock();
981  x.cv.WaitWithTimeout(&x.mu0, absl::Milliseconds(500)); // wake T
982  // T will be woken because the Wait() will call ConditionWithAcquire()
983  // for the second time, and it will return true.
984 
985  x.mu0.Unlock();
986 
987  // T will then acquire the lock and recheck its own condition.
988  // It will find the condition true, as this is the third invocation,
989  // but the use of another Mutex by the calling function will
990  // cause the old mutex implementation to think that the outer
991  // LockWhen() has timed out because the inner LockWhenWithTimeout() did.
992  // T will then check the condition a fourth time because it finds a
993  // timeout occurred. This should not happen in the new
994  // implementation that allows the Condition function to use Mutexes.
995 
996  // It should also succeed, even though the Condition function
997  // is being invoked from CondVar::Wait, and thus this thread
998  // is conceptually waiting both on the condition variable, and on mu2.
999 
1000  x.mu0.LockWhen(absl::Condition(&x.done));
1001  x.mu0.Unlock();
1002 }
1003 
1004 // The deadlock detector is not part of non-prod builds, so do not test it.
1005 #if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
1006 
1007 TEST(Mutex, DeadlockDetector) {
1009 
1010  // check that we can call ForgetDeadlockInfo() on a lock with the lock held
1011  absl::Mutex m1;
1012  absl::Mutex m2;
1013  absl::Mutex m3;
1014  absl::Mutex m4;
1015 
1016  m1.Lock(); // m1 gets ID1
1017  m2.Lock(); // m2 gets ID2
1018  m3.Lock(); // m3 gets ID3
1019  m3.Unlock();
1020  m2.Unlock();
1021  // m1 still held
1022  m1.ForgetDeadlockInfo(); // m1 loses ID
1023  m2.Lock(); // m2 gets ID2
1024  m3.Lock(); // m3 gets ID3
1025  m4.Lock(); // m4 gets ID4
1026  m3.Unlock();
1027  m2.Unlock();
1028  m4.Unlock();
1029  m1.Unlock();
1030 }
1031 
1032 // Bazel has a test "warning" file that programs can write to if the
1033 // test should pass with a warning. This class disables the warning
1034 // file until it goes out of scope.
1035 class ScopedDisableBazelTestWarnings {
1036  public:
1037  ScopedDisableBazelTestWarnings() {
1038 #ifdef WIN32
1039  char file[MAX_PATH];
1040  if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
1041  warnings_output_file_ = file;
1042  SetEnvironmentVariableA(kVarName, nullptr);
1043  }
1044 #else
1045  const char *file = getenv(kVarName);
1046  if (file != nullptr) {
1047  warnings_output_file_ = file;
1048  unsetenv(kVarName);
1049  }
1050 #endif
1051  }
1052 
1053  ~ScopedDisableBazelTestWarnings() {
1054  if (!warnings_output_file_.empty()) {
1055 #ifdef WIN32
1056  SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
1057 #else
1058  setenv(kVarName, warnings_output_file_.c_str(), 0);
1059 #endif
1060  }
1061  }
1062 
1063  private:
1064  static const char kVarName[];
1065  std::string warnings_output_file_;
1066 };
1067 const char ScopedDisableBazelTestWarnings::kVarName[] =
1068  "TEST_WARNINGS_OUTPUT_FILE";
1069 
1070 #ifdef THREAD_SANITIZER
1071 // This test intentionally creates deadlocks to test the deadlock detector.
1072 TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
1073 #else
1074 TEST(Mutex, DeadlockDetectorBazelWarning) {
1075 #endif
1077 
1078  // Cause deadlock detection to detect something, if it's
1079  // compiled in and enabled. But turn off the bazel warning.
1080  ScopedDisableBazelTestWarnings disable_bazel_test_warnings;
1081 
1082  absl::Mutex mu0;
1083  absl::Mutex mu1;
1084  bool got_mu0 = mu0.TryLock();
1085  mu1.Lock(); // acquire mu1 while holding mu0
1086  if (got_mu0) {
1087  mu0.Unlock();
1088  }
1089  if (mu0.TryLock()) { // try lock shouldn't cause deadlock detector to fire
1090  mu0.Unlock();
1091  }
1092  mu0.Lock(); // acquire mu0 while holding mu1; should get one deadlock
1093  // report here
1094  mu0.Unlock();
1095  mu1.Unlock();
1096 
1098 }
1099 
1100 // This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the
1101 // annotation-based static thread-safety analysis is not currently
1102 // predicate-aware and cannot tell if the two for-loops that acquire and
1103 // release the locks have the same predicates.
1104 TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
1105  // Stress test: Here we create a large number of locks and use all of them.
1106  // If a deadlock detector keeps a full graph of lock acquisition order,
1107  // it will likely be too slow for this test to pass.
1108  const int n_locks = 1 << 17;
1109  auto array_of_locks = absl::make_unique<absl::Mutex[]>(n_locks);
1110  for (int i = 0; i < n_locks; i++) {
1111  int end = std::min(n_locks, i + 5);
1112  // acquire and then release locks i, i+1, ..., i+4
1113  for (int j = i; j < end; j++) {
1114  array_of_locks[j].Lock();
1115  }
1116  for (int j = i; j < end; j++) {
1117  array_of_locks[j].Unlock();
1118  }
1119  }
1120 }
1121 
1122 #ifdef THREAD_SANITIZER
1123 // TSAN reports errors when locked Mutexes are destroyed.
1124 TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
1125 #else
1126 TEST(Mutex, DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
1127 #endif
1128  // Test a scenario where a cached deadlock graph node id in the
1129  // list of held locks is not invalidated when the corresponding
1130  // mutex is deleted.
1132  // Mutex that will be destroyed while being held
1133  absl::Mutex *a = new absl::Mutex;
1134  // Other mutexes needed by test
1135  absl::Mutex b, c;
1136 
1137  // Hold mutex.
1138  a->Lock();
1139 
1140  // Force deadlock id assignment by acquiring another lock.
1141  b.Lock();
1142  b.Unlock();
1143 
1144  // Delete the mutex. The Mutex destructor tries to remove held locks,
1145  // but the attempt isn't foolproof. It can fail if:
1146  // (a) Deadlock detection is currently disabled.
1147  // (b) The destruction is from another thread.
1148  // We exploit (a) by temporarily disabling deadlock detection.
1150  delete a;
1152 
1153  // Now acquire another lock which will force a deadlock id assignment.
1154  // We should end up getting assigned the same deadlock id that was
1155  // freed up when "a" was deleted, which will cause a spurious deadlock
1156  // report if the held lock entry for "a" was not invalidated.
1157  c.Lock();
1158  c.Unlock();
1159 }
1160 #endif // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
1161 
1162 // --------------------------------------------------------
1163 // Test for timeouts/deadlines on condition waits that are specified using
1164 // absl::Duration and absl::Time. For each waiting function we test with
1165 // a timeout/deadline that has already expired/passed, one that is infinite
1166 // and so never expires/passes, and one that will expire/pass in the near
1167 // future.
1168 
1169 static absl::Duration TimeoutTestAllowedSchedulingDelay() {
1170  // Note: we use a function here because Microsoft Visual Studio fails to
1171  // properly initialize constexpr static absl::Duration variables.
1172  return absl::Milliseconds(150);
1173 }
1174 
1175 // Returns true if `actual_delay` is close enough to `expected_delay` to pass
1176 // the timeouts/deadlines test. Otherwise, logs warnings and returns false.
1178 static bool DelayIsWithinBounds(absl::Duration expected_delay,
1179  absl::Duration actual_delay) {
1180  bool pass = true;
1181  // Do not allow the observed delay to be less than expected. This may occur
1182  // in practice due to clock skew or when the synchronization primitives use a
1183  // different clock than absl::Now(), but these cases should be handled by the
1184  // the retry mechanism in each TimeoutTest.
1185  if (actual_delay < expected_delay) {
1186  ABSL_RAW_LOG(WARNING,
1187  "Actual delay %s was too short, expected %s (difference %s)",
1188  absl::FormatDuration(actual_delay).c_str(),
1189  absl::FormatDuration(expected_delay).c_str(),
1190  absl::FormatDuration(actual_delay - expected_delay).c_str());
1191  pass = false;
1192  }
1193  // If the expected delay is <= zero then allow a small error tolerance, since
1194  // we do not expect context switches to occur during test execution.
1195  // Otherwise, thread scheduling delays may be substantial in rare cases, so
1196  // tolerate up to kTimeoutTestAllowedSchedulingDelay of error.
1197  absl::Duration tolerance = expected_delay <= absl::ZeroDuration()
1198  ? absl::Milliseconds(10)
1199  : TimeoutTestAllowedSchedulingDelay();
1200  if (actual_delay > expected_delay + tolerance) {
1201  ABSL_RAW_LOG(WARNING,
1202  "Actual delay %s was too long, expected %s (difference %s)",
1203  absl::FormatDuration(actual_delay).c_str(),
1204  absl::FormatDuration(expected_delay).c_str(),
1205  absl::FormatDuration(actual_delay - expected_delay).c_str());
1206  pass = false;
1207  }
1208  return pass;
1209 }
1210 
1211 // Parameters for TimeoutTest, below.
1212 struct TimeoutTestParam {
1213  // The file and line number (used for logging purposes only).
1214  const char *from_file;
1215  int from_line;
1216 
1217  // Should the absolute deadline API based on absl::Time be tested? If false,
1218  // the relative deadline API based on absl::Duration is tested.
1219  bool use_absolute_deadline;
1220 
1221  // The deadline/timeout used when calling the API being tested
1222  // (e.g. Mutex::LockWhenWithDeadline).
1223  absl::Duration wait_timeout;
1224 
1225  // The delay before the condition will be set true by the test code. If zero
1226  // or negative, the condition is set true immediately (before calling the API
1227  // being tested). Otherwise, if infinite, the condition is never set true.
1228  // Otherwise a closure is scheduled for the future that sets the condition
1229  // true.
1230  absl::Duration satisfy_condition_delay;
1231 
1232  // The expected result of the condition after the call to the API being
1233  // tested. Generally `true` means the condition was true when the API returns,
1234  // `false` indicates an expected timeout.
1235  bool expected_result;
1236 
1237  // The expected delay before the API under test returns. This is inherently
1238  // flaky, so some slop is allowed (see `DelayIsWithinBounds` above), and the
1239  // test keeps trying indefinitely until this constraint passes.
1240  absl::Duration expected_delay;
1241 };
1242 
1243 // Print a `TimeoutTestParam` to a debug log.
1244 std::ostream &operator<<(std::ostream &os, const TimeoutTestParam &param) {
1245  return os << "from: " << param.from_file << ":" << param.from_line
1246  << " use_absolute_deadline: "
1247  << (param.use_absolute_deadline ? "true" : "false")
1248  << " wait_timeout: " << param.wait_timeout
1249  << " satisfy_condition_delay: " << param.satisfy_condition_delay
1250  << " expected_result: "
1251  << (param.expected_result ? "true" : "false")
1252  << " expected_delay: " << param.expected_delay;
1253 }
1254 
1255 std::string FormatString(const TimeoutTestParam &param) {
1256  std::ostringstream os;
1257  os << param;
1258  return os.str();
1259 }
1260 
1261 // Like `thread::Executor::ScheduleAt` except:
1262 // a) Delays zero or negative are executed immediately in the current thread.
1263 // b) Infinite delays are never scheduled.
1264 // c) Calls this test's `ScheduleAt` helper instead of using `pool` directly.
1265 static void RunAfterDelay(absl::Duration delay,
1267  const std::function<void()> &callback) {
1268  if (delay <= absl::ZeroDuration()) {
1269  callback(); // immediate
1270  } else if (delay != absl::InfiniteDuration()) {
1271  ScheduleAfter(pool, delay, callback);
1272  }
1273 }
1274 
1275 class TimeoutTest : public ::testing::Test,
1276  public ::testing::WithParamInterface<TimeoutTestParam> {};
1277 
1278 std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {
1279  // The `finite` delay is a finite, relatively short, delay. We make it larger
1280  // than our allowed scheduling delay (slop factor) to avoid confusion when
1281  // diagnosing test failures. The other constants here have clear meanings.
1282  const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay();
1283  const absl::Duration never = absl::InfiniteDuration();
1284  const absl::Duration negative = -absl::InfiniteDuration();
1285  const absl::Duration immediate = absl::ZeroDuration();
1286 
1287  // Every test case is run twice; once using the absolute deadline API and once
1288  // using the relative timeout API.
1289  std::vector<TimeoutTestParam> values;
1290  for (bool use_absolute_deadline : {false, true}) {
1291  // Tests with a negative timeout (deadline in the past), which should
1292  // immediately return current state of the condition.
1293 
1294  // The condition is already true:
1295  values.push_back(TimeoutTestParam{
1296  __FILE__, __LINE__, use_absolute_deadline,
1297  negative, // wait_timeout
1298  immediate, // satisfy_condition_delay
1299  true, // expected_result
1300  immediate, // expected_delay
1301  });
1302 
1303  // The condition becomes true, but the timeout has already expired:
1304  values.push_back(TimeoutTestParam{
1305  __FILE__, __LINE__, use_absolute_deadline,
1306  negative, // wait_timeout
1307  finite, // satisfy_condition_delay
1308  false, // expected_result
1309  immediate // expected_delay
1310  });
1311 
1312  // The condition never becomes true:
1313  values.push_back(TimeoutTestParam{
1314  __FILE__, __LINE__, use_absolute_deadline,
1315  negative, // wait_timeout
1316  never, // satisfy_condition_delay
1317  false, // expected_result
1318  immediate // expected_delay
1319  });
1320 
1321  // Tests with an infinite timeout (deadline in the infinite future), which
1322  // should only return when the condition becomes true.
1323 
1324  // The condition is already true:
1325  values.push_back(TimeoutTestParam{
1326  __FILE__, __LINE__, use_absolute_deadline,
1327  never, // wait_timeout
1328  immediate, // satisfy_condition_delay
1329  true, // expected_result
1330  immediate // expected_delay
1331  });
1332 
1333  // The condition becomes true before the (infinite) expiry:
1334  values.push_back(TimeoutTestParam{
1335  __FILE__, __LINE__, use_absolute_deadline,
1336  never, // wait_timeout
1337  finite, // satisfy_condition_delay
1338  true, // expected_result
1339  finite, // expected_delay
1340  });
1341 
1342  // Tests with a (small) finite timeout (deadline soon), with the condition
1343  // becoming true both before and after its expiry.
1344 
1345  // The condition is already true:
1346  values.push_back(TimeoutTestParam{
1347  __FILE__, __LINE__, use_absolute_deadline,
1348  never, // wait_timeout
1349  immediate, // satisfy_condition_delay
1350  true, // expected_result
1351  immediate // expected_delay
1352  });
1353 
1354  // The condition becomes true before the expiry:
1355  values.push_back(TimeoutTestParam{
1356  __FILE__, __LINE__, use_absolute_deadline,
1357  finite * 2, // wait_timeout
1358  finite, // satisfy_condition_delay
1359  true, // expected_result
1360  finite // expected_delay
1361  });
1362 
1363  // The condition becomes true, but the timeout has already expired:
1364  values.push_back(TimeoutTestParam{
1365  __FILE__, __LINE__, use_absolute_deadline,
1366  finite, // wait_timeout
1367  finite * 2, // satisfy_condition_delay
1368  false, // expected_result
1369  finite // expected_delay
1370  });
1371 
1372  // The condition never becomes true:
1373  values.push_back(TimeoutTestParam{
1374  __FILE__, __LINE__, use_absolute_deadline,
1375  finite, // wait_timeout
1376  never, // satisfy_condition_delay
1377  false, // expected_result
1378  finite // expected_delay
1379  });
1380  }
1381  return values;
1382 }
1383 
1384 // Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.
1385 INSTANTIATE_TEST_SUITE_P(All, TimeoutTest,
1386  testing::ValuesIn(MakeTimeoutTestParamValues()));
1387 
1388 TEST_P(TimeoutTest, Await) {
1389  const TimeoutTestParam params = GetParam();
1390  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
1391 
1392  // Because this test asserts bounds on scheduling delays it is flaky. To
1393  // compensate it loops forever until it passes. Failures express as test
1394  // timeouts, in which case the test log can be used to diagnose the issue.
1395  for (int attempt = 1;; ++attempt) {
1396  ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
1397 
1398  absl::Mutex mu;
1399  bool value = false; // condition value (under mu)
1400 
1401  std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
1402  CreateDefaultPool();
1403  RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
1404  absl::MutexLock l(&mu);
1405  value = true;
1406  });
1407 
1408  absl::MutexLock lock(&mu);
1409  absl::Time start_time = absl::Now();
1410  absl::Condition cond(&value);
1411  bool result =
1412  params.use_absolute_deadline
1413  ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout)
1414  : mu.AwaitWithTimeout(cond, params.wait_timeout);
1415  if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
1416  EXPECT_EQ(params.expected_result, result);
1417  break;
1418  }
1419  }
1420 }
1421 
1422 TEST_P(TimeoutTest, LockWhen) {
1423  const TimeoutTestParam params = GetParam();
1424  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
1425 
1426  // Because this test asserts bounds on scheduling delays it is flaky. To
1427  // compensate it loops forever until it passes. Failures express as test
1428  // timeouts, in which case the test log can be used to diagnose the issue.
1429  for (int attempt = 1;; ++attempt) {
1430  ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
1431 
1432  absl::Mutex mu;
1433  bool value = false; // condition value (under mu)
1434 
1435  std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
1436  CreateDefaultPool();
1437  RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
1438  absl::MutexLock l(&mu);
1439  value = true;
1440  });
1441 
1442  absl::Time start_time = absl::Now();
1443  absl::Condition cond(&value);
1444  bool result =
1445  params.use_absolute_deadline
1446  ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout)
1447  : mu.LockWhenWithTimeout(cond, params.wait_timeout);
1448  mu.Unlock();
1449 
1450  if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
1451  EXPECT_EQ(params.expected_result, result);
1452  break;
1453  }
1454  }
1455 }
1456 
1457 TEST_P(TimeoutTest, ReaderLockWhen) {
1458  const TimeoutTestParam params = GetParam();
1459  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
1460 
1461  // Because this test asserts bounds on scheduling delays it is flaky. To
1462  // compensate it loops forever until it passes. Failures express as test
1463  // timeouts, in which case the test log can be used to diagnose the issue.
1464  for (int attempt = 0;; ++attempt) {
1465  ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
1466 
1467  absl::Mutex mu;
1468  bool value = false; // condition value (under mu)
1469 
1470  std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
1471  CreateDefaultPool();
1472  RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
1473  absl::MutexLock l(&mu);
1474  value = true;
1475  });
1476 
1477  absl::Time start_time = absl::Now();
1478  bool result =
1479  params.use_absolute_deadline
1481  start_time + params.wait_timeout)
1483  params.wait_timeout);
1484  mu.ReaderUnlock();
1485 
1486  if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
1487  EXPECT_EQ(params.expected_result, result);
1488  break;
1489  }
1490  }
1491 }
1492 
1493 TEST_P(TimeoutTest, Wait) {
1494  const TimeoutTestParam params = GetParam();
1495  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
1496 
1497  // Because this test asserts bounds on scheduling delays it is flaky. To
1498  // compensate it loops forever until it passes. Failures express as test
1499  // timeouts, in which case the test log can be used to diagnose the issue.
1500  for (int attempt = 0;; ++attempt) {
1501  ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
1502 
1503  absl::Mutex mu;
1504  bool value = false; // condition value (under mu)
1505  absl::CondVar cv; // signals a change of `value`
1506 
1507  std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
1508  CreateDefaultPool();
1509  RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
1510  absl::MutexLock l(&mu);
1511  value = true;
1512  cv.Signal();
1513  });
1514 
1515  absl::MutexLock lock(&mu);
1516  absl::Time start_time = absl::Now();
1517  absl::Duration timeout = params.wait_timeout;
1518  absl::Time deadline = start_time + timeout;
1519  while (!value) {
1520  if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline)
1521  : cv.WaitWithTimeout(&mu, timeout)) {
1522  break; // deadline/timeout exceeded
1523  }
1524  timeout = deadline - absl::Now(); // recompute
1525  }
1526  bool result = value; // note: `mu` is still held
1527 
1528  if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
1529  EXPECT_EQ(params.expected_result, result);
1530  break;
1531  }
1532  }
1533 }
1534 
1535 TEST(Mutex, Logging) {
1536  // Allow user to look at logging output
1537  absl::Mutex logged_mutex;
1538  logged_mutex.EnableDebugLog("fido_mutex");
1539  absl::CondVar logged_cv;
1540  logged_cv.EnableDebugLog("rover_cv");
1541  logged_mutex.Lock();
1542  logged_cv.WaitWithTimeout(&logged_mutex, absl::Milliseconds(20));
1543  logged_mutex.Unlock();
1544  logged_mutex.ReaderLock();
1545  logged_mutex.ReaderUnlock();
1546  logged_mutex.Lock();
1547  logged_mutex.Unlock();
1548  logged_cv.Signal();
1549  logged_cv.SignalAll();
1550 }
1551 
1552 // --------------------------------------------------------
1553 
1554 // Generate the vector of thread counts for tests parameterized on thread count.
1555 static std::vector<int> AllThreadCountValues() {
1556  if (kExtendedTest) {
1557  return {2, 4, 8, 10, 16, 20, 24, 30, 32};
1558  }
1559  return {2, 4, 10};
1560 }
1561 
1562 // A test fixture parameterized by thread count.
1563 class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};
1564 
1565 // Instantiate the above with AllThreadCountOptions().
1566 INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,
1567  ::testing::ValuesIn(AllThreadCountValues()),
1568  ::testing::PrintToStringParamName());
1569 
1570 // Reduces iterations by some factor for slow platforms
1571 // (determined empirically).
1572 static int ScaleIterations(int x) {
1573  // ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE is set in the implementation
1574  // of Mutex that uses either std::mutex or pthread_mutex_t. Use
1575  // these as keys to determine the slow implementation.
1576 #if defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
1577  return x / 10;
1578 #else
1579  return x;
1580 #endif
1581 }
1582 
1583 TEST_P(MutexVariableThreadCountTest, Mutex) {
1584  int threads = GetParam();
1585  int iterations = ScaleIterations(10000000) / threads;
1586  int operations = threads * iterations;
1587  EXPECT_EQ(RunTest(&TestMu, threads, iterations, operations), operations);
1588 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
1589  iterations = std::min(iterations, 10);
1590  operations = threads * iterations;
1591  EXPECT_EQ(RunTestWithInvariantDebugging(&TestMu, threads, iterations,
1592  operations, CheckSumG0G1),
1593  operations);
1594 #endif
1595 }
1596 
1597 TEST_P(MutexVariableThreadCountTest, Try) {
1598  int threads = GetParam();
1599  int iterations = 1000000 / threads;
1600  int operations = iterations * threads;
1601  EXPECT_EQ(RunTest(&TestTry, threads, iterations, operations), operations);
1602 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
1603  iterations = std::min(iterations, 10);
1604  operations = threads * iterations;
1605  EXPECT_EQ(RunTestWithInvariantDebugging(&TestTry, threads, iterations,
1606  operations, CheckSumG0G1),
1607  operations);
1608 #endif
1609 }
1610 
1611 TEST_P(MutexVariableThreadCountTest, R20ms) {
1612  int threads = GetParam();
1613  int iterations = 100;
1614  int operations = iterations * threads;
1615  EXPECT_EQ(RunTest(&TestR20ms, threads, iterations, operations), 0);
1616 }
1617 
1618 TEST_P(MutexVariableThreadCountTest, RW) {
1619  int threads = GetParam();
1620  int iterations = ScaleIterations(20000000) / threads;
1621  int operations = iterations * threads;
1622  EXPECT_EQ(RunTest(&TestRW, threads, iterations, operations), operations / 2);
1623 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
1624  iterations = std::min(iterations, 10);
1625  operations = threads * iterations;
1626  EXPECT_EQ(RunTestWithInvariantDebugging(&TestRW, threads, iterations,
1627  operations, CheckSumG0G1),
1628  operations / 2);
1629 #endif
1630 }
1631 
1632 TEST_P(MutexVariableThreadCountTest, Await) {
1633  int threads = GetParam();
1634  int iterations = ScaleIterations(500000);
1635  int operations = iterations;
1636  EXPECT_EQ(RunTest(&TestAwait, threads, iterations, operations), operations);
1637 }
1638 
1639 TEST_P(MutexVariableThreadCountTest, SignalAll) {
1640  int threads = GetParam();
1641  int iterations = 200000 / threads;
1642  int operations = iterations;
1643  EXPECT_EQ(RunTest(&TestSignalAll, threads, iterations, operations),
1644  operations);
1645 }
1646 
1647 TEST(Mutex, Signal) {
1648  int threads = 2; // TestSignal must use two threads
1649  int iterations = 200000;
1650  int operations = iterations;
1651  EXPECT_EQ(RunTest(&TestSignal, threads, iterations, operations), operations);
1652 }
1653 
1654 TEST(Mutex, Timed) {
1655  int threads = 10; // Use a fixed thread count of 10
1656  int iterations = 1000;
1657  int operations = iterations;
1658  EXPECT_EQ(RunTest(&TestCVTimeout, threads, iterations, operations),
1659  operations);
1660 }
1661 
1662 TEST(Mutex, CVTime) {
1663  int threads = 10; // Use a fixed thread count of 10
1664  int iterations = 1;
1665  EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1),
1666  threads * iterations);
1667 }
1668 
1669 TEST(Mutex, MuTime) {
1670  int threads = 10; // Use a fixed thread count of 10
1671  int iterations = 1;
1672  EXPECT_EQ(RunTest(&TestMuTime, threads, iterations, 1), threads * iterations);
1673 }
1674 
1675 } // namespace
int v
Definition: variant_test.cc:81
bool AwaitWithDeadline(const Condition &cond, absl::Time deadline)
void ForgetDeadlockInfo()
void ReaderLockWhen(const Condition &cond) SHARED_LOCK_FUNCTION()
bool WaitWithDeadline(Mutex *mu, absl::Time deadline)
void SleepFor(absl::Duration duration)
Definition: clock.h:68
Time Now()
Definition: clock.cc:37
#define ABSL_RAW_LOG(severity,...)
Definition: raw_logging.h:42
bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
void LockWhen(const Condition &cond) EXCLUSIVE_LOCK_FUNCTION()
std::ostream & operator<<(std::ostream &os, absl::LogSeverity s)
Definition: log_severity.cc:21
bool ReaderLockWhenWithDeadline(const Condition &cond, absl::Time deadline) SHARED_LOCK_FUNCTION()
void WriterLock() EXCLUSIVE_LOCK_FUNCTION()
Definition: mutex.h:260
char * end
constexpr Duration Milliseconds(int64_t n)
Definition: time.h:1458
void EnableDebugLog(const char *name)
void EnableDebugLog(const char *name)
void(* invariant)(void *arg)
Definition: mutex.cc:291
bool ReaderLockWhenWithTimeout(const Condition &cond, absl::Duration timeout) SHARED_LOCK_FUNCTION()
#define ABSL_RAW_CHECK(condition, message)
Definition: raw_logging.h:57
static const uint32_t c1
Definition: city.cc:57
bool LockWhenWithDeadline(const Condition &cond, absl::Time deadline) EXCLUSIVE_LOCK_FUNCTION()
void ReaderUnlock() UNLOCK_FUNCTION()
void Unlock() UNLOCK_FUNCTION()
size_t value
#define ABSL_MUST_USE_RESULT
Definition: attributes.h:449
int refcount GUARDED_BY(synch_event_mu)
std::string FormatDuration(Duration d)
Definition: duration.cc:758
bool LockWhenWithTimeout(const Condition &cond, absl::Duration timeout) EXCLUSIVE_LOCK_FUNCTION()
bool AwaitWithTimeout(const Condition &cond, absl::Duration timeout)
#define NO_THREAD_SAFETY_ANALYSIS
void Lock() EXCLUSIVE_LOCK_FUNCTION()
constexpr Duration Seconds(int64_t n)
Definition: time.h:1461
TEST(Symbolize, Unimplemented)
uint64_t b
Definition: layout_test.cc:50
void Await(const Condition &cond)
void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode)
Definition: mutex.cc:745
void EnableMutexInvariantDebugging(bool enabled)
Definition: mutex.cc:730
bool WaitWithTimeout(Mutex *mu, absl::Duration timeout)
void ReaderLock() SHARED_LOCK_FUNCTION()
constexpr Duration InfiniteDuration()
Definition: time.h:1513
void Wait(Mutex *mu)
constexpr Duration ZeroDuration()
Definition: time.h:286
void Schedule(std::function< void()> func)
Definition: thread_pool.h:56


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:19