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