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 thread_local absl::BitGen gen; // NOLINT
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) || defined(__ANDROID__) || \
53 defined(__APPLE__) || defined(_WIN32) || defined(_WIN64)
54 constexpr absl::Duration kTimingBound = absl::Milliseconds(5);
55 #else
56 constexpr absl::Duration kTimingBound = absl::Microseconds(250);
57 #endif
58
59 using absl::synchronization_internal::KernelTimeout;
60
TEST(KernelTimeout,FiniteTimes)61 TEST(KernelTimeout, FiniteTimes) {
62 constexpr absl::Duration kDurationsToTest[] = {
63 absl::ZeroDuration(),
64 absl::Nanoseconds(1),
65 absl::Microseconds(1),
66 absl::Milliseconds(1),
67 absl::Seconds(1),
68 absl::Minutes(1),
69 absl::Hours(1),
70 absl::Hours(1000),
71 -absl::Nanoseconds(1),
72 -absl::Microseconds(1),
73 -absl::Milliseconds(1),
74 -absl::Seconds(1),
75 -absl::Minutes(1),
76 -absl::Hours(1),
77 -absl::Hours(1000),
78 };
79
80 for (auto duration : kDurationsToTest) {
81 const absl::Time now = absl::Now();
82 const absl::Time when = now + duration;
83 SCOPED_TRACE(duration);
84 KernelTimeout t(when);
85 EXPECT_TRUE(t.has_timeout());
86 EXPECT_TRUE(t.is_absolute_timeout());
87 EXPECT_FALSE(t.is_relative_timeout());
88 EXPECT_EQ(absl::TimeFromTimespec(t.MakeAbsTimespec()), when);
89 #ifndef _WIN32
90 EXPECT_LE(
91 absl::AbsDuration(absl::Now() + duration -
92 absl::TimeFromTimespec(
93 t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),
94 absl::Milliseconds(10));
95 #endif
96 EXPECT_LE(
97 absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -
98 std::max(duration, absl::ZeroDuration())),
99 kTimingBound);
100 EXPECT_EQ(absl::FromUnixNanos(t.MakeAbsNanos()), when);
101 EXPECT_LE(absl::AbsDuration(absl::Milliseconds(t.InMillisecondsFromNow()) -
102 std::max(duration, absl::ZeroDuration())),
103 absl::Milliseconds(5));
104 EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoTimePoint()) - when),
105 absl::Microseconds(1));
106 EXPECT_LE(absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) -
107 std::max(duration, absl::ZeroDuration())),
108 kTimingBound);
109 }
110 }
111
TEST(KernelTimeout,InfiniteFuture)112 TEST(KernelTimeout, InfiniteFuture) {
113 KernelTimeout t(absl::InfiniteFuture());
114 EXPECT_FALSE(t.has_timeout());
115 // Callers are expected to check has_timeout() instead of using the methods
116 // below, but we do try to do something reasonable if they don't. We may not
117 // be able to round-trip back to absl::InfiniteDuration() or
118 // absl::InfiniteFuture(), but we should return a very large value.
119 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
120 absl::Now() + absl::Hours(100000));
121 #ifndef _WIN32
122 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
123 absl::Now() + absl::Hours(100000));
124 #endif
125 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
126 absl::Hours(100000));
127 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
128 absl::Now() + absl::Hours(100000));
129 EXPECT_EQ(t.InMillisecondsFromNow(),
130 std::numeric_limits<KernelTimeout::DWord>::max());
131 EXPECT_EQ(t.ToChronoTimePoint(),
132 std::chrono::time_point<std::chrono::system_clock>::max());
133 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
134 }
135
TEST(KernelTimeout,DefaultConstructor)136 TEST(KernelTimeout, DefaultConstructor) {
137 // The default constructor is equivalent to absl::InfiniteFuture().
138 KernelTimeout t;
139 EXPECT_FALSE(t.has_timeout());
140 // Callers are expected to check has_timeout() instead of using the methods
141 // below, but we do try to do something reasonable if they don't. We may not
142 // be able to round-trip back to absl::InfiniteDuration() or
143 // absl::InfiniteFuture(), but we should return a very large value.
144 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
145 absl::Now() + absl::Hours(100000));
146 #ifndef _WIN32
147 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
148 absl::Now() + absl::Hours(100000));
149 #endif
150 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
151 absl::Hours(100000));
152 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
153 absl::Now() + absl::Hours(100000));
154 EXPECT_EQ(t.InMillisecondsFromNow(),
155 std::numeric_limits<KernelTimeout::DWord>::max());
156 EXPECT_EQ(t.ToChronoTimePoint(),
157 std::chrono::time_point<std::chrono::system_clock>::max());
158 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
159 }
160
TEST(KernelTimeout,TimeMaxNanos)161 TEST(KernelTimeout, TimeMaxNanos) {
162 // Time >= kMaxNanos should behave as no timeout.
163 KernelTimeout t(absl::FromUnixNanos(std::numeric_limits<int64_t>::max()));
164 EXPECT_FALSE(t.has_timeout());
165 // Callers are expected to check has_timeout() instead of using the methods
166 // below, but we do try to do something reasonable if they don't. We may not
167 // be able to round-trip back to absl::InfiniteDuration() or
168 // absl::InfiniteFuture(), but we should return a very large value.
169 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
170 absl::Now() + absl::Hours(100000));
171 #ifndef _WIN32
172 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
173 absl::Now() + absl::Hours(100000));
174 #endif
175 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
176 absl::Hours(100000));
177 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
178 absl::Now() + absl::Hours(100000));
179 EXPECT_EQ(t.InMillisecondsFromNow(),
180 std::numeric_limits<KernelTimeout::DWord>::max());
181 EXPECT_EQ(t.ToChronoTimePoint(),
182 std::chrono::time_point<std::chrono::system_clock>::max());
183 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
184 }
185
TEST(KernelTimeout,Never)186 TEST(KernelTimeout, Never) {
187 // KernelTimeout::Never() is equivalent to absl::InfiniteFuture().
188 KernelTimeout t = KernelTimeout::Never();
189 EXPECT_FALSE(t.has_timeout());
190 // Callers are expected to check has_timeout() instead of using the methods
191 // below, but we do try to do something reasonable if they don't. We may not
192 // be able to round-trip back to absl::InfiniteDuration() or
193 // absl::InfiniteFuture(), but we should return a very large value.
194 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
195 absl::Now() + absl::Hours(100000));
196 #ifndef _WIN32
197 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
198 absl::Now() + absl::Hours(100000));
199 #endif
200 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
201 absl::Hours(100000));
202 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
203 absl::Now() + absl::Hours(100000));
204 EXPECT_EQ(t.InMillisecondsFromNow(),
205 std::numeric_limits<KernelTimeout::DWord>::max());
206 EXPECT_EQ(t.ToChronoTimePoint(),
207 std::chrono::time_point<std::chrono::system_clock>::max());
208 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
209 }
210
TEST(KernelTimeout,InfinitePast)211 TEST(KernelTimeout, InfinitePast) {
212 KernelTimeout t(absl::InfinitePast());
213 EXPECT_TRUE(t.has_timeout());
214 EXPECT_TRUE(t.is_absolute_timeout());
215 EXPECT_FALSE(t.is_relative_timeout());
216 EXPECT_LE(absl::TimeFromTimespec(t.MakeAbsTimespec()),
217 absl::FromUnixNanos(1));
218 #ifndef _WIN32
219 EXPECT_LE(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
220 absl::FromUnixSeconds(1));
221 #endif
222 EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
223 absl::ZeroDuration());
224 EXPECT_LE(absl::FromUnixNanos(t.MakeAbsNanos()), absl::FromUnixNanos(1));
225 EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});
226 EXPECT_LT(t.ToChronoTimePoint(), std::chrono::system_clock::from_time_t(0) +
227 std::chrono::seconds(1));
228 EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));
229 }
230
TEST(KernelTimeout,FiniteDurations)231 TEST(KernelTimeout, FiniteDurations) {
232 constexpr absl::Duration kDurationsToTest[] = {
233 absl::ZeroDuration(),
234 absl::Nanoseconds(1),
235 absl::Microseconds(1),
236 absl::Milliseconds(1),
237 absl::Seconds(1),
238 absl::Minutes(1),
239 absl::Hours(1),
240 absl::Hours(1000),
241 };
242
243 for (auto duration : kDurationsToTest) {
244 SCOPED_TRACE(duration);
245 KernelTimeout t(duration);
246 EXPECT_TRUE(t.has_timeout());
247 EXPECT_FALSE(t.is_absolute_timeout());
248 EXPECT_TRUE(t.is_relative_timeout());
249 EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
250 absl::TimeFromTimespec(t.MakeAbsTimespec())),
251 absl::Milliseconds(5));
252 #ifndef _WIN32
253 EXPECT_LE(
254 absl::AbsDuration(absl::Now() + duration -
255 absl::TimeFromTimespec(
256 t.MakeClockAbsoluteTimespec(CLOCK_REALTIME))),
257 absl::Milliseconds(5));
258 #endif
259 EXPECT_LE(
260 absl::AbsDuration(absl::DurationFromTimespec(t.MakeRelativeTimespec()) -
261 duration),
262 kTimingBound);
263 EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
264 absl::FromUnixNanos(t.MakeAbsNanos())),
265 absl::Milliseconds(5));
266 EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,
267 absl::Milliseconds(5));
268 EXPECT_LE(absl::AbsDuration(absl::Now() + duration -
269 absl::FromChrono(t.ToChronoTimePoint())),
270 kTimingBound);
271 EXPECT_LE(
272 absl::AbsDuration(absl::FromChrono(t.ToChronoDuration()) - duration),
273 kTimingBound);
274 }
275 }
276
TEST(KernelTimeout,NegativeDurations)277 TEST(KernelTimeout, NegativeDurations) {
278 constexpr absl::Duration kDurationsToTest[] = {
279 -absl::ZeroDuration(),
280 -absl::Nanoseconds(1),
281 -absl::Microseconds(1),
282 -absl::Milliseconds(1),
283 -absl::Seconds(1),
284 -absl::Minutes(1),
285 -absl::Hours(1),
286 -absl::Hours(1000),
287 -absl::InfiniteDuration(),
288 };
289
290 for (auto duration : kDurationsToTest) {
291 // Negative durations should all be converted to zero durations or "now".
292 SCOPED_TRACE(duration);
293 KernelTimeout t(duration);
294 EXPECT_TRUE(t.has_timeout());
295 EXPECT_FALSE(t.is_absolute_timeout());
296 EXPECT_TRUE(t.is_relative_timeout());
297 EXPECT_LE(absl::AbsDuration(absl::Now() -
298 absl::TimeFromTimespec(t.MakeAbsTimespec())),
299 absl::Milliseconds(5));
300 #ifndef _WIN32
301 EXPECT_LE(absl::AbsDuration(absl::Now() - absl::TimeFromTimespec(
302 t.MakeClockAbsoluteTimespec(
303 CLOCK_REALTIME))),
304 absl::Milliseconds(5));
305 #endif
306 EXPECT_EQ(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
307 absl::ZeroDuration());
308 EXPECT_LE(
309 absl::AbsDuration(absl::Now() - absl::FromUnixNanos(t.MakeAbsNanos())),
310 absl::Milliseconds(5));
311 EXPECT_EQ(t.InMillisecondsFromNow(), KernelTimeout::DWord{0});
312 EXPECT_LE(absl::AbsDuration(absl::Now() -
313 absl::FromChrono(t.ToChronoTimePoint())),
314 absl::Milliseconds(5));
315 EXPECT_EQ(t.ToChronoDuration(), std::chrono::nanoseconds(0));
316 }
317 }
318
TEST(KernelTimeout,InfiniteDuration)319 TEST(KernelTimeout, InfiniteDuration) {
320 KernelTimeout t(absl::InfiniteDuration());
321 EXPECT_FALSE(t.has_timeout());
322 // Callers are expected to check has_timeout() instead of using the methods
323 // below, but we do try to do something reasonable if they don't. We may not
324 // be able to round-trip back to absl::InfiniteDuration() or
325 // absl::InfiniteFuture(), but we should return a very large value.
326 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
327 absl::Now() + absl::Hours(100000));
328 #ifndef _WIN32
329 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
330 absl::Now() + absl::Hours(100000));
331 #endif
332 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
333 absl::Hours(100000));
334 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
335 absl::Now() + absl::Hours(100000));
336 EXPECT_EQ(t.InMillisecondsFromNow(),
337 std::numeric_limits<KernelTimeout::DWord>::max());
338 EXPECT_EQ(t.ToChronoTimePoint(),
339 std::chrono::time_point<std::chrono::system_clock>::max());
340 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
341 }
342
TEST(KernelTimeout,DurationMaxNanos)343 TEST(KernelTimeout, DurationMaxNanos) {
344 // Duration >= kMaxNanos should behave as no timeout.
345 KernelTimeout t(absl::Nanoseconds(std::numeric_limits<int64_t>::max()));
346 EXPECT_FALSE(t.has_timeout());
347 // Callers are expected to check has_timeout() instead of using the methods
348 // below, but we do try to do something reasonable if they don't. We may not
349 // be able to round-trip back to absl::InfiniteDuration() or
350 // absl::InfiniteFuture(), but we should return a very large value.
351 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
352 absl::Now() + absl::Hours(100000));
353 #ifndef _WIN32
354 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
355 absl::Now() + absl::Hours(100000));
356 #endif
357 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
358 absl::Hours(100000));
359 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
360 absl::Now() + absl::Hours(100000));
361 EXPECT_EQ(t.InMillisecondsFromNow(),
362 std::numeric_limits<KernelTimeout::DWord>::max());
363 EXPECT_EQ(t.ToChronoTimePoint(),
364 std::chrono::time_point<std::chrono::system_clock>::max());
365 EXPECT_GE(t.ToChronoDuration(), std::chrono::nanoseconds::max());
366 }
367
TEST(KernelTimeout,OverflowNanos)368 TEST(KernelTimeout, OverflowNanos) {
369 // Test what happens when KernelTimeout is constructed with an absl::Duration
370 // that would overflow now_nanos + duration.
371 int64_t now_nanos = absl::ToUnixNanos(absl::Now());
372 int64_t limit = std::numeric_limits<int64_t>::max() - now_nanos;
373 absl::Duration duration = absl::Nanoseconds(limit) + absl::Seconds(1);
374 KernelTimeout t(duration);
375 // Timeouts should still be far in the future.
376 EXPECT_GT(absl::TimeFromTimespec(t.MakeAbsTimespec()),
377 absl::Now() + absl::Hours(100000));
378 #ifndef _WIN32
379 EXPECT_GT(absl::TimeFromTimespec(t.MakeClockAbsoluteTimespec(CLOCK_REALTIME)),
380 absl::Now() + absl::Hours(100000));
381 #endif
382 EXPECT_GT(absl::DurationFromTimespec(t.MakeRelativeTimespec()),
383 absl::Hours(100000));
384 EXPECT_GT(absl::FromUnixNanos(t.MakeAbsNanos()),
385 absl::Now() + absl::Hours(100000));
386 EXPECT_LE(absl::Milliseconds(t.InMillisecondsFromNow()) - duration,
387 absl::Milliseconds(5));
388 EXPECT_GT(t.ToChronoTimePoint(),
389 std::chrono::system_clock::now() + std::chrono::hours(100000));
390 EXPECT_GT(t.ToChronoDuration(), std::chrono::hours(100000));
391 }
392
393 } // namespace
394