/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 | 20.6M | bool SafeToAdd64(int64_t a, int64_t b) { |
58 | 20.6M | bool negativeA = a < 0; |
59 | 20.6M | bool negativeB = b < 0; |
60 | 20.6M | if (negativeA != negativeB) { |
61 | 471 | return true; |
62 | 471 | } |
63 | 20.6M | bool negativeSum = (a + b) < 0; |
64 | 20.6M | return negativeSum == negativeA; |
65 | 20.6M | } |
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 | 303M | MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) { |
81 | 303M | CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul); |
82 | 303M | int64_t delta = value * mul; |
83 | 303M | return MonoDelta::FromNanoseconds(delta); |
84 | 303M | } yb::MonoDelta yb::MonoDeltaByMultiplication<double>(double, long long) Line | Count | Source | 80 | 1.86M | MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) { | 81 | 1.86M | CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul); | 82 | 1.86M | int64_t delta = value * mul; | 83 | 1.86M | return MonoDelta::FromNanoseconds(delta); | 84 | 1.86M | } |
yb::MonoDelta yb::MonoDeltaByMultiplication<long long>(long long, long long) Line | Count | Source | 80 | 301M | MonoDelta MonoDeltaByMultiplication(V value, int64_t mul) { | 81 | 301M | CHECK_LE(value, std::numeric_limits<int64_t>::max() / mul); | 82 | 301M | int64_t delta = value * mul; | 83 | 301M | return MonoDelta::FromNanoseconds(delta); | 84 | 301M | } |
|
85 | | |
86 | 16 | MonoDelta MonoDelta::FromMinutes(double minutes) { |
87 | 16 | return MonoDeltaByMultiplication(minutes, MonoTime::kNanosecondsPerMinute); |
88 | 16 | } |
89 | | |
90 | 1.86M | MonoDelta MonoDelta::FromSeconds(double seconds) { |
91 | 1.86M | return MonoDeltaByMultiplication(seconds, MonoTime::kNanosecondsPerSecond); |
92 | 1.86M | } |
93 | | |
94 | 277M | MonoDelta MonoDelta::FromMilliseconds(int64_t ms) { |
95 | 277M | return MonoDeltaByMultiplication(ms, MonoTime::kNanosecondsPerMillisecond); |
96 | 277M | } |
97 | | |
98 | 24.0M | MonoDelta MonoDelta::FromMicroseconds(int64_t us) { |
99 | 24.0M | return MonoDeltaByMultiplication(us, MonoTime::kNanosecondsPerMicrosecond); |
100 | 24.0M | } |
101 | | |
102 | 303M | MonoDelta MonoDelta::FromNanoseconds(int64_t ns) { |
103 | 303M | return MonoDelta(ns); |
104 | 303M | } |
105 | | |
106 | 434M | MonoDelta::MonoDelta() noexcept : nano_delta_(kUninitialized) { |
107 | 434M | } |
108 | | |
109 | 6.33G | bool MonoDelta::Initialized() const { |
110 | 6.33G | return nano_delta_ != kUninitialized; |
111 | 6.33G | } |
112 | | |
113 | 199M | bool MonoDelta::LessThan(const MonoDelta &rhs) const { |
114 | 199M | DCHECK(Initialized()); |
115 | 199M | DCHECK(rhs.Initialized()); |
116 | 199M | return nano_delta_ < rhs.nano_delta_; |
117 | 199M | } |
118 | | |
119 | 1.45k | bool MonoDelta::MoreThan(const MonoDelta &rhs) const { |
120 | 1.45k | DCHECK(Initialized()); |
121 | 1.45k | DCHECK(rhs.Initialized()); |
122 | 1.45k | return nano_delta_ > rhs.nano_delta_; |
123 | 1.45k | } |
124 | | |
125 | 635M | bool MonoDelta::Equals(const MonoDelta &rhs) const { |
126 | 635M | DCHECK(Initialized()); |
127 | 635M | DCHECK(rhs.Initialized()); |
128 | 635M | return nano_delta_ == rhs.nano_delta_; |
129 | 635M | } |
130 | | |
131 | 72.5M | bool MonoDelta::IsNegative() const { |
132 | 72.5M | DCHECK(Initialized()); |
133 | 72.5M | return nano_delta_ < 0; |
134 | 72.5M | } |
135 | | |
136 | 2.67M | std::string MonoDelta::ToString() const { |
137 | 2.67M | return Initialized() ? StringPrintf("%.3fs", ToSeconds())2.51M : "<uninitialized>"161k ; |
138 | 2.67M | } |
139 | | |
140 | | MonoDelta::MonoDelta(int64_t delta) |
141 | 308M | : nano_delta_(delta) { |
142 | 308M | } |
143 | | |
144 | 1.19G | double MonoDelta::ToSeconds() const { |
145 | 1.19G | DCHECK(Initialized()); |
146 | 1.19G | double d(nano_delta_); |
147 | 1.19G | d /= MonoTime::kNanosecondsPerSecond; |
148 | 1.19G | return d; |
149 | 1.19G | } |
150 | | |
151 | 84 | double MonoDelta::ToMinutes() const { |
152 | 84 | auto seconds = ToSeconds(); |
153 | 84 | return seconds / MonoTime::kSecondsPerMinute; |
154 | 84 | } |
155 | | |
156 | 930M | int64_t MonoDelta::ToNanoseconds() const { |
157 | 930M | DCHECK(Initialized()); |
158 | 930M | return nano_delta_; |
159 | 930M | } |
160 | | |
161 | 745M | std::chrono::steady_clock::duration MonoDelta::ToSteadyDuration() const { |
162 | 745M | return std::chrono::nanoseconds(ToNanoseconds()); |
163 | 745M | } |
164 | | |
165 | 771M | int64_t MonoDelta::ToMicroseconds() const { |
166 | 771M | DCHECK(Initialized()); |
167 | 771M | return nano_delta_ / MonoTime::kNanosecondsPerMicrosecond; |
168 | 771M | } |
169 | | |
170 | 361M | int64_t MonoDelta::ToMilliseconds() const { |
171 | 361M | DCHECK(Initialized()); |
172 | 361M | return nano_delta_ / MonoTime::kNanosecondsPerMillisecond; |
173 | 361M | } |
174 | | |
175 | 20.5M | MonoDelta& MonoDelta::operator+=(const MonoDelta& rhs) { |
176 | 20.5M | DCHECK(Initialized()); |
177 | 20.5M | DCHECK(rhs.Initialized()); |
178 | 20.5M | DCHECK(SafeToAdd64(nano_delta_, rhs.nano_delta_)); |
179 | 20.5M | DCHECK(nano_delta_ + rhs.nano_delta_ != kUninitialized); |
180 | 20.5M | nano_delta_ += rhs.nano_delta_; |
181 | 20.5M | return *this; |
182 | 20.5M | } |
183 | | |
184 | 100k | MonoDelta& MonoDelta::operator-=(const MonoDelta& rhs) { |
185 | 100k | DCHECK(Initialized()); |
186 | 100k | DCHECK(rhs.Initialized()); |
187 | 100k | DCHECK(SafeToAdd64(nano_delta_, -rhs.nano_delta_)); |
188 | 100k | DCHECK(nano_delta_ - rhs.nano_delta_ != kUninitialized); |
189 | 100k | nano_delta_ -= rhs.nano_delta_; |
190 | 100k | return *this; |
191 | 100k | } |
192 | | |
193 | 371M | MonoDelta& MonoDelta::operator*=(int64_t mul) { |
194 | 371M | DCHECK(Initialized()); |
195 | | DCHECK(mul == 0 || (nano_delta_ * mul / mul == nano_delta_)) // Check for overflow103k |
196 | 103k | << "Mul: " << mul << ", nano_delta_: " << nano_delta_; |
197 | 371M | DCHECK(nano_delta_ * mul != kUninitialized); |
198 | 371M | nano_delta_ *= mul; |
199 | 371M | return *this; |
200 | 371M | } |
201 | | |
202 | 24 | MonoDelta& MonoDelta::operator/=(int64_t divisor) { |
203 | 24 | DCHECK(Initialized()); |
204 | 24 | DCHECK_NE(divisor, 0); |
205 | 24 | nano_delta_ /= divisor; |
206 | 24 | return *this; |
207 | 24 | } |
208 | | |
209 | 7.50M | void MonoDelta::ToTimeVal(struct timeval *tv) const { |
210 | 7.50M | DCHECK(Initialized()); |
211 | 7.50M | tv->tv_sec = nano_delta_ / MonoTime::kNanosecondsPerSecond; |
212 | 7.50M | tv->tv_usec = narrow_cast<int32_t>( |
213 | 7.50M | (nano_delta_ - tv->tv_sec * MonoTime::kNanosecondsPerSecond) |
214 | 7.50M | / 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 | 7.50M | 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 | 7.50M | 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 | 7.50M | 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 | 7.50M | } |
236 | | |
237 | | |
238 | 102M | void MonoDelta::NanosToTimeSpec(int64_t nanos, struct timespec* ts) { |
239 | 102M | ts->tv_sec = nanos / MonoTime::kNanosecondsPerSecond; |
240 | 102M | 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 | 102M | if (PREDICT_FALSE(ts->tv_nsec < 0)) { |
245 | 1 | --(ts->tv_sec); |
246 | 1 | ts->tv_nsec += MonoTime::kNanosecondsPerSecond; |
247 | 1 | } |
248 | 102M | } |
249 | | |
250 | 102M | void MonoDelta::ToTimeSpec(struct timespec *ts) const { |
251 | 102M | DCHECK(Initialized()); |
252 | 102M | NanosToTimeSpec(nano_delta_, ts); |
253 | 102M | } |
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 | 1.46G | MonoTime MonoTime::Now() { |
264 | 1.46G | return MonoTime(std::chrono::steady_clock::now()); |
265 | 1.46G | } |
266 | | |
267 | 272k | MonoTime MonoTime::Max() { |
268 | 272k | return MonoTime(std::chrono::steady_clock::time_point::max()); |
269 | 272k | } |
270 | | |
271 | 2.47M | MonoTime MonoTime::Min() { |
272 | 2.47M | return MonoTime(std::chrono::steady_clock::time_point(std::chrono::steady_clock::duration(1))); |
273 | 2.47M | } |
274 | | |
275 | 4.07k | bool MonoTime::IsMax() const { |
276 | 4.07k | return Equals(kMax); |
277 | 4.07k | } |
278 | | |
279 | 4.07k | bool MonoTime::IsMin() const { |
280 | 4.07k | return Equals(kMin); |
281 | 4.07k | } |
282 | | |
283 | 462k | const MonoTime& MonoTime::Earliest(const MonoTime& a, const MonoTime& b) { |
284 | 462k | return std::min(a, b); |
285 | 462k | } |
286 | | |
287 | 762M | MonoDelta MonoTime::GetDeltaSince(const MonoTime &rhs) const { |
288 | 762M | DCHECK(Initialized()); |
289 | 762M | DCHECK(rhs.Initialized()); |
290 | 762M | return MonoDelta(value_ - rhs.value_); |
291 | 762M | } |
292 | | |
293 | 219M | void MonoTime::AddDelta(const MonoDelta &delta) { |
294 | 219M | DCHECK(Initialized()); |
295 | 219M | DCHECK(delta.Initialized()); |
296 | 219M | if (delta == MonoDelta::kMax) { |
297 | 0 | value_ = kMax.value_; |
298 | 219M | } else { |
299 | 219M | value_ += delta.ToSteadyDuration(); |
300 | 219M | } |
301 | 219M | } |
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 | 61.2M | bool MonoTime::ComesBefore(const MonoTime &rhs) const { |
314 | 61.2M | DCHECK(Initialized()); |
315 | 61.2M | DCHECK(rhs.Initialized()); |
316 | 61.2M | return value_ < rhs.value_; |
317 | 61.2M | } |
318 | | |
319 | 4.07k | std::string MonoTime::ToString() const { |
320 | 4.07k | if (!Initialized()) |
321 | 0 | return "MonoTime::kUninitialized"; |
322 | 4.07k | if (IsMax()) |
323 | 0 | return "MonoTime::kMax"; |
324 | 4.07k | if (IsMin()) |
325 | 0 | return "MonoTime::kMin"; |
326 | 4.07k | return StringPrintf("%.3fs", ToSeconds()); |
327 | 4.07k | } |
328 | | |
329 | 628k | bool MonoTime::Equals(const MonoTime& other) const { |
330 | 628k | return value_ == other.value_; |
331 | 628k | } |
332 | | |
333 | 4.06k | double MonoTime::ToSeconds() const { |
334 | 4.06k | return yb::ToSeconds(value_.time_since_epoch()); |
335 | 4.06k | } |
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 | 50.2M | void SleepFor(const MonoDelta& delta) { |
350 | 50.2M | ThreadRestrictions::AssertWaitAllowed(); |
351 | 50.2M | base::SleepForNanoseconds(delta.ToNanoseconds()); |
352 | 50.2M | } |
353 | | |
354 | 4.93G | CoarseMonoClock::time_point CoarseMonoClock::now() { |
355 | 4.93G | #if defined(__APPLE__) |
356 | 4.93G | int64_t nanos = std::chrono::duration_cast<std::chrono::nanoseconds>( |
357 | 4.93G | 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 | 4.93G | return time_point(duration(nanos)); |
365 | 4.93G | } |
366 | | |
367 | | template <> |
368 | 66.7k | CoarseMonoClock::Duration ClockResolution<CoarseMonoClock>() { |
369 | 66.7k | #if defined(__APPLE__) |
370 | 66.7k | return std::chrono::duration_cast<CoarseMonoClock::Duration>( |
371 | 66.7k | 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 | 66.7k | } |
381 | | |
382 | 166k | std::string ToString(CoarseMonoClock::TimePoint time_point) { |
383 | 166k | return MonoDelta(time_point.time_since_epoch()).ToString(); |
384 | 166k | } |
385 | | |
386 | 184M | CoarseTimePoint ToCoarse(MonoTime monotime) { |
387 | 184M | return CoarseTimePoint(monotime.ToSteadyTimePoint().time_since_epoch()); |
388 | 184M | } |
389 | | |
390 | 1.91M | std::chrono::steady_clock::time_point ToSteady(CoarseTimePoint time_point) { |
391 | 1.91M | return std::chrono::steady_clock::time_point(time_point.time_since_epoch()); |
392 | 1.91M | } |
393 | | |
394 | | } // namespace yb |