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