time.cc 27.7 KB
Newer Older
1
// Copyright 2013 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include "src/base/platform/time.h"
6 7

#if V8_OS_POSIX
8
#include <fcntl.h>  // for O_RDONLY
9
#include <sys/time.h>
10
#include <unistd.h>
11 12
#endif
#if V8_OS_MACOSX
13
#include <mach/mach.h>
14
#include <mach/mach_time.h>
15
#include <pthread.h>
16 17
#endif

18 19
#include <cstring>
#include <ostream>
20

21
#if V8_OS_WIN
22
#include "src/base/atomicops.h"
23 24 25
#include "src/base/lazy-instance.h"
#include "src/base/win32-headers.h"
#endif
26 27 28
#include "src/base/cpu.h"
#include "src/base/logging.h"
#include "src/base/platform/platform.h"
29

30 31 32 33 34 35 36 37 38 39 40
namespace {

#if V8_OS_MACOSX
int64_t ComputeThreadTicks() {
  mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
  thread_basic_info_data_t thread_info_data;
  kern_return_t kr = thread_info(
      pthread_mach_thread_np(pthread_self()),
      THREAD_BASIC_INFO,
      reinterpret_cast<thread_info_t>(&thread_info_data),
      &thread_info_count);
41
  CHECK_EQ(kr, KERN_SUCCESS);
42 43

  v8::base::CheckedNumeric<int64_t> absolute_micros(
44 45
      thread_info_data.user_time.seconds +
      thread_info_data.system_time.seconds);
46
  absolute_micros *= v8::base::Time::kMicrosecondsPerSecond;
47 48
  absolute_micros += (thread_info_data.user_time.microseconds +
                      thread_info_data.system_time.microseconds);
49 50 51 52 53 54 55
  return absolute_micros.ValueOrDie();
}
#elif V8_OS_POSIX
// Helper function to get results from clock_gettime() and convert to a
// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
// _POSIX_MONOTONIC_CLOCK to -1.
56
V8_INLINE int64_t ClockNow(clockid_t clk_id) {
57 58
#if (defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
  defined(V8_OS_BSD) || defined(V8_OS_ANDROID)
59 60 61 62 63 64 65 66 67 68
// On AIX clock_gettime for CLOCK_THREAD_CPUTIME_ID outputs time with
// resolution of 10ms. thread_cputime API provides the time in ns
#if defined(V8_OS_AIX)
  thread_cputime_t tc;
  if (clk_id == CLOCK_THREAD_CPUTIME_ID) {
    if (thread_cputime(-1, &tc) != 0) {
      UNREACHABLE();
    }
  }
#endif
69 70 71 72 73 74
  struct timespec ts;
  if (clock_gettime(clk_id, &ts) != 0) {
    UNREACHABLE();
  }
  v8::base::internal::CheckedNumeric<int64_t> result(ts.tv_sec);
  result *= v8::base::Time::kMicrosecondsPerSecond;
75 76 77 78 79 80 81
#if defined(V8_OS_AIX)
  if (clk_id == CLOCK_THREAD_CPUTIME_ID) {
    result += (tc.stime / v8::base::Time::kNanosecondsPerMicrosecond);
  } else {
    result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
  }
#else
82
  result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
83
#endif
84 85 86 87 88
  return result.ValueOrDie();
#else  // Monotonic clock not supported.
  return 0;
#endif
}
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

V8_INLINE bool IsHighResolutionTimer(clockid_t clk_id) {
  // Limit duration of timer resolution measurement to 100 ms. If we cannot
  // measure timer resoltuion within this time, we assume a low resolution
  // timer.
  int64_t end =
      ClockNow(clk_id) + 100 * v8::base::Time::kMicrosecondsPerMillisecond;
  int64_t start, delta;
  do {
    start = ClockNow(clk_id);
    // Loop until we can detect that the clock has changed. Non-HighRes timers
    // will increment in chunks, i.e. 15ms. By spinning until we see a clock
    // change, we detect the minimum time between measurements.
    do {
      delta = ClockNow(clk_id) - start;
    } while (delta == 0);
  } while (delta > 1 && start < end);
  return delta <= 1;
}

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#elif V8_OS_WIN
V8_INLINE bool IsQPCReliable() {
  v8::base::CPU cpu;
  // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable.
  return strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15;
}

// Returns the current value of the performance counter.
V8_INLINE uint64_t QPCNowRaw() {
  LARGE_INTEGER perf_counter_now = {};
  // According to the MSDN documentation for QueryPerformanceCounter(), this
  // will never fail on systems that run XP or later.
  // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
  BOOL result = ::QueryPerformanceCounter(&perf_counter_now);
  DCHECK(result);
  USE(result);
  return perf_counter_now.QuadPart;
}
127 128 129 130 131
#endif  // V8_OS_MACOSX


}  // namespace

