xref: /aosp_15_r20/external/abseil-cpp/absl/synchronization/internal/waiter_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2023 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/internal/waiter.h"
16*9356374aSAndroid Build Coastguard Worker 
17*9356374aSAndroid Build Coastguard Worker #include <ctime>
18*9356374aSAndroid Build Coastguard Worker #include <iostream>
19*9356374aSAndroid Build Coastguard Worker #include <ostream>
20*9356374aSAndroid Build Coastguard Worker 
21*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
22*9356374aSAndroid Build Coastguard Worker #include "absl/random/random.h"
23*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/create_thread_identity.h"
24*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/futex_waiter.h"
25*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/kernel_timeout.h"
26*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/pthread_waiter.h"
27*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/sem_waiter.h"
28*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/stdcpp_waiter.h"
29*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/thread_pool.h"
30*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/win32_waiter.h"
31*9356374aSAndroid Build Coastguard Worker #include "absl/time/clock.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/time/time.h"
33*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
34*9356374aSAndroid Build Coastguard Worker 
35*9356374aSAndroid Build Coastguard Worker // Test go/btm support by randomizing the value of clock_gettime() for
36*9356374aSAndroid Build Coastguard Worker // CLOCK_MONOTONIC. This works by overriding a weak symbol in glibc.
37*9356374aSAndroid Build Coastguard Worker // We should be resistant to this randomization when !SupportsSteadyClock().
38*9356374aSAndroid Build Coastguard Worker #if defined(__GOOGLE_GRTE_VERSION__) &&      \
39*9356374aSAndroid Build Coastguard Worker     !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
40*9356374aSAndroid Build Coastguard Worker     !defined(ABSL_HAVE_MEMORY_SANITIZER) &&  \
41*9356374aSAndroid Build Coastguard Worker     !defined(ABSL_HAVE_THREAD_SANITIZER)
42*9356374aSAndroid Build Coastguard Worker extern "C" int __clock_gettime(clockid_t c, struct timespec* ts);
43*9356374aSAndroid Build Coastguard Worker 
clock_gettime(clockid_t c,struct timespec * ts)44*9356374aSAndroid Build Coastguard Worker extern "C" int clock_gettime(clockid_t c, struct timespec* ts) {
45*9356374aSAndroid Build Coastguard Worker   if (c == CLOCK_MONOTONIC &&
46*9356374aSAndroid Build Coastguard Worker       !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) {
47*9356374aSAndroid Build Coastguard Worker     thread_local absl::BitGen gen;  // NOLINT
48*9356374aSAndroid Build Coastguard Worker     ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000);
49*9356374aSAndroid Build Coastguard Worker     ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000);
50*9356374aSAndroid Build Coastguard Worker     return 0;
51*9356374aSAndroid Build Coastguard Worker   }
52*9356374aSAndroid Build Coastguard Worker   return __clock_gettime(c, ts);
53*9356374aSAndroid Build Coastguard Worker }
54*9356374aSAndroid Build Coastguard Worker #endif
55*9356374aSAndroid Build Coastguard Worker 
56*9356374aSAndroid Build Coastguard Worker namespace {
57*9356374aSAndroid Build Coastguard Worker 
TEST(Waiter,PrintPlatformImplementation)58*9356374aSAndroid Build Coastguard Worker TEST(Waiter, PrintPlatformImplementation) {
59*9356374aSAndroid Build Coastguard Worker   // Allows us to verify that the platform is using the expected implementation.
60*9356374aSAndroid Build Coastguard Worker   std::cout << absl::synchronization_internal::Waiter::kName << std::endl;
61*9356374aSAndroid Build Coastguard Worker }
62*9356374aSAndroid Build Coastguard Worker 
63*9356374aSAndroid Build Coastguard Worker template <typename T>
64*9356374aSAndroid Build Coastguard Worker class WaiterTest : public ::testing::Test {
65*9356374aSAndroid Build Coastguard Worker  public:
66*9356374aSAndroid Build Coastguard Worker   // Waiter implementations assume that a ThreadIdentity has already been
67*9356374aSAndroid Build Coastguard Worker   // created.
WaiterTest()68*9356374aSAndroid Build Coastguard Worker   WaiterTest() {
69*9356374aSAndroid Build Coastguard Worker     absl::synchronization_internal::GetOrCreateCurrentThreadIdentity();
70*9356374aSAndroid Build Coastguard Worker   }
71*9356374aSAndroid Build Coastguard Worker };
72*9356374aSAndroid Build Coastguard Worker 
73*9356374aSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(WaiterTest);
74*9356374aSAndroid Build Coastguard Worker 
WithTolerance(absl::Duration d)75*9356374aSAndroid Build Coastguard Worker absl::Duration WithTolerance(absl::Duration d) { return d * 0.95; }
76*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(WaiterTest,WaitNoTimeout)77*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(WaiterTest, WaitNoTimeout) {
78*9356374aSAndroid Build Coastguard Worker   absl::synchronization_internal::ThreadPool tp(1);
79*9356374aSAndroid Build Coastguard Worker   TypeParam waiter;
80*9356374aSAndroid Build Coastguard Worker   tp.Schedule([&]() {
81*9356374aSAndroid Build Coastguard Worker     // Include some `Poke()` calls to ensure they don't cause `waiter` to return
82*9356374aSAndroid Build Coastguard Worker     // from `Wait()`.
83*9356374aSAndroid Build Coastguard Worker     waiter.Poke();
84*9356374aSAndroid Build Coastguard Worker     absl::SleepFor(absl::Seconds(1));
85*9356374aSAndroid Build Coastguard Worker     waiter.Poke();
86*9356374aSAndroid Build Coastguard Worker     absl::SleepFor(absl::Seconds(1));
87*9356374aSAndroid Build Coastguard Worker     waiter.Post();
88*9356374aSAndroid Build Coastguard Worker   });
89*9356374aSAndroid Build Coastguard Worker   absl::Time start = absl::Now();
90*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(
91*9356374aSAndroid Build Coastguard Worker       waiter.Wait(absl::synchronization_internal::KernelTimeout::Never()));
92*9356374aSAndroid Build Coastguard Worker   absl::Duration waited = absl::Now() - start;
93*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(waited, WithTolerance(absl::Seconds(2)));
94*9356374aSAndroid Build Coastguard Worker }
95*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(WaiterTest,WaitDurationWoken)96*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(WaiterTest, WaitDurationWoken) {
97*9356374aSAndroid Build Coastguard Worker   absl::synchronization_internal::ThreadPool tp(1);
98*9356374aSAndroid Build Coastguard Worker   TypeParam waiter;
99*9356374aSAndroid Build Coastguard Worker   tp.Schedule([&]() {
100*9356374aSAndroid Build Coastguard Worker     // Include some `Poke()` calls to ensure they don't cause `waiter` to return
101*9356374aSAndroid Build Coastguard Worker     // from `Wait()`.
102*9356374aSAndroid Build Coastguard Worker     waiter.Poke();
103*9356374aSAndroid Build Coastguard Worker     absl::SleepFor(absl::Milliseconds(500));
104*9356374aSAndroid Build Coastguard Worker     waiter.Post();
105*9356374aSAndroid Build Coastguard Worker   });
106*9356374aSAndroid Build Coastguard Worker   absl::Time start = absl::Now();
107*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(waiter.Wait(
108*9356374aSAndroid Build Coastguard Worker       absl::synchronization_internal::KernelTimeout(absl::Seconds(10))));
109*9356374aSAndroid Build Coastguard Worker   absl::Duration waited = absl::Now() - start;
110*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
111*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(waited, absl::Seconds(2));
112*9356374aSAndroid Build Coastguard Worker }
113*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(WaiterTest,WaitTimeWoken)114*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(WaiterTest, WaitTimeWoken) {
115*9356374aSAndroid Build Coastguard Worker   absl::synchronization_internal::ThreadPool tp(1);
116*9356374aSAndroid Build Coastguard Worker   TypeParam waiter;
117*9356374aSAndroid Build Coastguard Worker   tp.Schedule([&]() {
118*9356374aSAndroid Build Coastguard Worker     // Include some `Poke()` calls to ensure they don't cause `waiter` to return
119*9356374aSAndroid Build Coastguard Worker     // from `Wait()`.
120*9356374aSAndroid Build Coastguard Worker     waiter.Poke();
121*9356374aSAndroid Build Coastguard Worker     absl::SleepFor(absl::Milliseconds(500));
122*9356374aSAndroid Build Coastguard Worker     waiter.Post();
123*9356374aSAndroid Build Coastguard Worker   });
124*9356374aSAndroid Build Coastguard Worker   absl::Time start = absl::Now();
125*9356374aSAndroid Build Coastguard Worker   EXPECT_TRUE(waiter.Wait(absl::synchronization_internal::KernelTimeout(
126*9356374aSAndroid Build Coastguard Worker       start + absl::Seconds(10))));
127*9356374aSAndroid Build Coastguard Worker   absl::Duration waited = absl::Now() - start;
128*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
129*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(waited, absl::Seconds(2));
130*9356374aSAndroid Build Coastguard Worker }
131*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(WaiterTest,WaitDurationReached)132*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(WaiterTest, WaitDurationReached) {
133*9356374aSAndroid Build Coastguard Worker   TypeParam waiter;
134*9356374aSAndroid Build Coastguard Worker   absl::Time start = absl::Now();
135*9356374aSAndroid Build Coastguard Worker   EXPECT_FALSE(waiter.Wait(
136*9356374aSAndroid Build Coastguard Worker       absl::synchronization_internal::KernelTimeout(absl::Milliseconds(500))));
137*9356374aSAndroid Build Coastguard Worker   absl::Duration waited = absl::Now() - start;
138*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
139*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(waited, absl::Seconds(1));
140*9356374aSAndroid Build Coastguard Worker }
141*9356374aSAndroid Build Coastguard Worker 
TYPED_TEST_P(WaiterTest,WaitTimeReached)142*9356374aSAndroid Build Coastguard Worker TYPED_TEST_P(WaiterTest, WaitTimeReached) {
143*9356374aSAndroid Build Coastguard Worker   TypeParam waiter;
144*9356374aSAndroid Build Coastguard Worker   absl::Time start = absl::Now();
145*9356374aSAndroid Build Coastguard Worker   EXPECT_FALSE(waiter.Wait(absl::synchronization_internal::KernelTimeout(
146*9356374aSAndroid Build Coastguard Worker       start + absl::Milliseconds(500))));
147*9356374aSAndroid Build Coastguard Worker   absl::Duration waited = absl::Now() - start;
148*9356374aSAndroid Build Coastguard Worker   EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
149*9356374aSAndroid Build Coastguard Worker   EXPECT_LT(waited, absl::Seconds(1));
150*9356374aSAndroid Build Coastguard Worker }
151*9356374aSAndroid Build Coastguard Worker 
152*9356374aSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(WaiterTest,
153*9356374aSAndroid Build Coastguard Worker                             WaitNoTimeout,
154*9356374aSAndroid Build Coastguard Worker                             WaitDurationWoken,
155*9356374aSAndroid Build Coastguard Worker                             WaitTimeWoken,
156*9356374aSAndroid Build Coastguard Worker                             WaitDurationReached,
157*9356374aSAndroid Build Coastguard Worker                             WaitTimeReached);
158*9356374aSAndroid Build Coastguard Worker 
159*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_FUTEX_WAITER
160*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Futex, WaiterTest,
161*9356374aSAndroid Build Coastguard Worker                                absl::synchronization_internal::FutexWaiter);
162*9356374aSAndroid Build Coastguard Worker #endif
163*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_PTHREAD_WAITER
164*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Pthread, WaiterTest,
165*9356374aSAndroid Build Coastguard Worker                                absl::synchronization_internal::PthreadWaiter);
166*9356374aSAndroid Build Coastguard Worker #endif
167*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_SEM_WAITER
168*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Sem, WaiterTest,
169*9356374aSAndroid Build Coastguard Worker                                absl::synchronization_internal::SemWaiter);
170*9356374aSAndroid Build Coastguard Worker #endif
171*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_WIN32_WAITER
172*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Win32, WaiterTest,
173*9356374aSAndroid Build Coastguard Worker                                absl::synchronization_internal::Win32Waiter);
174*9356374aSAndroid Build Coastguard Worker #endif
175*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER
176*9356374aSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Stdcpp, WaiterTest,
177*9356374aSAndroid Build Coastguard Worker                                absl::synchronization_internal::StdcppWaiter);
178*9356374aSAndroid Build Coastguard Worker #endif
179*9356374aSAndroid Build Coastguard Worker 
180*9356374aSAndroid Build Coastguard Worker }  // namespace
181