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