132
namespace v8 {
133
namespace base {
134 135

int TimeDelta::InDays() const {
136 137 138 139
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int>::max();
  }
140 141 142 143
  return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
}

int TimeDelta::InHours() const {
144 145 146 147
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int>::max();
  }
148 149 150 151
  return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
}

int TimeDelta::InMinutes() const {
152 153 154 155
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int>::max();
  }
156 157 158 159
  return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
}

double TimeDelta::InSecondsF() const {
160 161 162 163
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<double>::infinity();
  }
164 165 166 167
  return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
}

int64_t TimeDelta::InSeconds() const {
168 169 170 171
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int64_t>::max();
  }
172 173 174 175
  return delta_ / Time::kMicrosecondsPerSecond;
}

double TimeDelta::InMillisecondsF() const {
176 177 178 179
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<double>::infinity();
  }
180 181 182 183
  return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
}

int64_t TimeDelta::InMilliseconds() const {
184 185 186 187
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int64_t>::max();
  }
188 189 190
  return delta_ / Time::kMicrosecondsPerMillisecond;
}

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
int64_t TimeDelta::InMillisecondsRoundedUp() const {
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int64_t>::max();
  }
  return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
         Time::kMicrosecondsPerMillisecond;
}

int64_t TimeDelta::InMicroseconds() const {
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int64_t>::max();
  }
  return delta_;
}
207 208

int64_t TimeDelta::InNanoseconds() const {
209 210 211 212
  if (IsMax()) {
    // Preserve max to prevent overflow.
    return std::numeric_limits<int64_t>::max();
  }
213 214 215 216
  return delta_ * Time::kNanosecondsPerMicrosecond;
}


217 218 219
#if V8_OS_MACOSX

TimeDelta TimeDelta::FromMachTimespec(struct mach_timespec ts) {
220 221
  DCHECK_GE(ts.tv_nsec, 0);
  DCHECK_LT(ts.tv_nsec,
222
            static_cast<long>(Time::kNanosecondsPerSecond));  // NOLINT
223 224 225 226 227 228 229
  return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
                   ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
}


struct mach_timespec TimeDelta::ToMachTimespec() const {
  struct mach_timespec ts;
230
  DCHECK_GE(delta_, 0);
231
  ts.tv_sec = static_cast<unsigned>(delta_ / Time::kMicrosecondsPerSecond);
232 233 234 235 236 237 238 239
  ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
      Time::kNanosecondsPerMicrosecond;
  return ts;
}

#endif  // V8_OS_MACOSX


240 241 242
#if V8_OS_POSIX

TimeDelta TimeDelta::FromTimespec(struct timespec ts) {
243 244
  DCHECK_GE(ts.tv_nsec, 0);
  DCHECK_LT(ts.tv_nsec,
245 246 247 248 249 250 251 252
            static_cast<long>(Time::kNanosecondsPerSecond));  // NOLINT
  return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
                   ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
}


struct timespec TimeDelta::ToTimespec() const {
  struct timespec ts;
253
  ts.tv_sec = static_cast<time_t>(delta_ / Time::kMicrosecondsPerSecond);
254 255 256 257 258 259 260 261
  ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
      Time::kNanosecondsPerMicrosecond;
  return ts;
}

#endif  // V8_OS_POSIX


262 263 264 265 266
#if V8_OS_WIN

// We implement time using the high-resolution timers so that we can get
// timeouts which are smaller than 10-15ms. To avoid any drift, we
// periodically resync the internal clock to the system clock.
267
class Clock final {
268
 public:
269
  Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {}
270 271

  Time Now() {
272 273
    // Time between resampling the un-granular clock for this API (1 minute).
    const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1);
274

275
    MutexGuard lock_guard(&mutex_);
276

277 278 279 280 281 282 283 284 285 286 287
    // Determine current time and ticks.
    TimeTicks ticks = GetSystemTicks();
    Time time = GetSystemTime();

