1dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
55de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/time.h"
6dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
7dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#if V8_OS_POSIX
8d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org#include <fcntl.h>  // for O_RDONLY
9dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#include <sys/time.h>
10f9fc81b8e741fda0abdc91a03c6d33cab8037e5amachenbach@chromium.org#include <unistd.h>
11dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#endif
12dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#if V8_OS_MACOSX
13dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#include <mach/mach_time.h>
14dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#endif
15dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
16e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org#include <string.h>
17dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
181e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#if V8_OS_WIN
191e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/lazy-instance.h"
201e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/win32-headers.h"
211e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#endif
225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/cpu.h"
235de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/logging.h"
245de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
25dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
26dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgnamespace v8 {
275de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgnamespace base {
28dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
29dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeDelta TimeDelta::FromDays(int days) {
30dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeDelta(days * Time::kMicrosecondsPerDay);
31dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
32dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
33dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
34dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeDelta TimeDelta::FromHours(int hours) {
35dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeDelta(hours * Time::kMicrosecondsPerHour);
36dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
37dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
38dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
39dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeDelta TimeDelta::FromMinutes(int minutes) {
40dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeDelta(minutes * Time::kMicrosecondsPerMinute);
41dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
42dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
43dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
44dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeDelta TimeDelta::FromSeconds(int64_t seconds) {
45dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeDelta(seconds * Time::kMicrosecondsPerSecond);
46dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
47dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
48dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
49dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeDelta TimeDelta::FromMilliseconds(int64_t milliseconds) {
50dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeDelta(milliseconds * Time::kMicrosecondsPerMillisecond);
51dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
52dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
53dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
54dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeDelta TimeDelta::FromNanoseconds(int64_t nanoseconds) {
55dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeDelta(nanoseconds / Time::kNanosecondsPerMicrosecond);
56dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
57dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
58dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
59dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgint TimeDelta::InDays() const {
60dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
61dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
62dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
63dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
64dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgint TimeDelta::InHours() const {
65dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
66dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
67dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
68dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
69dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgint TimeDelta::InMinutes() const {
70dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
71dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
72dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
73dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
74dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgdouble TimeDelta::InSecondsF() const {
75dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
76dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
77dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
78dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
79dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgint64_t TimeDelta::InSeconds() const {
80dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return delta_ / Time::kMicrosecondsPerSecond;
81dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
82dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
83dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
84dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgdouble TimeDelta::InMillisecondsF() const {
85dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
86dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
87dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
88dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
89dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgint64_t TimeDelta::InMilliseconds() const {
90dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return delta_ / Time::kMicrosecondsPerMillisecond;
91dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
92dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
93dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
94dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgint64_t TimeDelta::InNanoseconds() const {
95dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return delta_ * Time::kNanosecondsPerMicrosecond;
96dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
97dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
98dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
99e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_OS_MACOSX
100e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
101e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgTimeDelta TimeDelta::FromMachTimespec(struct mach_timespec ts) {
102e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_GE(ts.tv_nsec, 0);
103e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_LT(ts.tv_nsec,
104e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org            static_cast<long>(Time::kNanosecondsPerSecond));  // NOLINT
105e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
106e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org                   ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
107e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
108e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
109e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
110e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgstruct mach_timespec TimeDelta::ToMachTimespec() const {
111e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  struct mach_timespec ts;
112e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(delta_ >= 0);
113e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts.tv_sec = delta_ / Time::kMicrosecondsPerSecond;
114e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
115e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      Time::kNanosecondsPerMicrosecond;
116e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return ts;
117e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
118e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
119e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif  // V8_OS_MACOSX
120e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
121e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
122e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_OS_POSIX
123e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
124e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgTimeDelta TimeDelta::FromTimespec(struct timespec ts) {
125e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_GE(ts.tv_nsec, 0);
126e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_LT(ts.tv_nsec,
127e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org            static_cast<long>(Time::kNanosecondsPerSecond));  // NOLINT
128e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
129e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org                   ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
130e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
131e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
132e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
133e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgstruct timespec TimeDelta::ToTimespec() const {
134e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  struct timespec ts;
135e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts.tv_sec = delta_ / Time::kMicrosecondsPerSecond;
136e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
137e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      Time::kNanosecondsPerMicrosecond;
138e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return ts;
139e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
140e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
141e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif  // V8_OS_POSIX
142e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
143e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
144dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#if V8_OS_WIN
145dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
146dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// We implement time using the high-resolution timers so that we can get
147dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// timeouts which are smaller than 10-15ms. To avoid any drift, we
148dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// periodically resync the internal clock to the system clock.
149ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass Clock FINAL {
150dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org public:
151d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {}
152dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
153dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  Time Now() {
154d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // Time between resampling the un-granular clock for this API (1 minute).
155d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1);
156dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
157d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    LockGuard<Mutex> lock_guard(&mutex_);
158dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
159d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // Determine current time and ticks.
160d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    TimeTicks ticks = GetSystemTicks();
161d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    Time time = GetSystemTime();
162d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
163d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // Check if we need to synchronize with the system clock due to a backwards
164d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // time change or the amount of time elapsed.
165d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    TimeDelta elapsed = ticks - initial_ticks_;
166d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    if (time < initial_time_ || elapsed > kMaxElapsedTime) {
167d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      initial_ticks_ = ticks;
168d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      initial_time_ = time;
169d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org      return time;
170dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    }
171dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
172d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    return initial_time_ + elapsed;
173dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
174dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
175dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  Time NowFromSystemTime() {
176dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    LockGuard<Mutex> lock_guard(&mutex_);
177d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    initial_ticks_ = GetSystemTicks();
178d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    initial_time_ = GetSystemTime();
179dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return initial_time_;
180dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
181dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
182dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org private:
183d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  static TimeTicks GetSystemTicks() {
184d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    return TimeTicks::Now();
185d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  }
186dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
187d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  static Time GetSystemTime() {
188dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    FILETIME ft;
189dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    ::GetSystemTimeAsFileTime(&ft);
190dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return Time::FromFiletime(ft);
191dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
192dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
193dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  TimeTicks initial_ticks_;
194dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  Time initial_time_;
195dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  Mutex mutex_;
196dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org};
197dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
198dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
1995de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgstatic LazyStaticInstance<Clock, DefaultConstructTrait<Clock>,
2005de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org                          ThreadSafeInitOnceTrait>::type clock =
2011e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    LAZY_STATIC_INSTANCE_INITIALIZER;
202dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
203dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
204dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::Now() {
205dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return clock.Pointer()->Now();
206dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
207dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
208dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
209dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::NowFromSystemTime() {
210dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return clock.Pointer()->NowFromSystemTime();
211dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
212dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
213dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
214dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// Time between windows epoch and standard epoch.
215dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgstatic const int64_t kTimeToEpochInMicroseconds = V8_INT64_C(11644473600000000);
216dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
217dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
218dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::FromFiletime(FILETIME ft) {
219dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0) {
220dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return Time();
221dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
222dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (ft.dwLowDateTime == std::numeric_limits<DWORD>::max() &&
223dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      ft.dwHighDateTime == std::numeric_limits<DWORD>::max()) {
224dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return Max();
225dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
226dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  int64_t us = (static_cast<uint64_t>(ft.dwLowDateTime) +
227dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org                (static_cast<uint64_t>(ft.dwHighDateTime) << 32)) / 10;
228dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return Time(us - kTimeToEpochInMicroseconds);
229dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
230dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
231dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
232dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgFILETIME Time::ToFiletime() const {
233e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(us_ >= 0);
234dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  FILETIME ft;
235dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (IsNull()) {
236dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    ft.dwLowDateTime = 0;
237dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    ft.dwHighDateTime = 0;
238dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return ft;
239dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
240dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (IsMax()) {
241dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    ft.dwLowDateTime = std::numeric_limits<DWORD>::max();
242dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    ft.dwHighDateTime = std::numeric_limits<DWORD>::max();
243dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return ft;
244dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
245dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  uint64_t us = static_cast<uint64_t>(us_ + kTimeToEpochInMicroseconds) * 10;
246dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ft.dwLowDateTime = static_cast<DWORD>(us);
247dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ft.dwHighDateTime = static_cast<DWORD>(us >> 32);
248dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return ft;
249dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
250dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
251dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#elif V8_OS_POSIX
252dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
253dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::Now() {
254dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  struct timeval tv;
255dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  int result = gettimeofday(&tv, NULL);
256e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
257dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  USE(result);
258dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return FromTimeval(tv);
259dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
260dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
261dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
262dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::NowFromSystemTime() {
263dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return Now();
264dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
265dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
266dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
267e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgTime Time::FromTimespec(struct timespec ts) {
268e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ts.tv_nsec >= 0);
269e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ts.tv_nsec < static_cast<long>(kNanosecondsPerSecond));  // NOLINT
270e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (ts.tv_nsec == 0 && ts.tv_sec == 0) {
271e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return Time();
272e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
273e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (ts.tv_nsec == static_cast<long>(kNanosecondsPerSecond - 1) &&  // NOLINT
274e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      ts.tv_sec == std::numeric_limits<time_t>::max()) {
275e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return Max();
276e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
277e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return Time(ts.tv_sec * kMicrosecondsPerSecond +
278e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org              ts.tv_nsec / kNanosecondsPerMicrosecond);
279e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
280e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
281e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
282e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgstruct timespec Time::ToTimespec() const {
283e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  struct timespec ts;
284e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (IsNull()) {
285e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ts.tv_sec = 0;
286e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ts.tv_nsec = 0;
287e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return ts;
288e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
289e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (IsMax()) {
290e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ts.tv_sec = std::numeric_limits<time_t>::max();
291e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ts.tv_nsec = static_cast<long>(kNanosecondsPerSecond - 1);  // NOLINT
292e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return ts;
293e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
294e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts.tv_sec = us_ / kMicrosecondsPerSecond;
295e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts.tv_nsec = (us_ % kMicrosecondsPerSecond) * kNanosecondsPerMicrosecond;
296e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return ts;
297e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
298e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
299e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
300dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::FromTimeval(struct timeval tv) {
301e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(tv.tv_usec >= 0);
302e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(tv.tv_usec < static_cast<suseconds_t>(kMicrosecondsPerSecond));
303dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (tv.tv_usec == 0 && tv.tv_sec == 0) {
304dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return Time();
305dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
306dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (tv.tv_usec == static_cast<suseconds_t>(kMicrosecondsPerSecond - 1) &&
307dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      tv.tv_sec == std::numeric_limits<time_t>::max()) {
308dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return Max();
309dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
310dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return Time(tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec);
311dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
312dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
313dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
314dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgstruct timeval Time::ToTimeval() const {
315dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  struct timeval tv;
316dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (IsNull()) {
317dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    tv.tv_sec = 0;
318dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    tv.tv_usec = 0;
319dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return tv;
320dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
321dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (IsMax()) {
322dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    tv.tv_sec = std::numeric_limits<time_t>::max();
323dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    tv.tv_usec = static_cast<suseconds_t>(kMicrosecondsPerSecond - 1);
324dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return tv;
325dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
326dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  tv.tv_sec = us_ / kMicrosecondsPerSecond;
327dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  tv.tv_usec = us_ % kMicrosecondsPerSecond;
328dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return tv;
329dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
330dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
331dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#endif  // V8_OS_WIN
332dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
333dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
334dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTime Time::FromJsTime(double ms_since_epoch) {
335dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // The epoch is a valid time, so this constructor doesn't interpret
336dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // 0 as the null time.
337dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (ms_since_epoch == std::numeric_limits<double>::max()) {
338dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return Max();
339dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
340dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return Time(
341dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      static_cast<int64_t>(ms_since_epoch * kMicrosecondsPerMillisecond));
342dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
343dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
344dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
345dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgdouble Time::ToJsTime() const {
346dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (IsNull()) {
347dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // Preserve 0 so the invalid result doesn't depend on the platform.
348dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return 0;
349dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
350dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (IsMax()) {
351dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // Preserve max without offset to prevent overflow.
352dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return std::numeric_limits<double>::max();
353dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
354dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return static_cast<double>(us_) / kMicrosecondsPerMillisecond;
355dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
356dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
357dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
358dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#if V8_OS_WIN
359dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
360dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgclass TickClock {
361dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org public:
362dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  virtual ~TickClock() {}
363dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  virtual int64_t Now() = 0;
364d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  virtual bool IsHighResolution() = 0;
365dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org};
366dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
367dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
368dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// Overview of time counters:
369dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// (1) CPU cycle counter. (Retrieved via RDTSC)
370dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// The CPU counter provides the highest resolution time stamp and is the least
371dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// expensive to retrieve. However, the CPU counter is unreliable and should not
372dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// be used in production. Its biggest issue is that it is per processor and it
373dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// is not synchronized between processors. Also, on some computers, the counters
374dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// will change frequency due to thermal and power changes, and stop in some
375dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// states.
376dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org//
377dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
378dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// resolution (100 nanoseconds) time stamp but is comparatively more expensive
379dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// to retrieve. What QueryPerformanceCounter actually does is up to the HAL.
380dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// (with some help from ACPI).
381dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx
382dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// in the worst case, it gets the counter from the rollover interrupt on the
383dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// programmable interrupt timer. In best cases, the HAL may conclude that the
384dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// RDTSC counter runs at a constant frequency, then it uses that instead. On
385dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// multiprocessor machines, it will try to verify the values returned from
386dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// RDTSC on each processor are consistent with each other, and apply a handful
387dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// of workarounds for known buggy hardware. In other words, QPC is supposed to
388dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// give consistent result on a multiprocessor computer, but it is unreliable in
389dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// reality due to bugs in BIOS or HAL on some, especially old computers.
390dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// With recent updates on HAL and newer BIOS, QPC is getting more reliable but
391dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// it should be used with caution.
392dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org//
393dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// (3) System time. The system time provides a low-resolution (typically 10ms
394dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// to 55 milliseconds) time stamp but is comparatively less expensive to
395dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org// retrieve and more reliable.
396ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass HighResolutionTickClock FINAL : public TickClock {
397dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org public:
398dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  explicit HighResolutionTickClock(int64_t ticks_per_second)
399dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      : ticks_per_second_(ticks_per_second) {
400e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_LT(0, ticks_per_second);
401dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
402dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  virtual ~HighResolutionTickClock() {}
403dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
404ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  virtual int64_t Now() OVERRIDE {
405dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    LARGE_INTEGER now;
406dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    BOOL result = QueryPerformanceCounter(&now);
407e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result);
408dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    USE(result);
409dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
410dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // Intentionally calculate microseconds in a round about manner to avoid
411dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // overflow and precision issues. Think twice before simplifying!
412dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    int64_t whole_seconds = now.QuadPart / ticks_per_second_;
413dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    int64_t leftover_ticks = now.QuadPart % ticks_per_second_;
414dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) +
415dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org        ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_);
416dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
417d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // Make sure we never return 0 here, so that TimeTicks::HighResolutionNow()
418dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // will never return 0.
419dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return ticks + 1;
420dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
421dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
422ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  virtual bool IsHighResolution() OVERRIDE {
423d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    return true;
424dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
425dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
426dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org private:
427d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  int64_t ticks_per_second_;
428dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org};
429dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
430dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
431ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass RolloverProtectedTickClock FINAL : public TickClock {
432dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org public:
433dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // We initialize rollover_ms_ to 1 to ensure that we will never
434d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  // return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below.
435dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {}
436dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  virtual ~RolloverProtectedTickClock() {}
437dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
438ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  virtual int64_t Now() OVERRIDE {
439dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    LockGuard<Mutex> lock_guard(&mutex_);
440dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // We use timeGetTime() to implement TimeTicks::Now(), which rolls over
441dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // every ~49.7 days. We try to track rollover ourselves, which works if
442dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // TimeTicks::Now() is called at least every 49 days.
443dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // Note that we do not use GetTickCount() here, since timeGetTime() gives
444dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // more predictable delta values, as described here:
445dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx
446d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // timeGetTime() provides 1ms granularity when combined with
447d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // timeBeginPeriod(). If the host application for V8 wants fast timers, it
448d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    // can use timeBeginPeriod() to increase the resolution.
449dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    DWORD now = timeGetTime();
450dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    if (now < last_seen_now_) {
451dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      rollover_ms_ += V8_INT64_C(0x100000000);  // ~49.7 days.
452dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    }
453dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    last_seen_now_ = now;
454dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond;
455dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
456dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
457ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  virtual bool IsHighResolution() OVERRIDE {
458d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    return false;
459d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  }
460d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
461dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org private:
462dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  Mutex mutex_;
463dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  DWORD last_seen_now_;
464dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  int64_t rollover_ms_;
465dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org};
466dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
467dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
4685de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgstatic LazyStaticInstance<RolloverProtectedTickClock,
4695de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org                          DefaultConstructTrait<RolloverProtectedTickClock>,
4705de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org                          ThreadSafeInitOnceTrait>::type tick_clock =
4711e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    LAZY_STATIC_INSTANCE_INITIALIZER;
472dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
473dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
474dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgstruct CreateHighResTickClockTrait {
475dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  static TickClock* Create() {
476dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // Check if the installed hardware supports a high-resolution performance
477dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // counter, and if not fallback to the low-resolution tick clock.
478dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    LARGE_INTEGER ticks_per_second;
479dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    if (!QueryPerformanceFrequency(&ticks_per_second)) {
480dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      return tick_clock.Pointer();
481dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    }
482dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
483dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // On Athlon X2 CPUs (e.g. model 15) the QueryPerformanceCounter
484dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    // is unreliable, fallback to the low-resolution tick clock.
485dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    CPU cpu;
486dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    if (strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15) {
487dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org      return tick_clock.Pointer();
488dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    }
489dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
490dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    return new HighResolutionTickClock(ticks_per_second.QuadPart);
491dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
492dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org};
493dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
494dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
4955de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgstatic LazyDynamicInstance<TickClock, CreateHighResTickClockTrait,
4965de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org                           ThreadSafeInitOnceTrait>::type high_res_tick_clock =
4975de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org    LAZY_DYNAMIC_INSTANCE_INITIALIZER;
498dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
499dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
500dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeTicks TimeTicks::Now() {
501dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // Make sure we never return 0 here.
502dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  TimeTicks ticks(tick_clock.Pointer()->Now());
503e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!ticks.IsNull());
504dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return ticks;
505dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
506dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
507dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
508d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgTimeTicks TimeTicks::HighResolutionNow() {
509dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // Make sure we never return 0 here.
510dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  TimeTicks ticks(high_res_tick_clock.Pointer()->Now());
511e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!ticks.IsNull());
512dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return ticks;
513dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
514dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
515d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
516d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org// static
517d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgbool TimeTicks::IsHighResolutionClockWorking() {
518d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  return high_res_tick_clock.Pointer()->IsHighResolution();
519d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org}
520d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
521d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
522d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org// static
523d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgTimeTicks TimeTicks::KernelTimestampNow() { return TimeTicks(0); }
524d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
525d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
526d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org// static
527d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgbool TimeTicks::KernelTimestampAvailable() { return false; }
528d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
529dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#else  // V8_OS_WIN
530dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
531dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.orgTimeTicks TimeTicks::Now() {
532d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  return HighResolutionNow();
533dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
534dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
535dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
536d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgTimeTicks TimeTicks::HighResolutionNow() {
537dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  int64_t ticks;
538dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#if V8_OS_MACOSX
539dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  static struct mach_timebase_info info;
540dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (info.denom == 0) {
541dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    kern_return_t result = mach_timebase_info(&info);
542e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(KERN_SUCCESS, result);
543dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    USE(result);
544dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
545dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ticks = (mach_absolute_time() / Time::kNanosecondsPerMicrosecond *
546dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org           info.numer / info.denom);
547dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#elif V8_OS_SOLARIS
548dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
5497cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org#elif V8_LIBRT_NOT_AVAILABLE
5507cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  // TODO(bmeurer): This is a temporary hack to support cross-compiling
5517cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  // Chrome for Android in AOSP. Remove this once AOSP is fixed, also
5527cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  // cleanup the tools/gyp/v8.gyp file.
5537cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  struct timeval tv;
5547cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  int result = gettimeofday(&tv, NULL);
555e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
5567cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  USE(result);
5577cb86f7bc0558dc51955c821aeda27afbeabe311jkummerow@chromium.org  ticks = (tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec);
558dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#elif V8_OS_POSIX
559dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  struct timespec ts;
560dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  int result = clock_gettime(CLOCK_MONOTONIC, &ts);
561e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
562dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  USE(result);
563dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  ticks = (ts.tv_sec * Time::kMicrosecondsPerSecond +
564dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org           ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
565dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#endif  // V8_OS_MACOSX
566dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  // Make sure we never return 0 here.
567dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  return TimeTicks(ticks + 1);
568dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org}
569dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
570d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
571d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org// static
572d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.orgbool TimeTicks::IsHighResolutionClockWorking() {
573d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  return true;
574d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org}
575d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org
576d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
577d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org#if V8_OS_LINUX && !V8_LIBRT_NOT_AVAILABLE
578d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
579d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgclass KernelTimestampClock {
580d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org public:
581d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  KernelTimestampClock() : clock_fd_(-1), clock_id_(kClockInvalid) {
582d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    clock_fd_ = open(kTraceClockDevice, O_RDONLY);
583d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    if (clock_fd_ == -1) {
584d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      return;
585d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    }
586d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    clock_id_ = get_clockid(clock_fd_);
587d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  }
588d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
589d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  virtual ~KernelTimestampClock() {
590d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    if (clock_fd_ != -1) {
591d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      close(clock_fd_);
592d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    }
593d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  }
594d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
595d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  int64_t Now() {
596d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    if (clock_id_ == kClockInvalid) {
597d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      return 0;
598d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    }
599d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
600d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    struct timespec ts;
601d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
602d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    clock_gettime(clock_id_, &ts);
603d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    return ((int64_t)ts.tv_sec * kNsecPerSec) + ts.tv_nsec;
604d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  }
605d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
606d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  bool Available() { return clock_id_ != kClockInvalid; }
607d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
608d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org private:
609d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  static const clockid_t kClockInvalid = -1;
610d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  static const char kTraceClockDevice[];
611d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  static const uint64_t kNsecPerSec = 1000000000;
612d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
613d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  int clock_fd_;
614d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  clockid_t clock_id_;
615d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
616d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  static int get_clockid(int fd) { return ((~(clockid_t)(fd) << 3) | 3); }
617d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org};
618d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
619d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
620d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org// Timestamp module name
621d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgconst char KernelTimestampClock::kTraceClockDevice[] = "/dev/trace_clock";
622d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
623d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org#else
624d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
625d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgclass KernelTimestampClock {
626d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org public:
627d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  KernelTimestampClock() {}
628d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
629d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  int64_t Now() { return 0; }
630d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  bool Available() { return false; }
631d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org};
632d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
633d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org#endif  // V8_OS_LINUX && !V8_LIBRT_NOT_AVAILABLE
634d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
635d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgstatic LazyStaticInstance<KernelTimestampClock,
636d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org                          DefaultConstructTrait<KernelTimestampClock>,
637d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org                          ThreadSafeInitOnceTrait>::type kernel_tick_clock =
638d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    LAZY_STATIC_INSTANCE_INITIALIZER;
639d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
640d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
641d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org// static
642d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgTimeTicks TimeTicks::KernelTimestampNow() {
643d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  return TimeTicks(kernel_tick_clock.Pointer()->Now());
644d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org}
645d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
646d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
647d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org// static
648d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgbool TimeTicks::KernelTimestampAvailable() {
649d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  return kernel_tick_clock.Pointer()->Available();
650d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org}
651d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
652dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org#endif  // V8_OS_WIN
653dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org
6545de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org} }  // namespace v8::base
655