1 // Copyright 2023 The Abseil Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/synchronization/internal/kernel_timeout.h"
16
17 #include <ctime>
18 #include <chrono> // NOLINT(build/c++11)
19 #include <limits>
20
21 #include "absl/base/config.h"
22 #include "absl/random/random.h"
23 #include "absl/time/clock.h"
24 #include "absl/time/time.h"
25 #include "gtest/gtest.h"
26
27 // Test go/btm support by randomizing the value of clock_gettime() for
28 // CLOCK_MONOTONIC. This works by overriding a weak symbol in glibc.
29 // We should be resistant to this randomization when !SupportsSteadyClock().
30 #if defined(__GOOGLE_GRTE_VERSION__) && \
31 !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
32 !defined(ABSL_HAVE_MEMORY_SANITIZER) && \
33 !defined(ABSL_HAVE_THREAD_SANITIZER)
34 extern "C" int __clock_gettime(clockid_t c, struct timespec* ts);
35
clock_gettime(clockid_t c,struct timespec * ts)36 extern "C" int clock_gettime(clockid_t c, struct timespec* ts) {
37 if (c == CLOCK_MONOTONIC &&
38 !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) {
39 absl::SharedBitGen gen;
40 ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000);
41 ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000);
42 return 0;
43 }
44 return __clock_gettime(c, ts);
45 }
46 #endif
47
48 namespace {
49
50 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
51 defined(ABSL_HAVE_MEMORY_SANITIZER) || \
52 defined(ABSL_HAVE_THREAD_SANITIZER) || \
53 defined(__ANDROID__) || \
54 defined(_WIN32) || defined(_WIN64)
55 constexpr absl::Duration kTimingBound = absl::Milliseconds(5);
56 #else
57 constexpr absl::Duration kTimingBound = absl::Microseconds(250);
58 #endif
59
60 using absl::synchronization_internal::KernelTimeout;
61
TEST(KernelTimeout,FiniteTimes)62 TEST(KernelTimeout, FiniteTimes) {
63 constexpr absl::Duration kDurationsToTest[] = {
64 absl::ZeroDuration(),
65 absl::Nanoseconds(1),
66 absl::Microseconds(1),
67 absl::Milliseconds(1),
68 absl::Seconds(1),
69 absl::Minutes(1),
70 absl::Hours(1),
71 absl::Hours(1000),
72 -absl::Nanoseconds(1),
73 -absl::Microseconds(1),
74 -absl::Milliseconds(1),
75 -absl::Seconds(1),
76 -absl::Minutes(1),
77 -absl::Hours(1),
78 -absl::Hours(1000),
79 };
80
81 for (auto duration : kDurationsToTest) {
82 const absl::Time now = absl::Now();
83 const absl::Time when = now + duration;
84 SCOPED_TRACE(duration);
85 KernelTimeout t(when);
86 EXPECT_TRUE(t.has_timeout());
87 EXPECT_TRUE(t.is_absolute_timeout());
88 EXPECT_FALSE(t.is_relative_timeout());
89 EXPECT_EQ(absl::TimeFromTimespec(t.MakeAbsTimespec()), when);
90 #ifndef _WIN32
91 EXPECT_LE(
92 absl::AbsDuration(absl::Now() + duration -
93 absl::TimeFromTimespec(
94 t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),
95 absl::Milliseconds(10));
96 #endif
97 EXPECT_LE(
98 absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -
99 std::max(duration, absl::ZeroDuration())),
100 kTimingBound);
101 EXPECT_EQ(absl::FromUnixNanos(t.MakeAbsNanos()), when);
102 EXPECT_LE(absl::AbsDuration(absl::Milliseconds(t.InMillisecondsFromNow()) -
103 std::max(duration, absl::ZeroDuration())),
104 absl::Milliseconds(5));
105 EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoTimePoint()) - when),
106 absl::Microseconds(1));
107 EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) -
108 std::max(duration, absl::ZeroDuration())),
109 kTimingBound);
110 }
111 }
112
TEST(KernelTimeout,InfiniteFuture)113 TEST(KernelTimeout, InfiniteFuture) {
114 KernelTimeout t(absl::InfiniteFuture());
115 EXPECT_FALSE(t.has_timeout());
116 // Callers are expected to check has_timeout() instead of using the methods
117 // below, but we do try to do something reasonable if they don't. We may not
118 // be able to round-trip back to absl::InfiniteDuration() or
119 // absl::InfiniteFuture(), but we should return a very large value.
120 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
121 absl::Now() + absl::Hours(100000));
122 #ifndef _WIN32
123 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
124 absl::Now() + absl::Hours(100000));
125 #endif
126 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
127 absl::Hours(100000));
128 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
129 absl::Now() + absl::Hours(100000));
130 EXPECT_EQ(t.InMillisecondsFromNow(),
131 std::numeric_limits<KernelTimeout::DWord>::max());
132 EXPECT_EQ(t.ToChronoTimePoint(),
133 std::chrono::time_point<std::chrono::system_clock>::max());
134 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
135 }
136
TEST(KernelTimeout,DefaultConstructor)137 TEST(KernelTimeout, DefaultConstructor) {
138 // The default constructor is equivalent to absl::InfiniteFuture().
139 KernelTimeout t;
140 EXPECT_FALSE(t.has_timeout());
141 // Callers are expected to check has_timeout() instead of using the methods
142 // below, but we do try to do something reasonable if they don't. We may not
143 // be able to round-trip back to absl::InfiniteDuration() or
144 // absl::InfiniteFuture(), but we should return a very large value.
145 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
146 absl::Now() + absl::Hours(100000));
147 #ifndef _WIN32
148 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
149 absl::Now() + absl::Hours(100000));
150 #endif
151 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
152 absl::Hours(100000));
153 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
154 absl::Now() + absl::Hours(100000));
155 EXPECT_EQ(t.InMillisecondsFromNow(),
156 std::numeric_limits<KernelTimeout::DWord>::max());
157 EXPECT_EQ(t.ToChronoTimePoint(),
158 std::chrono::time_point<std::chrono::system_clock>::max());
159 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
160 }
161
TEST(KernelTimeout,TimeMaxNanos)162 TEST(KernelTimeout, TimeMaxNanos) {
163 // Time >= kMaxNanos should behave as no timeout.
164 KernelTimeout t(absl::FromUnixNanos(std::numeric_limits<int64_t>::max()));
165 EXPECT_FALSE(t.has_timeout());
166 // Callers are expected to check has_timeout() instead of using the methods
167 // below, but we do try to do something reasonable if they don't. We may not
168 // be able to round-trip back to absl::InfiniteDuration() or
169 // absl::InfiniteFuture(), but we should return a very large value.
170 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
171 absl::Now() + absl::Hours(100000));
172 #ifndef _WIN32
173 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
174 absl::Now() + absl::Hours(100000));
175 #endif
176 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
177 absl::Hours(100000));
178 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
179 absl::Now() + absl::Hours(100000));
180 EXPECT_EQ(t.InMillisecondsFromNow(),
181 std::numeric_limits<KernelTimeout::DWord>::max());
182 EXPECT_EQ(t.ToChronoTimePoint(),
183 std::chrono::time_point<std::chrono::system_clock>::max());
184 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
185 }
186
TEST(KernelTimeout,Never)187 TEST(KernelTimeout, Never) {
188 // KernelTimeout::Never() is equivalent to absl::InfiniteFuture().
189 KernelTimeout t = KernelTimeout::Never();
190 EXPECT_FALSE(t.has_timeout());
191 // Callers are expected to check has_timeout() instead of using the methods
192 // below, but we do try to do something reasonable if they don't. We may not
193 // be able to round-trip back to absl::InfiniteDuration() or
194 // absl::InfiniteFuture(), but we should return a very large value.
195 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
196 absl::Now() + absl::Hours(100000));
197 #ifndef _WIN32
198 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
199 absl::Now() + absl::Hours(100000));
200 #endif
201 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
202 absl::Hours(100000));
203 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
204 absl::Now() + absl::Hours(100000));
205 EXPECT_EQ(t.InMillisecondsFromNow(),
206 std::numeric_limits<KernelTimeout::DWord>::max());
207 EXPECT_EQ(t.ToChronoTimePoint(),
208 std::chrono::time_point<std::chrono::system_clock>::max());
209 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
210 }
211
TEST(KernelTimeout,InfinitePast)212 TEST(KernelTimeout, InfinitePast) {
213 KernelTimeout t(absl::InfinitePast());
214 EXPECT_TRUE(t.has_timeout());
215 EXPECT_TRUE(t.is_absolute_timeout());
216 EXPECT_FALSE(t.is_relative_timeout());
217 EXPECT_LE(absl::TimeFromTimespec(t.MakeAbsTimespec()),
218 absl::FromUnixNanos(1));
219 #ifndef _WIN32
220 EXPECT_LE(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
221 absl::FromUnixSeconds(1));
222 #endif
223 EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
224 absl::ZeroDuration());
225 EXPECT_LE(absl::FromUnixNanos(t.MakeAbsNanos()), absl::FromUnixNanos(1));
226 EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});
227 EXPECT_LT(t.ToChronoTimePoint(), std::chrono::system_clock::from_time_t(0) +
228 std::chrono::seconds(1));
229 EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));
230 }
231
TEST(KernelTimeout,FiniteDurations)232 TEST(KernelTimeout, FiniteDurations) {
233 constexpr absl::Duration kDurationsToTest[] = {
234 absl::ZeroDuration(),
235 absl::Nanoseconds(1),
236 absl::Microseconds(1),
237 absl::Milliseconds(1),
238 absl::Seconds(1),
239 absl::Minutes(1),
240 absl::Hours(1),
241 absl::Hours(1000),
242 };
243
244 for (auto duration : kDurationsToTest) {
245 SCOPED_TRACE(duration);
246 KernelTimeout t(duration);
247 EXPECT_TRUE(t.has_timeout());
248 EXPECT_FALSE(t.is_absolute_timeout());
249 EXPECT_TRUE(t.is_relative_timeout());
250 EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
251 absl::TimeFromTimespec(t.MakeAbsTimespec())),
252 absl::Milliseconds(5));
253 #ifndef _WIN32
254 EXPECT_LE(
255 absl::AbsDuration(absl::Now() + duration -
256 absl::TimeFromTimespec(
257 t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),
258 absl::Milliseconds(5));
259 #endif
260 EXPECT_LE(
261 absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -
262 duration),
263 kTimingBound);
264 EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
265 absl::FromUnixNanos(t.MakeAbsNanos())),
266 absl::Milliseconds(5));
267 EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,
268 absl::Milliseconds(5));
269 EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
270 absl::FromChrono(t.ToChronoTimePoint())),
271 kTimingBound);
272 EXPECT_LE(
273 absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - duration),
274 kTimingBound);
275 }
276 }
277
TEST(KernelTimeout,NegativeDurations)278 TEST(KernelTimeout, NegativeDurations) {
279 constexpr absl::Duration kDurationsToTest[] = {
280 -absl::ZeroDuration(),
281 -absl::Nanoseconds(1),
282 -absl::Microseconds(1),
283 -absl::Milliseconds(1),
284 -absl::Seconds(1),
285 -absl::Minutes(1),
286 -absl::Hours(1),
287 -absl::Hours(1000),
288 -absl::InfiniteDuration(),
289 };
290
291 for (auto duration : kDurationsToTest) {
292 // Negative durations should all be converted to zero durations or "now".
293 SCOPED_TRACE(duration);
294 KernelTimeout t(duration);
295 EXPECT_TRUE(t.has_timeout());
296 EXPECT_FALSE(t.is_absolute_timeout());
297 EXPECT_TRUE(t.is_relative_timeout());
298 EXPECT_LE(absl::AbsDuration(absl::Now() -
299 absl::TimeFromTimespec(t.MakeAbsTimespec())),
300 absl::Milliseconds(5));
301 #ifndef _WIN32
302 EXPECT_LE(absl::AbsDuration(absl::Now() - absl::TimeFromTimespec(
303 t.MakeClockAbsoluteTimespec(
304 CLOCK_REALTIME))),
305 absl::Milliseconds(5));
306 #endif
307 EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
308 absl::ZeroDuration());
309 EXPECT_LE(
310 absl::AbsDuration(absl::Now() - absl::FromUnixNanos(t.MakeAbsNanos())),
311 absl::Milliseconds(5));
312 EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});
313 EXPECT_LE(absl::AbsDuration(absl::Now() -
314 absl::FromChrono(t.ToChronoTimePoint())),
315 absl::Milliseconds(5));
316 EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));
317 }
318 }
319
TEST(KernelTimeout,InfiniteDuration)320 TEST(KernelTimeout, InfiniteDuration) {
321 KernelTimeout t(absl::InfiniteDuration());
322 EXPECT_FALSE(t.has_timeout());
323 // Callers are expected to check has_timeout() instead of using the methods
324 // below, but we do try to do something reasonable if they don't. We may not
325 // be able to round-trip back to absl::InfiniteDuration() or
326 // absl::InfiniteFuture(), but we should return a very large value.
327 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
328 absl::Now() + absl::Hours(100000));
329 #ifndef _WIN32
330 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
331 absl::Now() + absl::Hours(100000));
332 #endif
333 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
334 absl::Hours(100000));
335 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
336 absl::Now() + absl::Hours(100000));
337 EXPECT_EQ(t.InMillisecondsFromNow(),
338 std::numeric_limits<KernelTimeout::DWord>::max());
339 EXPECT_EQ(t.ToChronoTimePoint(),
340 std::chrono::time_point<std::chrono::system_clock>::max());
341 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
342 }
343
TEST(KernelTimeout,DurationMaxNanos)344 TEST(KernelTimeout, DurationMaxNanos) {
345 // Duration >= kMaxNanos should behave as no timeout.
346 KernelTimeout t(absl::Nanoseconds(std::numeric_limits<int64_t>::max()));
347 EXPECT_FALSE(t.has_timeout());
348 // Callers are expected to check has_timeout() instead of using the methods
349 // below, but we do try to do something reasonable if they don't. We may not
350 // be able to round-trip back to absl::InfiniteDuration() or
351 // absl::InfiniteFuture(), but we should return a very large value.
352 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
353 absl::Now() + absl::Hours(100000));
354 #ifndef _WIN32
355 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
356 absl::Now() + absl::Hours(100000));
357 #endif
358 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
359 absl::Hours(100000));
360 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
361 absl::Now() + absl::Hours(100000));
362 EXPECT_EQ(t.InMillisecondsFromNow(),
363 std::numeric_limits<KernelTimeout::DWord>::max());
364 EXPECT_EQ(t.ToChronoTimePoint(),
365 std::chrono::time_point<std::chrono::system_clock>::max());
366 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
367 }
368
TEST(KernelTimeout,OverflowNanos)369 TEST(KernelTimeout, OverflowNanos) {
370 // Test what happens when KernelTimeout is constructed with an absl::Duration
371 // that would overflow now_nanos + duration.
372 int64_t now_nanos = absl::ToUnixNanos(absl::Now());
373 int64_t limit = std::numeric_limits<int64_t>::max() - now_nanos;
374 absl::Duration duration = absl::Nanoseconds(limit) + absl::Seconds(1);
375 KernelTimeout t(duration);
376 // Timeouts should still be far in the future.
377 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
378 absl::Now() + absl::Hours(100000));
379 #ifndef _WIN32
380 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
381 absl::Now() + absl::Hours(100000));
382 #endif
383 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
384 absl::Hours(100000));
385 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
386 absl::Now() + absl::Hours(100000));
387 EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,
388 absl::Milliseconds(5));
389 EXPECT_GT(t.ToChronoTimePoint(),
390 std::chrono::system_clock::now() + std::chrono::hours(100000));
391 EXPECT_GT(t.ToChronoDuration(), std::chrono::hours(100000));
392 }
393
394 } // namespace
395