• 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/internal/raw_logging.h"
34 #include "absl/base/internal/sysinfo.h"
35 #include "absl/memory/memory.h"
36 #include "absl/synchronization/internal/thread_pool.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 
CreatePool(int threads)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>
CreateDefaultPool()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.
ScheduleAfter(absl::synchronization_internal::ThreadPool * tp,absl::Duration after,const std::function<void ()> & func)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 
GetInvariantChecked()78 static bool GetInvariantChecked() {
79   return invariant_checked.load(std::memory_order_relaxed);
80 }
81 
SetInvariantChecked(bool new_value)82 static void SetInvariantChecked(bool new_value) {
83   invariant_checked.store(new_value, std::memory_order_relaxed);
84 }
85 
CheckSumG0G1(void * v)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 
TestMu(TestContext * cxt,int c)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 
TestTry(TestContext * cxt,int c)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 
TestR20ms(TestContext * cxt,int c)113 static void TestR20ms(TestContext *cxt, int c) {
114   for (int i = 0; i != cxt->iterations; i++) {
115     absl::ReaderMutexLock l(&cxt->mu);
116     absl::SleepFor(absl::Milliseconds(20));
117     cxt->mu.AssertReaderHeld();
118   }
119 }
120 
TestRW(TestContext * cxt,int c)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 
MyTurn()145 bool MyContext::MyTurn() {
146   TestContext *cxt = this->cxt;
147   return cxt->g0 == this->target || cxt->g0 == cxt->iterations;
148 }
149 
TestAwait(TestContext * cxt,int c)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 
TestSignalAll(TestContext * cxt,int c)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 
TestSignal(TestContext * cxt,int c)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 
TestCVTimeout(TestContext * cxt,int c)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 
G0GE2(TestContext * cxt)220 static bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; }
221 
TestTime(TestContext * cxt,int c,bool use_cv)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;
239     ABSL_RAW_CHECK(
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;
252     ABSL_RAW_CHECK(
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;
268     ABSL_RAW_CHECK(
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;
281     ABSL_RAW_CHECK(
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 {
306       ABSL_RAW_CHECK(
307           !cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)),
308           "TestTime failed");
309     }
310     const absl::Duration elapsed = absl::Now() - start;
311     ABSL_RAW_CHECK(
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 
TestMuTime(TestContext * cxt,int c)339 static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }
340 
TestCVTime(TestContext * cxt,int c)341 static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }
342 
EndTest(int * c0,int * c1,absl::Mutex * mu,absl::CondVar * cv,const std::function<void (int)> & cb)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().
RunTestCommon(TestContext * cxt,void (* test)(TestContext * cxt,int),int threads,int iterations,int operations)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;
365   absl::synchronization_internal::ThreadPool tp(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.
RunTest(void (* test)(TestContext * cxt,int),int threads,int iterations,int operations)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)
RunTestWithInvariantDebugging(void (* test)(TestContext * cxt,int),int threads,int iterations,int operations,void (* invariant)(void *))391 static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),
392                                          int threads, int iterations,
393                                          int operations,
394                                          void (*invariant)(void *)) {
395   absl::EnableMutexInvariantDebugging(true);
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 
WaitForA(TimeoutBugStruct * x)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 
NoAWaiters(TimeoutBugStruct * x)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.
TEST(Mutex,CondVarWaitSignalsAwait)424 TEST(Mutex, CondVarWaitSignalsAwait) {
425   // Use a struct so the lock annotations apply.
426   struct {
427     absl::Mutex barrier_mu;
428     bool barrier ABSL_GUARDED_BY(barrier_mu) = false;
429 
430     absl::Mutex release_mu;
431     bool release ABSL_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.
TEST(Mutex,CondVarWaitWithTimeoutSignalsAwait)465 TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {
466   // Use a struct so the lock annotations apply.
467   struct {
468     absl::Mutex barrier_mu;
469     bool barrier ABSL_GUARDED_BY(barrier_mu) = false;
470 
471     absl::Mutex release_mu;
472     bool release ABSL_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()
TEST(Mutex,MutexTimeoutBug)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 
CondVarWaitDeadlock__anon791c89e00111::CondVarWaitDeadlock543   CondVarWaitDeadlock() {
544     read_lock1 = GetParam() & (1 << 0);
545     read_lock2 = GetParam() & (1 << 1);
546     signal_unlocked = GetParam() & (1 << 2);
547   }
548 
Waiter1__anon791c89e00111::CondVarWaitDeadlock549   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 
Waiter2__anon791c89e00111::CondVarWaitDeadlock565   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.
TEST_P(CondVarWaitDeadlock,Test)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).
592   absl::SleepFor(absl::Milliseconds(100));
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()
AcquireAsReader(DequeueAllWakeableBugStruct * x)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.
640   absl::SleepFor(absl::Seconds(2));
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()
TEST(Mutex,MutexReaderWakeupBug)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 
LockWhenTestIsCond(LockWhenTestStruct * s)683 static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
684   s->mu2.Lock();
685   s->waiting = true;
686   s->mu2.Unlock();
687   return s->cond;
688 }
689 
LockWhenTestWaitForIsCond(LockWhenTestStruct * s)690 static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
691   s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));
692   s->mu1.Unlock();
693 }
694 
TEST(Mutex,LockWhen)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
IsCond(void * v)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
AllDone(void * v)744 static bool AllDone(void *v) {
745   ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
746   return x->done == 0;
747 }
748 
749 // L={}
WaitForCond(ReaderDecrementBugStruct * x)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={}
GetReadLock(ReaderDecrementBugStruct * x)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.
TEST(Mutex,MutexReaderDecrementBug)773 TEST(Mutex, MutexReaderDecrementBug) ABSL_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.
TEST(Mutex,DISABLED_LockedMutexDestructionBug)820 TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
821 #else
822 TEST(Mutex, LockedMutexDestructionBug) ABSL_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));
924   absl::SleepFor(absl::Seconds(2));
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) {
1008   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
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
1076   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);
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 
1097   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
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) ABSL_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) ABSL_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.
1131   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
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.
1149   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
1150   delete a;
1151   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
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.
1177 ABSL_MUST_USE_RESULT
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,
1266                           absl::synchronization_internal::ThreadPool *pool,
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
1480             ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value),
1481                                             start_time + params.wait_timeout)
1482             : mu.ReaderLockWhenWithTimeout(absl::Condition(&value),
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
1676