abseil-cpp/absl/synchronization/mutex_test.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
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 
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>
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.
59 static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,
61  const std::function<void()> &func) {
62  tp->Schedule([func, 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
75 };
76 
77 // To test whether the invariant check call occurs
78 static std::atomic<bool> invariant_checked;
79 
80 static bool GetInvariantChecked() {
81  return invariant_checked.load(std::memory_order_relaxed);
82 }
83 
84 static void SetInvariantChecked(bool new_value) {
85  invariant_checked.store(new_value, std::memory_order_relaxed);
86 }
87 
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 
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 
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 
115 static void TestR20ms(TestContext *cxt, int c) {
116  for (int i = 0; i != cxt->iterations; i++) {
117  absl::ReaderMutexLock l(&cxt->mu);
119  cxt->mu.AssertReaderHeld();
120  }
121 }
122 
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 
147 bool MyContext::MyTurn() {
148  TestContext *cxt = this->cxt;
149  return cxt->g0 == this->target || cxt->g0 == cxt->iterations;
150 }
151 
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 
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 
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 
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 
222 static bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; }
223 
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 
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;
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;
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;
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;
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 {
309  !cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)),
310  "TestTime failed");
311  }
312  const absl::Duration elapsed = absl::Now() - start;
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 
341 static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }
342 
343 static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }
344 
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);
352  (*c1)++;
353  cv->Signal();
354 }
355 
356 // Code common to RunTest() and RunTestWithInvariantDebugging().
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;
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.
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)
393 static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),
394  int threads, int iterations,
395  int operations,
396  void (*invariant)(void *)) {
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 
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 
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.
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.
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()
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;
539  bool cond1 = false;
540  bool cond2 = false;
541  bool read_lock1;
542  bool read_lock2;
543  bool signal_unlocked;
544 
545  CondVarWaitDeadlock() {
546  read_lock1 = GetParam() & (1 << 0);
547  read_lock2 = GetParam() & (1 << 1);
548  signal_unlocked = GetParam() & (1 << 2);
549  }
550 
551  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 
567  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.
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).
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),
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()
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.
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()
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 
685 static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
686  s->mu2.Lock();
687  s->waiting = true;
688  s->mu2.Unlock();
689  return s->cond;
690 }
691 
692 static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
693  s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));
694  s->mu1.Unlock();
695 }
696 
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 
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
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
780 static bool AllDone(void *v) {
781  ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
782  return x->done == 0;
783 }
784 
785 // L={}
786 static void WaitForCond(ReaderDecrementBugStruct *x) {
789  x->mu.LockWhen(absl::Condition(&IsCond, x));
790  x->done--;
791  x->mu.Unlock();
792 }
793 
794 // L={}
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.
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.
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;
957  int running = 3;
958  tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
959  tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
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) {
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
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 
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.
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.
1183  delete a;
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.
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) {
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) {
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,
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();
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);
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 
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 
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);
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()),
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
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
ABSL_RAW_CHECK
#define ABSL_RAW_CHECK(condition, message)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:59
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
absl::internal_any_invocable::True
std::integral_constant< bool, sizeof(absl::void_t< T... > *) !=0 > True
Definition: internal/any_invocable.h:687
absl::str_format_internal::LengthMod::j
@ j
testing::WithParamInterface
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1848
bool
bool
Definition: setup_once.h:312
absl::ZeroDuration
constexpr Duration ZeroDuration()
Definition: third_party/abseil-cpp/absl/time/time.h:308
invariant
void(* invariant)(void *arg)
Definition: abseil-cpp/absl/synchronization/mutex.cc:308
absl::synchronization_internal::ThreadPool
Definition: third_party/abseil-cpp/absl/synchronization/internal/thread_pool.h:33
absl::Time
Definition: third_party/abseil-cpp/absl/time/time.h:642
file
const grpc_generator::File * file
Definition: python_private_generator.h:38
absl::Mutex
Definition: abseil-cpp/absl/synchronization/mutex.h:131
test
Definition: spinlock_test.cc:36
absl::Mutex::Unlock
void Unlock() ABSL_UNLOCK_FUNCTION()
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
ABSL_GUARDED_BY
#define ABSL_GUARDED_BY(x)
Definition: abseil-cpp/absl/base/thread_annotations.h:62
absl::Mutex::ReaderLock
void ReaderLock() ABSL_SHARED_LOCK_FUNCTION()
absl::FormatConversionChar::s
@ s
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
testing::Range
internal::ParamGenerator< T > Range(T start, T end, IncrementT step)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:229
absl::SleepFor
void SleepFor(absl::Duration duration)
Definition: abseil-cpp/absl/time/clock.h:70
xds_manager.p
p
Definition: xds_manager.py:60
start_time
static int64_t start_time
Definition: benchmark-getaddrinfo.c:37
absl::Mutex::ForgetDeadlockInfo
void ForgetDeadlockInfo()
Definition: abseil-cpp/absl/synchronization/mutex.cc:1421
threads
static uv_thread_t * threads
Definition: threadpool.c:38
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
testing::TestWithParam
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1883
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
absl::CondVar::EnableDebugLog
void EnableDebugLog(const char *name)
Definition: abseil-cpp/absl/synchronization/mutex.cc:2456
benchmark::FormatString
std::string FormatString(const char *msg, va_list args)
Definition: benchmark/src/colorprint.cc:85
ABSL_MUST_USE_RESULT
#define ABSL_MUST_USE_RESULT
Definition: abseil-cpp/absl/base/attributes.h:441
absl::Milliseconds
constexpr Duration Milliseconds(T n)
Definition: third_party/abseil-cpp/absl/time/time.h:415
absl::MutexLock
Definition: abseil-cpp/absl/synchronization/mutex.h:525
absl::OnDeadlockCycle::kIgnore
@ kIgnore
absl::Mutex::EnableDebugLog
void EnableDebugLog(const char *name)
Definition: abseil-cpp/absl/synchronization/mutex.cc:741
start
static uint64_t start
Definition: benchmark-pound.c:74
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
hpack_encoder_fixtures::Args
Args({0, 16384})
grpc_core::TestContext
promise_detail::Context< T > TestContext
Definition: test_context.h:23
absl::WriterMutexLock
Definition: abseil-cpp/absl/synchronization/mutex.h:587
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
TEST
#define TEST(name, init_size,...)
Definition: arena_test.cc:75
TEST_P
#define TEST_P(test_suite_name, test_name)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:414
python_utils.jobset.INFO
INFO
Definition: jobset.py:111
mu
Mutex mu
Definition: server_config_selector_filter.cc:74
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
absl::Mutex::Lock
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION()
cond
static uv_cond_t cond
Definition: threadpool.c:33
done
struct tab * done
Definition: bloaty/third_party/zlib/examples/enough.c:176
absl::Duration
Definition: third_party/abseil-cpp/absl/time/time.h:159
negative
static uint8_t negative(signed char b)
Definition: curve25519.c:786
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
google::protobuf::WARNING
static const LogLevel WARNING
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.h:71
callback
static void callback(void *arg, int status, int timeouts, struct hostent *host)
Definition: acountry.c:224
gen
OPENSSL_EXPORT GENERAL_NAME * gen
Definition: x509v3.h:495
running
static const char running[]
Definition: benchmark-async-pummel.c:34
absl::Condition
Definition: abseil-cpp/absl/synchronization/mutex.h:663
min
#define min(a, b)
Definition: qsort.h:83
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
g
struct @717 g
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
absl::FormatDuration
std::string FormatDuration(Duration d)
Definition: abseil-cpp/absl/time/duration.cc:768
after
IntAfterTypedTestSuiteP after
Definition: googletest/googletest/test/gtest-typed-test_test.cc:375
absl::CondVar::Wait
void Wait(Mutex *mu)
Definition: abseil-cpp/absl/synchronization/mutex.cc:2628
grpc_core::never
Poll< int > never()
Definition: race_test.cc:24
value
const char * value
Definition: hpack_parser_table.cc:165
absl::Seconds
constexpr Duration Seconds(T n)
Definition: third_party/abseil-cpp/absl/time/time.h:419
absl::Mutex::ReaderUnlock
void ReaderUnlock() ABSL_UNLOCK_FUNCTION()
absl::hash_internal::c1
static const uint32_t c1
Definition: abseil-cpp/absl/hash/internal/city.cc:58
absl::Now
ABSL_NAMESPACE_BEGIN Time Now()
Definition: abseil-cpp/absl/time/clock.cc:39
absl::ReaderMutexLock
Definition: abseil-cpp/absl/synchronization/mutex.h:560
func
const EVP_CIPHER *(* func)(void)
Definition: cipher_extra.c:73
cv
unsigned cv
Definition: cxa_demangle.cpp:4908
absl::CondVar
Definition: abseil-cpp/absl/synchronization/mutex.h:798
absl::str_format_internal::LengthMod::t
@ t
testing::PrintToStringParamName
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-param-util.h:66
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
google::protobuf.internal::Mutex
WrappedMutex Mutex
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/mutex.h:113
values
std::array< int64_t, Size > values
Definition: abseil-cpp/absl/container/btree_benchmark.cc:608
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
absl::CondVar::SignalAll
void SignalAll()
Definition: abseil-cpp/absl/synchronization/mutex.cc:2689
absl::ABSL_NAMESPACE_BEGIN::dummy
int dummy
Definition: function_type_benchmark.cc:28
release
return ret release()
Definition: doc/python/sphinx/conf.py:37
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
pool
InternalDescriptorPool * pool
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:807
absl::EnableMutexInvariantDebugging
void EnableMutexInvariantDebugging(bool enabled)
Definition: abseil-cpp/absl/synchronization/mutex.cc:747
RunTest
static void RunTest(RandomDistInterface &&r, int threads, const std::string &title)
Definition: qps_interarrival_test.cc:31
testing::ValuesIn
internal::ParamGenerator< typename std::iterator_traits< ForwardIterator >::value_type > ValuesIn(ForwardIterator begin, ForwardIterator end)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:297
absl::CondVar::Signal
void Signal()
Definition: abseil-cpp/absl/synchronization/mutex.cc:2649
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
grpc::operator<<
std::ostream & operator<<(std::ostream &out, const string_ref &string)
Definition: grpcpp/impl/codegen/string_ref.h:145
absl::InfiniteDuration
constexpr Duration InfiniteDuration()
Definition: third_party/abseil-cpp/absl/time/time.h:1573
absl::OnDeadlockCycle::kAbort
@ kAbort
t1
Table t1
Definition: abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc:185
getenv
#define getenv(ptr)
Definition: ares_private.h:106
absl::Mutex::TryLock
bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true)
ABSL_RAW_LOG
#define ABSL_RAW_LOG(severity,...)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:44
absl::SetMutexDeadlockDetectionMode
void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode)
Definition: abseil-cpp/absl/synchronization/mutex.cc:762
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
absl::CondVar::WaitWithTimeout
bool WaitWithTimeout(Mutex *mu, absl::Duration timeout)
Definition: abseil-cpp/absl/synchronization/mutex.cc:2620
top
static upb_pb_encoder_segment * top(upb_pb_encoder *e)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:7624
thread
static uv_thread_t thread
Definition: test-async-null-cb.c:29
Test
Definition: hpack_parser_test.cc:43
timeout
uv_timer_t timeout
Definition: libuv/docs/code/uvwget/main.c:9
cb
OPENSSL_EXPORT pem_password_cb * cb
Definition: pem.h:351
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
state
static struct rpc_state state
Definition: bad_server_response_test.cc:87
absl::OnDeadlockCycle::kReport
@ kReport
absl::synchronization_internal::ThreadPool::Schedule
void Schedule(std::function< void()> func)
Definition: third_party/abseil-cpp/absl/synchronization/internal/thread_pool.h:57
ABSL_NO_THREAD_SAFETY_ANALYSIS
#define ABSL_NO_THREAD_SAFETY_ANALYSIS
Definition: abseil-cpp/absl/base/thread_annotations.h:280
INSTANTIATE_TEST_SUITE_P
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name,...)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:460


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:31