    // Check if we need to synchronize with the system clock due to a backwards
    // time change or the amount of time elapsed.
    TimeDelta elapsed = ticks - initial_ticks_;
    if (time < initial_time_ || elapsed > kMaxElapsedTime) {
      initial_ticks_ = ticks;
      initial_time_ = time;
      return time;
288 289
    }

290
    return initial_time_ + elapsed;
291 292 293
  }

  Time NowFromSystemTime() {
294
    MutexGuard lock_guard(&mutex_);
295 296
    initial_ticks_ = GetSystemTicks();
    initial_time_ = GetSystemTime();
297 298 299 300
    return initial_time_;
  }

 private:
301 302 303
  static TimeTicks GetSystemTicks() {
    return TimeTicks::Now();
  }
304

305
  static Time GetSystemTime() {
306 307 308 309 310 311 312
    FILETIME ft;
    ::GetSystemTimeAsFileTime(&ft);
    return Time::FromFiletime(ft);
  }

  TimeTicks initial_ticks_;
  Time initial_time_;
313
  Mutex mutex_;
314 315
};

316
namespace {
317 318
DEFINE_LAZY_LEAKY_OBJECT_GETTER(Clock, GetClock)
}
319

320
Time Time::Now() { return GetClock()->Now(); }
321

322
Time Time::NowFromSystemTime() { return GetClock()->NowFromSystemTime(); }
323 324

// Time between windows epoch and standard epoch.
325
static const int64_t kTimeToEpochInMicroseconds = int64_t{11644473600000000};
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341

Time Time::FromFiletime(FILETIME ft) {
  if (ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0) {
    return Time();
  }
  if (ft.dwLowDateTime == std::numeric_limits<DWORD>::max() &&
      ft.dwHighDateTime == std::numeric_limits<DWORD>::max()) {
    return Max();
  }
  int64_t us = (static_cast<uint64_t>(ft.dwLowDateTime) +
                (static_cast<uint64_t>(ft.dwHighDateTime) << 32)) / 10;
  return Time(us - kTimeToEpochInMicroseconds);
}


FILETIME Time::ToFiletime() const {
342
  DCHECK_GE(us_, 0);
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
  FILETIME ft;
  if (IsNull()) {
    ft.dwLowDateTime = 0;
    ft.dwHighDateTime = 0;
    return ft;
  }
  if (IsMax()) {
    ft.dwLowDateTime = std::numeric_limits<DWORD>::max();
    ft.dwHighDateTime = std::numeric_limits<DWORD>::max();
    return ft;
  }
  uint64_t us = static_cast<uint64_t>(us_ + kTimeToEpochInMicroseconds) * 10;
  ft.dwLowDateTime = static_cast<DWORD>(us);
  ft.dwHighDateTime = static_cast<DWORD>(us >> 32);
  return ft;
}

#elif V8_OS_POSIX

Time Time::Now() {
  struct timeval tv;
364
  int result = gettimeofday(&tv, nullptr);
365
  DCHECK_EQ(0, result);
366 367 368 369 370 371 372 373 374 375
  USE(result);
  return FromTimeval(tv);
}


Time Time::NowFromSystemTime() {
  return Now();
}


376
Time Time::FromTimespec(struct timespec ts) {
377 378
  DCHECK_GE(ts.tv_nsec, 0);
  DCHECK_LT(ts.tv_nsec, kNanosecondsPerSecond);
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
  if (ts.tv_nsec == 0 && ts.tv_sec == 0) {
    return Time();
  }
  if (ts.tv_nsec == static_cast<long>(kNanosecondsPerSecond - 1) &&  // NOLINT
      ts.tv_sec == std::numeric_limits<time_t>::max()) {
    return Max();
  }
  return Time(ts.tv_sec * kMicrosecondsPerSecond +
              ts.tv_nsec / kNanosecondsPerMicrosecond);
}


struct timespec Time::ToTimespec() const {
  struct timespec ts;
  if (IsNull()) {
    ts.tv_sec = 0;
    ts.tv_nsec = 0;
    return ts;
  }
  if (IsMax()) {
    ts.tv_sec = std::numeric_limits<time_t>::max();
    ts.tv_nsec = static_cast<long>(kNanosecondsPerSecond - 1);  // NOLINT
    return ts;
  }
403
  ts.tv_sec = static_cast<time_t>(us_ / kMicrosecondsPerSecond);
404 405 406 407 408
  ts.tv_nsec = (us_ % kMicrosecondsPerSecond) * kNanosecondsPerMicrosecond;
  return ts;
}


