/Users/deen/code/yugabyte-db/src/yb/util/monotime.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | |
33 | | #include "yb/util/monotime.h" |
34 | | |
35 | | #include <glog/logging.h> |
36 | | |
37 | | #include "yb/gutil/casts.h" |
38 | | #include "yb/gutil/stringprintf.h" |
39 | | #include "yb/gutil/sysinfo.h" |
40 | | |
41 | | #include "yb/util/result.h" |
42 | | #include "yb/util/thread_restrictions.h" |
43 | | |
44 | | #if defined(__APPLE__) |
45 | | #include "yb/gutil/walltime.h" |
46 | | #endif |
47 | | |
48 | | using namespace std::literals; |
49 | | |
50 | | namespace yb { |
51 | | |
52 | | #define MAX_MONOTONIC_SECONDS \ |
53 | | (((1ULL<<63) - 1ULL) /(int64_t)MonoTime::kNanosecondsPerSecond) |
54 | | |
55 | | namespace { |
56 | | |
57 | 2.07M | bool SafeToAdd64(int64_t a, int64_t b) { |
58 | 2.07M | bool negativeA = a < 0; |
59 | 2.07M | bool negativeB = b < 0; |
60 | 2.07M | if (negativeA != negativeB) { |
61 | 140 | return true; |
62 | 140 | } |
63 | 2.07M | bool negativeSum = (a + b) < 0; |
64 | 2.07M | return negativeSum == negativeA; |
65 | 2.07M | } |
66 | | |
67 | | } // namespace |
68 | | |
69 | | /// |
70 | | /// MonoDelta |
71 | | /// |
72 | | |
73 | | const MonoDelta::NanoDeltaType MonoDelta::kUninitialized = |
74 | | std::numeric_limits<NanoDeltaType>::min(); |
75 | | const MonoDelta MonoDelta::kMin = MonoDelta(std::numeric_limits<NanoDeltaType>::min() + 1); |
76 | | const MonoDelta MonoDelta::kMax = MonoDelta(std::numeric_limits<NanoDeltaType>::max()); |
77 | | const MonoDelta MonoDelta::kZero = MonoDelta(0); |
78 | | |
79 | | template <class V> |
80 | 89.2M | MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) { |
81 | 89.2M | CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul); |
82 | 89.2M | int64_t delta = value * mul; |
83 | 89.2M | return MonoDelta::FromNanoseconds(delta); |
84 | 89.2M | } _ZN2yb25MonoDeltaByMultiplicationIdEENS_9MonoDeltaET_x Line | Count | Source | 80 | 354k | MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) { | 81 | 354k | CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul); | 82 | 354k | int64_t delta = value * mul; | 83 | 354k | return MonoDelta::FromNanoseconds(delta); | 84 | 354k | } |
_ZN2yb25MonoDeltaByMultiplicationIxEENS_9MonoDeltaET_x Line | Count | Source | 80 | 88.8M | MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) { | 81 | 88.8M | CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul); | 82 | 88.8M | int64_t delta = value * mul; | 83 | 88.8M | return MonoDelta::FromNanoseconds(delta); | 84 | 88.8M | } |
|
85 | | |
86 | 0 | MonoDelta MonoDelta::FromMinutes(double minutes) { |
87 | 0 | return MonoDeltaByMultiplication(minutes, MonoTime::kNanosecondsPerMinute); |
88 | 0 | } |
89 | | |
90 | 354k | MonoDelta MonoDelta::FromSeconds(double seconds) { |
91 | 354k | return MonoDeltaByMultiplication(seconds, MonoTime::kNanosecondsPerSecond); |
92 | 354k | } |
93 | | |
94 | 71.8M | MonoDelta MonoDelta::FromMilliseconds(int64_t ms) { |
95 | 71.8M | return MonoDeltaByMultiplication(ms, MonoTime::kNanosecondsPerMillisecond); |
96 | 71.8M | } |
97 | | |
98 | 17.0M | MonoDelta MonoDelta::FromMicroseconds(int64_t us) { |
99 | 17.0M | return MonoDeltaByMultiplication(us, MonoTime::kNanosecondsPerMicrosecond); |
100 | 17.0M | } |
101 | | |
102 | 89.4M | MonoDelta MonoDelta::FromNanoseconds(int64_t ns) { |
103 | 89.4M | return MonoDelta(ns); |
104 | 89.4M | } |
105 | | |
106 | 166M | MonoDelta::MonoDelta() noexcept : nano_delta_(kUninitialized) { |
107 | 166M | } |
108 | | |
109 | 1.89G | bool MonoDelta::Initialized() const { |
110 | 1.89G | return nano_delta_ != kUninitialized; |
111 | 1.89G | } |
112 | | |
113 | 79.2M | bool MonoDelta::LessThan(const MonoDelta &rhs) const { |
114 | 79.2M | DCHECK(Initialized()); |
115 | 79.2M | DCHECK(rhs.Initialized()); |
116 | 79.2M | return nano_delta_ < rhs.nano_delta_; |
117 | 79.2M | } |
118 | | |
119 | 1.18k | bool MonoDelta::MoreThan(const MonoDelta &rhs) const { |
120 | 1.18k | DCHECK(Initialized()); |
121 | 1.18k | DCHECK(rhs.Initialized()); |
122 | 1.18k | return nano_delta_ > rhs.nano_delta_; |
123 | 1.18k | } |
124 | | |
125 | 229M | bool MonoDelta::Equals(const MonoDelta &rhs) const { |
126 | 229M | DCHECK(Initialized()); |
127 | 229M | DCHECK(rhs.Initialized()); |
128 | 229M | return nano_delta_ == rhs.nano_delta_; |
129 | 229M | } |
130 | | |
131 | 28.1M | bool MonoDelta::IsNegative() const { |
132 | 28.1M | DCHECK(Initialized()); |
133 | 28.1M | return nano_delta_ < 0; |
134 | 28.1M | } |
135 | | |
136 | 512k | std::string MonoDelta::ToString() const { |
137 | 418k | return Initialized() ? StringPrintf("%.3fs", ToSeconds()) : "<uninitialized>"; |
138 | 512k | } |
139 | | |
140 | | MonoDelta::MonoDelta(int64_t delta) |
141 | 90.5M | : nano_delta_(delta) { |
142 | 90.5M | } |
143 | | |
144 | 128M | double MonoDelta::ToSeconds() const { |
145 | 128M | DCHECK(Initialized()); |
146 | 128M | double d(nano_delta_); |
147 | 128M | d /= MonoTime::kNanosecondsPerSecond; |
148 | 128M | return d; |
149 | 128M | } |
150 | | |
151 | 0 | double MonoDelta::ToMinutes() const { |
152 | 0 | auto seconds = ToSeconds(); |
153 | 0 | return seconds / MonoTime::kSecondsPerMinute; |
154 | 0 | } |
155 | | |
156 | 306M | int64_t MonoDelta::ToNanoseconds() const { |
157 | 306M | DCHECK(Initialized()); |
158 | 306M | return nano_delta_; |
159 | 306M | } |
160 | | |
161 | 242M | std::chrono::steady_clock::duration MonoDelta::ToSteadyDuration() const { |
162 | 242M | return std::chrono::nanoseconds(ToNanoseconds()); |
163 | 242M | } |
164 | | |
165 | 264M | int64_t MonoDelta::ToMicroseconds() const { |
166 | 264M | DCHECK(Initialized()); |
167 | 264M | return nano_delta_ / MonoTime::kNanosecondsPerMicrosecond; |
168 | 264M | } |
169 | | |
170 | 105M | int64_t MonoDelta::ToMilliseconds() const { |
171 | 105M | DCHECK(Initialized()); |
172 | 105M | return nano_delta_ / MonoTime::kNanosecondsPerMillisecond; |
173 | 105M | } |
174 | | |
175 | 2.01M | MonoDelta& MonoDelta::operator+=(const MonoDelta& rhs) { |
176 | 2.01M | DCHECK(Initialized()); |
177 | 2.01M | DCHECK(rhs.Initialized()); |
178 | 2.01M | DCHECK(SafeToAdd64(nano_delta_, rhs.nano_delta_)); |
179 | 2.01M | DCHECK(nano_delta_ + rhs.nano_delta_ != kUninitialized); |
180 | 2.01M | nano_delta_ += rhs.nano_delta_; |
181 | 2.01M | return *this; |
182 | 2.01M | } |
183 | | |
184 | 53.5k | MonoDelta& MonoDelta::operator-=(const MonoDelta& rhs) { |
185 | 53.5k | DCHECK(Initialized()); |
186 | 53.5k | DCHECK(rhs.Initialized()); |
187 | 53.5k | DCHECK(SafeToAdd64(nano_delta_, -rhs.nano_delta_)); |
188 | 53.5k | DCHECK(nano_delta_ - rhs.nano_delta_ != kUninitialized); |
189 | 53.5k | nano_delta_ -= rhs.nano_delta_; |
190 | 53.5k | return *this; |
191 | 53.5k | } |
192 | | |
193 | 119M | MonoDelta& MonoDelta::operator*=(int64_t mul) { |
194 | 119M | DCHECK(Initialized()); |
195 | | DCHECK(mul == 0 || (nano_delta_ * mul / mul == nano_delta_)) // Check for overflow |
196 | 50.6k | << "Mul: " << mul << ", nano_delta_: " << nano_delta_; |
197 | 119M | DCHECK(nano_delta_ * mul != kUninitialized); |
198 | 119M | nano_delta_ *= mul; |
199 | 119M | return *this; |
200 | 119M | } |
201 | | |
202 | 21 | MonoDelta& MonoDelta::operator/=(int64_t divisor) { |
203 | 21 | DCHECK(Initialized()); |
204 | 21 | DCHECK_NE(divisor, 0); |
205 | 21 | nano_delta_ /= divisor; |
206 | 21 | return *this; |
207 | 21 | } |
208 | | |
209 | 1.88M | void MonoDelta::ToTimeVal(struct timeval *tv) const { |
210 | 1.88M | DCHECK(Initialized()); |
211 | 1.88M | tv->tv_sec = nano_delta_ / MonoTime::kNanosecondsPerSecond; |
212 | 1.88M | tv->tv_usec = narrow_cast<int32_t>( |
213 | 1.88M | (nano_delta_ - tv->tv_sec * MonoTime::kNanosecondsPerSecond) |
214 | 1.88M | / MonoTime::kNanosecondsPerMicrosecond); |
215 | | |
216 | | // tv_usec must be between 0 and 999999. |
217 | | // There is little use for negative timevals so wrap it in PREDICT_FALSE. |
218 | 1.88M | if (PREDICT_FALSE(tv->tv_usec < 0)) { |
219 | 1 | --(tv->tv_sec); |
220 | 1 | tv->tv_usec += MonoTime::kMicrosecondsPerSecond; |
221 | 1 | } |
222 | | |
223 | | // Catch positive corner case where we "round down" and could potentially set a timeout of 0. |
224 | | // Make it 1 usec. |
225 | 1.88M | if (PREDICT_FALSE(tv->tv_usec == 0 && tv->tv_sec == 0 && nano_delta_ > 0)) { |
226 | 1 | tv->tv_usec = 1; |
227 | 1 | } |
228 | | |
229 | | // Catch negative corner case where we "round down" and could potentially set a timeout of 0. |
230 | | // Make it -1 usec (but normalized, so tv_usec is not negative). |
231 | 1.88M | if (PREDICT_FALSE(tv->tv_usec == 0 && tv->tv_sec == 0 && nano_delta_ < 0)) { |
232 | 1 | tv->tv_sec = -1; |
233 | 1 | tv->tv_usec = 999999; |
234 | 1 | } |
235 | 1.88M | } |
236 | | |
237 | | |
238 | 45.7M | void MonoDelta::NanosToTimeSpec(int64_t nanos, struct timespec* ts) { |
239 | 45.7M | ts->tv_sec = nanos / MonoTime::kNanosecondsPerSecond; |
240 | 45.7M | ts->tv_nsec = nanos - (ts->tv_sec * MonoTime::kNanosecondsPerSecond); |
241 | | |
242 | | // tv_nsec must be between 0 and 999999999. |
243 | | // There is little use for negative timespecs so wrap it in PREDICT_FALSE. |
244 | 45.7M | if (PREDICT_FALSE(ts->tv_nsec < 0)) { |
245 | 1 | --(ts->tv_sec); |
246 | 1 | ts->tv_nsec += MonoTime::kNanosecondsPerSecond; |
247 | 1 | } |
248 | 45.7M | } |
249 | | |
250 | 45.7M | void MonoDelta::ToTimeSpec(struct timespec *ts) const { |
251 | 45.7M | DCHECK(Initialized()); |
252 | 45.7M | NanosToTimeSpec(nano_delta_, ts); |
253 | 45.7M | } |
254 | | |
255 | | /// |
256 | | /// MonoTime |
257 | | /// |
258 | | |
259 | | const MonoTime MonoTime::kMin = MonoTime::Min(); |
260 | | const MonoTime MonoTime::kMax = MonoTime::Max(); |
261 | | const MonoTime MonoTime::kUninitialized = MonoTime(); |
262 | | |
263 | 564M | MonoTime MonoTime::Now() { |
264 | 564M | return MonoTime(std::chrono::steady_clock::now()); |
265 | 564M | } |
266 | | |
267 | 178k | MonoTime MonoTime::Max() { |
268 | 178k | return MonoTime(std::chrono::steady_clock::time_point::max()); |
269 | 178k | } |
270 | | |
271 | 1.04M | MonoTime MonoTime::Min() { |
272 | 1.04M | return MonoTime(std::chrono::steady_clock::time_point(std::chrono::steady_clock::duration(1))); |
273 | 1.04M | } |
274 | | |
275 | 2.90k | bool MonoTime::IsMax() const { |
276 | 2.90k | return Equals(kMax); |
277 | 2.90k | } |
278 | | |
279 | 2.89k | bool MonoTime::IsMin() const { |
280 | 2.89k | return Equals(kMin); |
281 | 2.89k | } |
282 | | |
283 | 271k | const MonoTime& MonoTime::Earliest(const MonoTime& a, const MonoTime& b) { |
284 | 271k | return std::min(a, b); |
285 | 271k | } |
286 | | |
287 | 298M | MonoDelta MonoTime::GetDeltaSince(const MonoTime &rhs) const { |
288 | 298M | DCHECK(Initialized()); |
289 | 298M | DCHECK(rhs.Initialized()); |
290 | 298M | return MonoDelta(value_ - rhs.value_); |
291 | 298M | } |
292 | | |
293 | 82.9M | void MonoTime::AddDelta(const MonoDelta &delta) { |
294 | 82.9M | DCHECK(Initialized()); |
295 | 82.9M | DCHECK(delta.Initialized()); |
296 | 82.9M | if (delta == MonoDelta::kMax) { |
297 | 0 | value_ = kMax.value_; |
298 | 82.9M | } else { |
299 | 82.9M | value_ += delta.ToSteadyDuration(); |
300 | 82.9M | } |
301 | 82.9M | } |
302 | | |
303 | 1 | void MonoTime::SubtractDelta(const MonoDelta &delta) { |
304 | 1 | DCHECK(Initialized()); |
305 | 1 | DCHECK(delta.Initialized()); |
306 | 1 | if (delta == MonoDelta::kMin) { |
307 | 0 | value_ = kMin.value_; |
308 | 1 | } else { |
309 | 1 | value_ -= delta.ToSteadyDuration(); |
310 | 1 | } |
311 | 1 | } |
312 | | |
313 | 27.7M | bool MonoTime::ComesBefore(const MonoTime &rhs) const { |
314 | 27.7M | DCHECK(Initialized()); |
315 | 27.7M | DCHECK(rhs.Initialized()); |
316 | 27.7M | return value_ < rhs.value_; |
317 | 27.7M | } |
318 | | |
319 | 2.90k | std::string MonoTime::ToString() const { |
320 | 2.90k | if (!Initialized()) |
321 | 0 | return "MonoTime::kUninitialized"; |
322 | 2.90k | if (IsMax()) |
323 | 0 | return "MonoTime::kMax"; |
324 | 2.90k | if (IsMin()) |
325 | 0 | return "MonoTime::kMin"; |
326 | 2.90k | return StringPrintf("%.3fs", ToSeconds()); |
327 | 2.90k | } |
328 | | |
329 | 14.4k | bool MonoTime::Equals(const MonoTime& other) const { |
330 | 14.4k | return value_ == other.value_; |
331 | 14.4k | } |
332 | | |
333 | 2.89k | double MonoTime::ToSeconds() const { |
334 | 2.89k | return yb::ToSeconds(value_.time_since_epoch()); |
335 | 2.89k | } |
336 | | |
337 | 0 | void MonoTime::MakeAtLeast(MonoTime rhs) { |
338 | 0 | if (rhs.Initialized() && (!Initialized() || value_ < rhs.value_)) { |
339 | 0 | value_ = rhs.value_; |
340 | 0 | } |
341 | 0 | } |
342 | | |
343 | | // ------------------------------------------------------------------------------------------------ |
344 | | |
345 | 0 | std::string FormatForComparisonFailureMessage(const MonoDelta& op, const MonoDelta& other) { |
346 | 0 | return op.ToString(); |
347 | 0 | } |
348 | | |
349 | 2.05M | void SleepFor(const MonoDelta& delta) { |
350 | 2.05M | ThreadRestrictions::AssertWaitAllowed(); |
351 | 2.05M | base::SleepForNanoseconds(delta.ToNanoseconds()); |
352 | 2.05M | } |
353 | | |
354 | 992M | CoarseMonoClock::time_point CoarseMonoClock::now() { |
355 | 992M | #if defined(__APPLE__) |
356 | 992M | int64_t nanos = std::chrono::duration_cast<std::chrono::nanoseconds>( |
357 | 992M | std::chrono::steady_clock::now().time_since_epoch()).count(); |
358 | | # else |
359 | | struct timespec ts; |
360 | | PCHECK(clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0); |
361 | | CHECK_LT(ts.tv_sec, MAX_MONOTONIC_SECONDS); |
362 | | int64_t nanos = static_cast<int64_t>(ts.tv_sec) * MonoTime::kNanosecondsPerSecond + ts.tv_nsec; |
363 | | #endif // defined(__APPLE__) |
364 | 992M | return time_point(duration(nanos)); |
365 | 992M | } |
366 | | |
367 | | template <> |
368 | 39.9k | CoarseMonoClock::Duration ClockResolution<CoarseMonoClock>() { |
369 | 39.9k | #if defined(__APPLE__) |
370 | 39.9k | return std::chrono::duration_cast<CoarseMonoClock::Duration>( |
371 | 39.9k | std::chrono::steady_clock::duration(1)); |
372 | | #else |
373 | | struct timespec res; |
374 | | if (clock_getres(CLOCK_MONOTONIC_COARSE, &res) == 0) { |
375 | | auto resolution = std::chrono::seconds(res.tv_sec) + std::chrono::nanoseconds(res.tv_nsec); |
376 | | return std::chrono::duration_cast<CoarseMonoClock::Duration>(resolution); |
377 | | } |
378 | | return CoarseMonoClock::Duration(1); |
379 | | #endif // defined(__APPLE__) |
380 | 39.9k | } |
381 | | |
382 | 82.6k | std::string ToString(CoarseMonoClock::TimePoint time_point) { |
383 | 82.6k | return MonoDelta(time_point.time_since_epoch()).ToString(); |
384 | 82.6k | } |
385 | | |
386 | 53.7M | CoarseTimePoint ToCoarse(MonoTime monotime) { |
387 | 53.7M | return CoarseTimePoint(monotime.ToSteadyTimePoint().time_since_epoch()); |
388 | 53.7M | } |
389 | | |
390 | 430k | std::chrono::steady_clock::time_point ToSteady(CoarseTimePoint time_point) { |
391 | 430k | return std::chrono::steady_clock::time_point(time_point.time_since_epoch()); |
392 | 430k | } |
393 | | |
394 | | } // namespace yb |