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