409
Time Time::FromTimeval(struct timeval tv) {
410
  DCHECK_GE(tv.tv_usec, 0);
411
  DCHECK(tv.tv_usec < static_cast<suseconds_t>(kMicrosecondsPerSecond));
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
  if (tv.tv_usec == 0 && tv.tv_sec == 0) {
    return Time();
  }
  if (tv.tv_usec == static_cast<suseconds_t>(kMicrosecondsPerSecond - 1) &&
      tv.tv_sec == std::numeric_limits<time_t>::max()) {
    return Max();
  }
  return Time(tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec);
}


struct timeval Time::ToTimeval() const {
  struct timeval tv;
  if (IsNull()) {
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    return tv;
  }
  if (IsMax()) {
    tv.tv_sec = std::numeric_limits<time_t>::max();
    tv.tv_usec = static_cast<suseconds_t>(kMicrosecondsPerSecond - 1);
    return tv;
  }
435
  tv.tv_sec = static_cast<time_t>(us_ / kMicrosecondsPerSecond);
436 437 438 439 440 441
  tv.tv_usec = us_ % kMicrosecondsPerSecond;
  return tv;
}

#endif  // V8_OS_WIN

442 443
// static
TimeTicks TimeTicks::HighResolutionNow() {
444 445 446 447 448
  // a DCHECK of TimeTicks::IsHighResolution() was removed from here
  // as it turns out this path is used in the wild for logs and counters.
  //
  // TODO(hpayer) We may eventually want to split TimedHistograms based
  // on low resolution clocks to avoid polluting metrics
449 450
  return TimeTicks::Now();
}
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475

Time Time::FromJsTime(double ms_since_epoch) {
  // The epoch is a valid time, so this constructor doesn't interpret
  // 0 as the null time.
  if (ms_since_epoch == std::numeric_limits<double>::max()) {
    return Max();
  }
  return Time(
      static_cast<int64_t>(ms_since_epoch * kMicrosecondsPerMillisecond));
}


double Time::ToJsTime() const {
  if (IsNull()) {
    // Preserve 0 so the invalid result doesn't depend on the platform.
    return 0;
  }
  if (IsMax()) {
    // Preserve max without offset to prevent overflow.
    return std::numeric_limits<double>::max();
  }
  return static_cast<double>(us_) / kMicrosecondsPerMillisecond;
}


476 477 478 479 480
std::ostream& operator<<(std::ostream& os, const Time& time) {
  return os << time.ToJsTime();
}


481 482
#if V8_OS_WIN

483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
namespace {

// We define a wrapper to adapt between the __stdcall and __cdecl call of the
// mock function, and to avoid a static constructor.  Assigning an import to a
// function pointer directly would require setup code to fetch from the IAT.
DWORD timeGetTimeWrapper() { return timeGetTime(); }

DWORD (*g_tick_function)(void) = &timeGetTimeWrapper;

// A structure holding the most significant bits of "last seen" and a
// "rollover" counter.
union LastTimeAndRolloversState {
  // The state as a single 32-bit opaque value.
  base::Atomic32 as_opaque_32;

