Line data Source code
1 : // Copyright 2013 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_BASE_PLATFORM_TIME_H_
6 : #define V8_BASE_PLATFORM_TIME_H_
7 :
8 : #include <stdint.h>
9 :
10 : #include <ctime>
11 : #include <iosfwd>
12 : #include <limits>
13 :
14 : #include "src/base/base-export.h"
15 : #include "src/base/bits.h"
16 : #include "src/base/macros.h"
17 : #include "src/base/safe_math.h"
18 : #if V8_OS_WIN
19 : #include "src/base/win32-headers.h"
20 : #endif
21 :
22 : // Forward declarations.
23 : extern "C" {
24 : struct _FILETIME;
25 : struct mach_timespec;
26 : struct timespec;
27 : struct timeval;
28 : }
29 :
30 : namespace v8 {
31 : namespace base {
32 :
33 : class Time;
34 : class TimeDelta;
35 : class TimeTicks;
36 :
37 : namespace time_internal {
38 : template<class TimeClass>
39 : class TimeBase;
40 : }
41 :
42 : class TimeConstants {
43 : public:
44 : static constexpr int64_t kHoursPerDay = 24;
45 : static constexpr int64_t kMillisecondsPerSecond = 1000;
46 : static constexpr int64_t kMillisecondsPerDay =
47 : kMillisecondsPerSecond * 60 * 60 * kHoursPerDay;
48 : static constexpr int64_t kMicrosecondsPerMillisecond = 1000;
49 : static constexpr int64_t kMicrosecondsPerSecond =
50 : kMicrosecondsPerMillisecond * kMillisecondsPerSecond;
51 : static constexpr int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
52 : static constexpr int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
53 : static constexpr int64_t kMicrosecondsPerDay =
54 : kMicrosecondsPerHour * kHoursPerDay;
55 : static constexpr int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
56 : static constexpr int64_t kNanosecondsPerMicrosecond = 1000;
57 : static constexpr int64_t kNanosecondsPerSecond =
58 : kNanosecondsPerMicrosecond * kMicrosecondsPerSecond;
59 : };
60 :
61 : // -----------------------------------------------------------------------------
62 : // TimeDelta
63 : //
64 : // This class represents a duration of time, internally represented in
65 : // microseonds.
66 :
67 : class V8_BASE_EXPORT TimeDelta final {
68 : public:
69 0 : constexpr TimeDelta() : delta_(0) {}
70 :
71 : // Converts units of time to TimeDeltas.
72 : static constexpr TimeDelta FromDays(int days) {
73 : return TimeDelta(days * TimeConstants::kMicrosecondsPerDay);
74 : }
75 : static constexpr TimeDelta FromHours(int hours) {
76 : return TimeDelta(hours * TimeConstants::kMicrosecondsPerHour);
77 : }
78 : static constexpr TimeDelta FromMinutes(int minutes) {
79 : return TimeDelta(minutes * TimeConstants::kMicrosecondsPerMinute);
80 : }
81 : static constexpr TimeDelta FromSeconds(int64_t seconds) {
82 : return TimeDelta(seconds * TimeConstants::kMicrosecondsPerSecond);
83 : }
84 54 : static constexpr TimeDelta FromMilliseconds(int64_t milliseconds) {
85 58 : return TimeDelta(milliseconds * TimeConstants::kMicrosecondsPerMillisecond);
86 : }
87 : static constexpr TimeDelta FromMicroseconds(int64_t microseconds) {
88 : return TimeDelta(microseconds);
89 : }
90 : static constexpr TimeDelta FromNanoseconds(int64_t nanoseconds) {
91 89 : return TimeDelta(nanoseconds / TimeConstants::kNanosecondsPerMicrosecond);
92 : }
93 :
94 : // Returns the maximum time delta, which should be greater than any reasonable
95 : // time delta we might compare it to. Adding or subtracting the maximum time
96 : // delta to a time or another time delta has an undefined result.
97 : static constexpr TimeDelta Max();
98 :
99 : // Returns the minimum time delta, which should be less than than any
100 : // reasonable time delta we might compare it to. Adding or subtracting the
101 : // minimum time delta to a time or another time delta has an undefined result.
102 : static constexpr TimeDelta Min();
103 :
104 : // Returns true if the time delta is zero.
105 : constexpr bool IsZero() const { return delta_ == 0; }
106 :
107 : // Returns true if the time delta is the maximum/minimum time delta.
108 : constexpr bool IsMax() const {
109 7689404 : return delta_ == std::numeric_limits<int64_t>::max();
110 : }
111 : constexpr bool IsMin() const {
112 0 : return delta_ == std::numeric_limits<int64_t>::min();
113 : }
114 :
115 : // Returns the time delta in some unit. The F versions return a floating
116 : // point value, the "regular" versions return a rounded-down value.
117 : //
118 : // InMillisecondsRoundedUp() instead returns an integer that is rounded up
119 : // to the next full millisecond.
120 : int InDays() const;
121 : int InHours() const;
122 : int InMinutes() const;
123 : double InSecondsF() const;
124 : int64_t InSeconds() const;
125 : double InMillisecondsF() const;
126 : int64_t InMilliseconds() const;
127 : int64_t InMillisecondsRoundedUp() const;
128 : int64_t InMicroseconds() const;
129 : int64_t InNanoseconds() const;
130 :
131 : // Converts to/from Mach time specs.
132 : static TimeDelta FromMachTimespec(struct mach_timespec ts);
133 : struct mach_timespec ToMachTimespec() const;
134 :
135 : // Converts to/from POSIX time specs.
136 : static TimeDelta FromTimespec(struct timespec ts);
137 : struct timespec ToTimespec() const;
138 :
139 : // Computations with other deltas.
140 : TimeDelta operator+(const TimeDelta& other) const {
141 0 : return TimeDelta(delta_ + other.delta_);
142 : }
143 : TimeDelta operator-(const TimeDelta& other) const {
144 1 : return TimeDelta(delta_ - other.delta_);
145 : }
146 :
147 : TimeDelta& operator+=(const TimeDelta& other) {
148 6137871 : delta_ += other.delta_;
149 : return *this;
150 : }
151 : TimeDelta& operator-=(const TimeDelta& other) {
152 0 : delta_ -= other.delta_;
153 : return *this;
154 : }
155 0 : constexpr TimeDelta operator-() const { return TimeDelta(-delta_); }
156 :
157 : double TimesOf(const TimeDelta& other) const {
158 0 : return static_cast<double>(delta_) / static_cast<double>(other.delta_);
159 : }
160 : double PercentOf(const TimeDelta& other) const {
161 0 : return TimesOf(other) * 100.0;
162 : }
163 :
164 : // Computations with ints, note that we only allow multiplicative operations
165 : // with ints, and additive operations with other deltas.
166 : TimeDelta operator*(int64_t a) const {
167 : return TimeDelta(delta_ * a);
168 : }
169 : TimeDelta operator/(int64_t a) const {
170 : return TimeDelta(delta_ / a);
171 : }
172 : TimeDelta& operator*=(int64_t a) {
173 3 : delta_ *= a;
174 : return *this;
175 : }
176 : TimeDelta& operator/=(int64_t a) {
177 3 : delta_ /= a;
178 : return *this;
179 : }
180 : int64_t operator/(const TimeDelta& other) const {
181 : return delta_ / other.delta_;
182 : }
183 :
184 : // Comparison operators.
185 : constexpr bool operator==(const TimeDelta& other) const {
186 17 : return delta_ == other.delta_;
187 : }
188 : constexpr bool operator!=(const TimeDelta& other) const {
189 267706 : return delta_ != other.delta_;
190 : }
191 : constexpr bool operator<(const TimeDelta& other) const {
192 1 : return delta_ < other.delta_;
193 : }
194 : constexpr bool operator<=(const TimeDelta& other) const {
195 2 : return delta_ <= other.delta_;
196 : }
197 : constexpr bool operator>(const TimeDelta& other) const {
198 3 : return delta_ > other.delta_;
199 : }
200 : constexpr bool operator>=(const TimeDelta& other) const {
201 : return delta_ >= other.delta_;
202 : }
203 :
204 : private:
205 : template<class TimeClass> friend class time_internal::TimeBase;
206 : // Constructs a delta given the duration in microseconds. This is private
207 : // to avoid confusion by callers with an integer constructor. Use
208 : // FromSeconds, FromMilliseconds, etc. instead.
209 : explicit constexpr TimeDelta(int64_t delta) : delta_(delta) {}
210 :
211 : // Delta in microseconds.
212 : int64_t delta_;
213 : };
214 :
215 : // static
216 : constexpr TimeDelta TimeDelta::Max() {
217 : return TimeDelta(std::numeric_limits<int64_t>::max());
218 : }
219 :
220 : // static
221 : constexpr TimeDelta TimeDelta::Min() {
222 : return TimeDelta(std::numeric_limits<int64_t>::min());
223 : }
224 :
225 : namespace time_internal {
226 :
227 : // TimeBase--------------------------------------------------------------------
228 :
229 : // Provides value storage and comparison/math operations common to all time
230 : // classes. Each subclass provides for strong type-checking to ensure
231 : // semantically meaningful comparison/math of time values from the same clock
232 : // source or timeline.
233 : template <class TimeClass>
234 : class TimeBase : public TimeConstants {
235 : public:
236 : #if V8_OS_WIN
237 : // To avoid overflow in QPC to Microseconds calculations, since we multiply
238 : // by kMicrosecondsPerSecond, then the QPC value should not exceed
239 : // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply.
240 : static constexpr int64_t kQPCOverflowThreshold = INT64_C(0x8637BD05AF7);
241 : #endif
242 :
243 : // Returns true if this object has not been initialized.
244 : //
245 : // Warning: Be careful when writing code that performs math on time values,
246 : // since it's possible to produce a valid "zero" result that should not be
247 : // interpreted as a "null" value.
248 218723 : constexpr bool IsNull() const { return us_ == 0; }
249 :
250 : // Returns the maximum/minimum times, which should be greater/less than any
251 : // reasonable time with which we might compare it.
252 : static TimeClass Max() {
253 : return TimeClass(std::numeric_limits<int64_t>::max());
254 : }
255 : static TimeClass Min() {
256 : return TimeClass(std::numeric_limits<int64_t>::min());
257 : }
258 :
259 : // Returns true if this object represents the maximum/minimum time.
260 : constexpr bool IsMax() const {
261 0 : return us_ == std::numeric_limits<int64_t>::max();
262 : }
263 : constexpr bool IsMin() const {
264 : return us_ == std::numeric_limits<int64_t>::min();
265 : }
266 :
267 : // For serializing only. Use FromInternalValue() to reconstitute. Please don't
268 : // use this and do arithmetic on it, as it is more error prone than using the
269 : // provided operators.
270 29013460 : int64_t ToInternalValue() const { return us_; }
271 :
272 : TimeClass& operator=(TimeClass other) {
273 : us_ = other.us_;
274 : return *(static_cast<TimeClass*>(this));
275 : }
276 :
277 : // Compute the difference between two times.
278 : TimeDelta operator-(TimeClass other) const {
279 7241529 : return TimeDelta::FromMicroseconds(us_ - other.us_);
280 : }
281 :
282 : // Return a new time modified by some delta.
283 : TimeClass operator+(TimeDelta delta) const {
284 62363 : return TimeClass(bits::SignedSaturatedAdd64(delta.delta_, us_));
285 : }
286 : TimeClass operator-(TimeDelta delta) const {
287 0 : return TimeClass(-bits::SignedSaturatedSub64(delta.delta_, us_));
288 : }
289 :
290 : // Modify by some time delta.
291 : TimeClass& operator+=(TimeDelta delta) {
292 : return static_cast<TimeClass&>(*this = (*this + delta));
293 : }
294 : TimeClass& operator-=(TimeDelta delta) {
295 : return static_cast<TimeClass&>(*this = (*this - delta));
296 : }
297 :
298 : // Comparison operators
299 : bool operator==(TimeClass other) const {
300 12 : return us_ == other.us_;
301 : }
302 : bool operator!=(TimeClass other) const {
303 27450 : return us_ != other.us_;
304 : }
305 : bool operator<(TimeClass other) const {
306 : return us_ < other.us_;
307 : }
308 : bool operator<=(TimeClass other) const {
309 : return us_ <= other.us_;
310 : }
311 : bool operator>(TimeClass other) const {
312 4 : return us_ > other.us_;
313 : }
314 : bool operator>=(TimeClass other) const {
315 677812 : return us_ >= other.us_;
316 : }
317 :
318 : // Converts an integer value representing TimeClass to a class. This is used
319 : // when deserializing a |TimeClass| structure, using a value known to be
320 : // compatible. It is not provided as a constructor because the integer type
321 : // may be unclear from the perspective of a caller.
322 : static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); }
323 :
324 : protected:
325 2 : explicit constexpr TimeBase(int64_t us) : us_(us) {}
326 :
327 : // Time value in a microsecond timebase.
328 : int64_t us_;
329 : };
330 :
331 : } // namespace time_internal
332 :
333 :
334 : // -----------------------------------------------------------------------------
335 : // Time
336 : //
337 : // This class represents an absolute point in time, internally represented as
338 : // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970.
339 :
340 : class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> {
341 : public:
342 : // Contains the nullptr time. Use Time::Now() to get the current time.
343 : constexpr Time() : TimeBase(0) {}
344 :
345 : // Returns the current time. Watch out, the system might adjust its clock
346 : // in which case time will actually go backwards. We don't guarantee that
347 : // times are increasing, or that two calls to Now() won't be the same.
348 : static Time Now();
349 :
350 : // Returns the current time. Same as Now() except that this function always
351 : // uses system time so that there are no discrepancies between the returned
352 : // time and system time even on virtual environments including our test bot.
353 : // For timing sensitive unittests, this function should be used.
354 : static Time NowFromSystemTime();
355 :
356 : // Returns the time for epoch in Unix-like system (Jan 1, 1970).
357 : static Time UnixEpoch() { return Time(0); }
358 :
359 : // Converts to/from POSIX time specs.
360 : static Time FromTimespec(struct timespec ts);
361 : struct timespec ToTimespec() const;
362 :
363 : // Converts to/from POSIX time values.
364 : static Time FromTimeval(struct timeval tv);
365 : struct timeval ToTimeval() const;
366 :
367 : // Converts to/from Windows file times.
368 : static Time FromFiletime(struct _FILETIME ft);
369 : struct _FILETIME ToFiletime() const;
370 :
371 : // Converts to/from the Javascript convention for times, a number of
372 : // milliseconds since the epoch:
373 : static Time FromJsTime(double ms_since_epoch);
374 : double ToJsTime() const;
375 :
376 : private:
377 : friend class time_internal::TimeBase<Time>;
378 : explicit constexpr Time(int64_t us) : TimeBase(us) {}
379 : };
380 :
381 : V8_BASE_EXPORT std::ostream& operator<<(std::ostream&, const Time&);
382 :
383 : inline Time operator+(const TimeDelta& delta, const Time& time) {
384 : return time + delta;
385 : }
386 :
387 :
388 : // -----------------------------------------------------------------------------
389 : // TimeTicks
390 : //
391 : // This class represents an abstract time that is most of the time incrementing
392 : // for use in measuring time durations. It is internally represented in
393 : // microseconds. It can not be converted to a human-readable time, but is
394 : // guaranteed not to decrease (if the user changes the computer clock,
395 : // Time::Now() may actually decrease or jump). But note that TimeTicks may
396 : // "stand still", for example if the computer suspended.
397 :
398 : class V8_BASE_EXPORT TimeTicks final
399 : : public time_internal::TimeBase<TimeTicks> {
400 : public:
401 : constexpr TimeTicks() : TimeBase(0) {}
402 :
403 : // Platform-dependent tick count representing "right now." When
404 : // IsHighResolution() returns false, the resolution of the clock could be as
405 : // coarse as ~15.6ms. Otherwise, the resolution should be no worse than one
406 : // microsecond.
407 : // This method never returns a null TimeTicks.
408 : static TimeTicks Now();
409 :
410 : // This is equivalent to Now() but DCHECKs that IsHighResolution(). Useful for
411 : // test frameworks that rely on high resolution clocks (in practice all
412 : // platforms but low-end Windows devices have high resolution clocks).
413 : static TimeTicks HighResolutionNow();
414 :
415 : // Returns true if the high-resolution clock is working on this system.
416 : static bool IsHighResolution();
417 :
418 : private:
419 : friend class time_internal::TimeBase<TimeTicks>;
420 :
421 : // Please use Now() to create a new object. This is for internal use
422 : // and testing. Ticks are in microseconds.
423 : explicit constexpr TimeTicks(int64_t ticks) : TimeBase(ticks) {}
424 : };
425 :
426 : inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) {
427 : return ticks + delta;
428 : }
429 :
430 :
431 : // ThreadTicks ----------------------------------------------------------------
432 :
433 : // Represents a clock, specific to a particular thread, than runs only while the
434 : // thread is running.
435 : class V8_BASE_EXPORT ThreadTicks final
436 : : public time_internal::TimeBase<ThreadTicks> {
437 : public:
438 : constexpr ThreadTicks() : TimeBase(0) {}
439 :
440 : // Returns true if ThreadTicks::Now() is supported on this system.
441 : static bool IsSupported();
442 :
443 : // Waits until the initialization is completed. Needs to be guarded with a
444 : // call to IsSupported().
445 : static void WaitUntilInitialized() {
446 : #if V8_OS_WIN
447 : WaitUntilInitializedWin();
448 : #endif
449 : }
450 :
451 : // Returns thread-specific CPU-time on systems that support this feature.
452 : // Needs to be guarded with a call to IsSupported(). Use this timer
453 : // to (approximately) measure how much time the calling thread spent doing
454 : // actual work vs. being de-scheduled. May return bogus results if the thread
455 : // migrates to another CPU between two calls. Returns an empty ThreadTicks
456 : // object until the initialization is completed. If a clock reading is
457 : // absolutely needed, call WaitUntilInitialized() before this method.
458 : static ThreadTicks Now();
459 :
460 : #if V8_OS_WIN
461 : // Similar to Now() above except this returns thread-specific CPU time for an
462 : // arbitrary thread. All comments for Now() method above apply apply to this
463 : // method as well.
464 : static ThreadTicks GetForThread(const HANDLE& thread_handle);
465 : #endif
466 :
467 : private:
468 : template <class TimeClass>
469 : friend class time_internal::TimeBase;
470 :
471 : // Please use Now() or GetForThread() to create a new object. This is for
472 : // internal use and testing. Ticks are in microseconds.
473 : explicit constexpr ThreadTicks(int64_t ticks) : TimeBase(ticks) {}
474 :
475 : #if V8_OS_WIN
476 : // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't
477 : // been measured yet. Needs to be guarded with a call to IsSupported().
478 : static double TSCTicksPerSecond();
479 : static bool IsSupportedWin();
480 : static void WaitUntilInitializedWin();
481 : #endif
482 : };
483 :
484 : } // namespace base
485 : } // namespace v8
486 :
487 : #endif // V8_BASE_PLATFORM_TIME_H_
|