  // The state as usable values.
  struct {
    // The top 8-bits of the "last" time. This is enough to check for rollovers
    // and the small bit-size means fewer CompareAndSwap operations to store
    // changes in state, which in turn makes for fewer retries.
    uint8_t last_8;
    // A count of the number of detected rollovers. Using this as bits 47-32
    // of the upper half of a 64-bit value results in a 48-bit tick counter.
    // This extends the total rollover period from about 49 days to about 8800
    // years while still allowing it to be stored with last_8 in a single
    // 32-bit value.
    uint16_t rollovers;
  } as_values;
511
};
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
base::Atomic32 g_last_time_and_rollovers = 0;
static_assert(sizeof(LastTimeAndRolloversState) <=
                  sizeof(g_last_time_and_rollovers),
              "LastTimeAndRolloversState does not fit in a single atomic word");

// We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
// because it returns the number of milliseconds since Windows has started,
// which will roll over the 32-bit value every ~49 days.  We try to track
// rollover ourselves, which works if TimeTicks::Now() is called at least every
// 48.8 days (not 49 days because only changes in the top 8 bits get noticed).
TimeTicks RolloverProtectedNow() {
  LastTimeAndRolloversState state;
  DWORD now;  // DWORD is always unsigned 32 bits.

  while (true) {
    // Fetch the "now" and "last" tick values, updating "last" with "now" and
    // incrementing the "rollovers" counter if the tick-value has wrapped back
    // around. Atomic operations ensure that both "last" and "rollovers" are
    // always updated together.
    int32_t original = base::Acquire_Load(&g_last_time_and_rollovers);
    state.as_opaque_32 = original;
    now = g_tick_function();
    uint8_t now_8 = static_cast<uint8_t>(now >> 24);
    if (now_8 < state.as_values.last_8) ++state.as_values.rollovers;
    state.as_values.last_8 = now_8;

    // If the state hasn't changed, exit the loop.
    if (state.as_opaque_32 == original) break;

    // Save the changed state. If the existing value is unchanged from the
    // original, exit the loop.
    int32_t check = base::Release_CompareAndSwap(&g_last_time_and_rollovers,
                                                 original, state.as_opaque_32);
    if (check == original) break;

    // Another thread has done something in between so retry from the top.
  }
549

550 551 552 553
  return TimeTicks() +
         TimeDelta::FromMilliseconds(
             now + (static_cast<uint64_t>(state.as_values.rollovers) << 32));
}
554

555 556
// Discussion of tick counter options on Windows:
//
557 558
// (1) CPU cycle counter. (Retrieved via RDTSC)
// The CPU counter provides the highest resolution time stamp and is the least
559 560 561 562
// expensive to retrieve. However, on older CPUs, two issues can affect its
// reliability: First it is maintained per processor and not synchronized
// between processors. Also, the counters will change frequency due to thermal
// and power changes, and stop in some states.
563 564
//
// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
565 566 567 568 569 570 571 572 573 574
// resolution (<1 microsecond) time stamp. On most hardware running today, it
// auto-detects and uses the constant-rate RDTSC counter to provide extremely
// efficient and reliable time stamps.
//
// On older CPUs where RDTSC is unreliable, it falls back to using more
// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI
// PM timer, and can involve system calls; and all this is up to the HAL (with
// some help from ACPI). According to
// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the
// worst case, it gets the counter from the rollover interrupt on the
575 576 577 578 579
// programmable interrupt timer. In best cases, the HAL may conclude that the
// RDTSC counter runs at a constant frequency, then it uses that instead. On
// multiprocessor machines, it will try to verify the values returned from
// RDTSC on each processor are consistent with each other, and apply a handful
// of workarounds for known buggy hardware. In other words, QPC is supposed to
580 581
// give consistent results on a multiprocessor computer, but for older CPUs it
// can be unreliable due bugs in BIOS or HAL.
582
//
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6
// milliseconds) time stamp but is comparatively less expensive to retrieve and
// more reliable. Time::EnableHighResolutionTimer() and
// Time::ActivateHighResolutionTimer() can be called to alter the resolution of
// this timer; and also other Windows applications can alter it, affecting this
// one.

TimeTicks InitialTimeTicksNowFunction();

// See "threading notes" in InitializeNowFunctionPointer() for details on how
// concurrent reads/writes to these globals has been made safe.
using TimeTicksNowFunction = decltype(&TimeTicks::Now);
TimeTicksNowFunction g_time_ticks_now_function = &InitialTimeTicksNowFunction;
int64_t g_qpc_ticks_per_second = 0;

// As of January 2015, use of <atomic> is forbidden in Chromium code. This is
// what std::atomic_thread_fence does on Windows on all Intel architectures when
// the memory_order argument is anything but std::memory_order_seq_cst:
#define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier();

TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) {
  // Ensure that the assignment to |g_qpc_ticks_per_second|, made in
  // InitializeNowFunctionPointer(), has happened by this point.
  ATOMIC_THREAD_FENCE(memory_order_acquire);

  DCHECK_GT(g_qpc_ticks_per_second, 0);

  // If the QPC Value is below the overflow threshold, we proceed with
  // simple multiply and divide.
  if (qpc_value < TimeTicks::kQPCOverflowThreshold) {
    return TimeDelta::FromMicroseconds(
        qpc_value * TimeTicks::kMicrosecondsPerSecond / g_qpc_ticks_per_second);
615
  }
616 617 618 619 620 621 622 623 624
  // Otherwise, calculate microseconds in a round about manner to avoid
  // overflow and precision issues.
  int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second;
  int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second);
  return TimeDelta::FromMicroseconds(
      (whole_seconds * TimeTicks::kMicrosecondsPerSecond) +
      ((leftover_ticks * TimeTicks::kMicrosecondsPerSecond) /
       g_qpc_ticks_per_second));
}
625

626
TimeTicks QPCNow() { return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw()); }
627

628 629 630 631
bool IsBuggyAthlon(const CPU& cpu) {
  // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable.
  return strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15;
}
632

633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
void InitializeTimeTicksNowFunctionPointer() {
  LARGE_INTEGER ticks_per_sec = {};
  if (!QueryPerformanceFrequency(&ticks_per_sec)) ticks_per_sec.QuadPart = 0;

  // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use
  // the low-resolution clock.
  //
  // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
  // will still use the low-resolution clock. A CPU lacking a non-stop time
  // counter will cause Windows to provide an alternate QPC implementation that
  // works, but is expensive to use. Certain Athlon CPUs are known to make the
  // QPC implementation unreliable.
  //
  // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
  // ~72% of users fall within this category.
  TimeTicksNowFunction now_function;
  CPU cpu;
  if (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter() ||
      IsBuggyAthlon(cpu)) {
    now_function = &RolloverProtectedNow;
  } else {
    now_function = &QPCNow;
655 656
  }

657 658 659 660 661 662 663 664 665 666 667 668 669
  // Threading note 1: In an unlikely race condition, it's possible for two or
  // more threads to enter InitializeNowFunctionPointer() in parallel. This is
  // not a problem since all threads should end up writing out the same values
  // to the global variables.
  //
  // Threading note 2: A release fence is placed here to ensure, from the
  // perspective of other threads using the function pointers, that the
  // assignment to |g_qpc_ticks_per_second| happens before the function pointers
  // are changed.
  g_qpc_ticks_per_second = ticks_per_sec.QuadPart;
  ATOMIC_THREAD_FENCE(memory_order_release);
  g_time_ticks_now_function = now_function;
}
670

671 672 673 674
TimeTicks InitialTimeTicksNowFunction() {
  InitializeTimeTicksNowFunctionPointer();
  return g_time_ticks_now_function();
}
675

676
#undef ATOMIC_THREAD_FENCE
677

678
}  // namespace
679

680
// static
681 682
TimeTicks TimeTicks::Now() {
  // Make sure we never return 0 here.
683
  TimeTicks ticks(g_time_ticks_now_function());
684
  DCHECK(!ticks.IsNull());
685 686 687
  return ticks;
}

688
// static
689 690 691 692
bool TimeTicks::IsHighResolution() {
  if (g_time_ticks_now_function == &InitialTimeTicksNowFunction)
    InitializeTimeTicksNowFunctionPointer();
  return g_time_ticks_now_function == &QPCNow;
693 694
}

695 696 697 698 699 700 701 702
#else  // V8_OS_WIN

TimeTicks TimeTicks::Now() {
  int64_t ticks;
#if V8_OS_MACOSX
  static struct mach_timebase_info info;
  if (info.denom == 0) {
    kern_return_t result = mach_timebase_info(&info);
703
    DCHECK_EQ(KERN_SUCCESS, result);
704 705 706 707 708 709 710
    USE(result);
  }
  ticks = (mach_absolute_time() / Time::kNanosecondsPerMicrosecond *
           info.numer / info.denom);
#elif V8_OS_SOLARIS
  ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
#elif V8_OS_POSIX
711
  ticks = ClockNow(CLOCK_MONOTONIC);
712 713
#else
#error platform does not implement TimeTicks::HighResolutionNow.
714 715 716 717 718
#endif  // V8_OS_MACOSX
  // Make sure we never return 0 here.
  return TimeTicks(ticks + 1);
}

719
// static
720 721 722 723 724 725 726 727 728 729
bool TimeTicks::IsHighResolution() {
#if V8_OS_MACOSX
  return true;
#elif V8_OS_POSIX
  static bool is_high_resolution = IsHighResolutionTimer(CLOCK_MONOTONIC);
  return is_high_resolution;
#else
  return true;
#endif
}
730

731 732
#endif  // V8_OS_WIN

733 734 735

bool ThreadTicks::IsSupported() {
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
736
    defined(V8_OS_MACOSX) || defined(V8_OS_ANDROID) || defined(V8_OS_SOLARIS)
lpy's avatar
lpy committed
737 738 739
  return true;
#elif defined(V8_OS_WIN)
  return IsSupportedWin();
740
#else
lpy's avatar
lpy committed
741
  return false;
742 743 744 745 746 747 748 749 750 751
#endif
}


ThreadTicks ThreadTicks::Now() {
#if V8_OS_MACOSX
  return ThreadTicks(ComputeThreadTicks());
#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
  defined(V8_OS_ANDROID)
  return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
752 753
#elif V8_OS_SOLARIS
  return ThreadTicks(gethrvtime() / Time::kNanosecondsPerMicrosecond);
754 755
#elif V8_OS_WIN
  return ThreadTicks::GetForThread(::GetCurrentThread());
756 757 758 759 760
#else
  UNREACHABLE();
#endif
}

761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793

#if V8_OS_WIN
ThreadTicks ThreadTicks::GetForThread(const HANDLE& thread_handle) {
  DCHECK(IsSupported());

  // Get the number of TSC ticks used by the current thread.
  ULONG64 thread_cycle_time = 0;
  ::QueryThreadCycleTime(thread_handle, &thread_cycle_time);

  // Get the frequency of the TSC.
  double tsc_ticks_per_second = TSCTicksPerSecond();
  if (tsc_ticks_per_second == 0)
    return ThreadTicks();

  // Return the CPU time of the current thread.
  double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
  return ThreadTicks(
      static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond));
}

// static
bool ThreadTicks::IsSupportedWin() {
  static bool is_supported = base::CPU().has_non_stop_time_stamp_counter() &&
                             !IsQPCReliable();
  return is_supported;
}

// static
void ThreadTicks::WaitUntilInitializedWin() {
  while (TSCTicksPerSecond() == 0)
    ::Sleep(10);
}

794 795 796 797 798 799
#ifdef V8_HOST_ARCH_ARM64
#define ReadCycleCounter() _ReadStatusReg(ARM64_PMCCNTR_EL0)
#else
#define ReadCycleCounter() __rdtsc()
#endif

800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
double ThreadTicks::TSCTicksPerSecond() {
  DCHECK(IsSupported());

  // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
  // frequency, because there is no guarantee that the TSC frequency is equal to
  // the performance counter frequency.

  // The TSC frequency is cached in a static variable because it takes some time
  // to compute it.
  static double tsc_ticks_per_second = 0;
  if (tsc_ticks_per_second != 0)
    return tsc_ticks_per_second;

  // Increase the thread priority to reduces the chances of having a context
  // switch during a reading of the TSC and the performance counter.
  int previous_priority = ::GetThreadPriority(::GetCurrentThread());
  ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

  // The first time that this function is called, make an initial reading of the
  // TSC and the performance counter.
820
  static const uint64_t tsc_initial = ReadCycleCounter();
821 822 823 824
  static const uint64_t perf_counter_initial = QPCNowRaw();

  // Make a another reading of the TSC and the performance counter every time
  // that this function is called.
825
  uint64_t tsc_now = ReadCycleCounter();
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
  uint64_t perf_counter_now = QPCNowRaw();

  // Reset the thread priority.
  ::SetThreadPriority(::GetCurrentThread(), previous_priority);

  // Make sure that at least 50 ms elapsed between the 2 readings. The first
  // time that this function is called, we don't expect this to be the case.
  // Note: The longer the elapsed time between the 2 readings is, the more
  //   accurate the computed TSC frequency will be. The 50 ms value was
  //   chosen because local benchmarks show that it allows us to get a
  //   stddev of less than 1 tick/us between multiple runs.
  // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
  //   this will never fail on systems that run XP or later.
  //   https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
  LARGE_INTEGER perf_counter_frequency = {};
  ::QueryPerformanceFrequency(&perf_counter_frequency);
  DCHECK_GE(perf_counter_now, perf_counter_initial);
  uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
  double elapsed_time_seconds =
      perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);

  const double kMinimumEvaluationPeriodSeconds = 0.05;
  if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
    return 0;

  // Compute the frequency of the TSC.
  DCHECK_GE(tsc_now, tsc_initial);
  uint64_t tsc_ticks = tsc_now - tsc_initial;
  tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;

  return tsc_ticks_per_second;
}
858
#undef ReadCycleCounter
859 860
#endif  // V8_OS_WIN

861 862
}  // namespace base
}  // namespace v8