11cb0ef41Sopenharmony_ci// Copyright 2013 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/base/platform/time.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#if V8_OS_POSIX
81cb0ef41Sopenharmony_ci#include <fcntl.h>  // for O_RDONLY
91cb0ef41Sopenharmony_ci#include <sys/time.h>
101cb0ef41Sopenharmony_ci#include <unistd.h>
111cb0ef41Sopenharmony_ci#endif
121cb0ef41Sopenharmony_ci#if V8_OS_DARWIN
131cb0ef41Sopenharmony_ci#include <mach/mach.h>
141cb0ef41Sopenharmony_ci#include <mach/mach_time.h>
151cb0ef41Sopenharmony_ci#include <pthread.h>
161cb0ef41Sopenharmony_ci#endif
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci#include <cstring>
191cb0ef41Sopenharmony_ci#include <ostream>
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci#if V8_OS_WIN
221cb0ef41Sopenharmony_ci#include <windows.h>
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// This has to come after windows.h.
251cb0ef41Sopenharmony_ci#include <mmsystem.h>  // For timeGetTime().
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#include <atomic>
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include "src/base/lazy-instance.h"
301cb0ef41Sopenharmony_ci#include "src/base/win32-headers.h"
311cb0ef41Sopenharmony_ci#endif
321cb0ef41Sopenharmony_ci#include "src/base/cpu.h"
331cb0ef41Sopenharmony_ci#include "src/base/logging.h"
341cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci#if V8_OS_STARBOARD
371cb0ef41Sopenharmony_ci#include "starboard/time.h"
381cb0ef41Sopenharmony_ci#endif
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_cinamespace {
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci#if V8_OS_DARWIN
431cb0ef41Sopenharmony_ciint64_t ComputeThreadTicks() {
441cb0ef41Sopenharmony_ci  mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
451cb0ef41Sopenharmony_ci  thread_basic_info_data_t thread_info_data;
461cb0ef41Sopenharmony_ci  kern_return_t kr = thread_info(
471cb0ef41Sopenharmony_ci      pthread_mach_thread_np(pthread_self()),
481cb0ef41Sopenharmony_ci      THREAD_BASIC_INFO,
491cb0ef41Sopenharmony_ci      reinterpret_cast<thread_info_t>(&thread_info_data),
501cb0ef41Sopenharmony_ci      &thread_info_count);
511cb0ef41Sopenharmony_ci  CHECK_EQ(kr, KERN_SUCCESS);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  // We can add the seconds into a {int64_t} without overflow.
541cb0ef41Sopenharmony_ci  CHECK_LE(thread_info_data.user_time.seconds,
551cb0ef41Sopenharmony_ci           std::numeric_limits<int64_t>::max() -
561cb0ef41Sopenharmony_ci               thread_info_data.system_time.seconds);
571cb0ef41Sopenharmony_ci  int64_t seconds =
581cb0ef41Sopenharmony_ci      thread_info_data.user_time.seconds + thread_info_data.system_time.seconds;
591cb0ef41Sopenharmony_ci  // Multiplying the seconds by {kMicrosecondsPerSecond}, and adding something
601cb0ef41Sopenharmony_ci  // in [0, 2 * kMicrosecondsPerSecond) must result in a valid {int64_t}.
611cb0ef41Sopenharmony_ci  static constexpr int64_t kSecondsLimit =
621cb0ef41Sopenharmony_ci      (std::numeric_limits<int64_t>::max() /
631cb0ef41Sopenharmony_ci       v8::base::Time::kMicrosecondsPerSecond) -
641cb0ef41Sopenharmony_ci      2;
651cb0ef41Sopenharmony_ci  CHECK_GT(kSecondsLimit, seconds);
661cb0ef41Sopenharmony_ci  int64_t micros = seconds * v8::base::Time::kMicrosecondsPerSecond;
671cb0ef41Sopenharmony_ci  micros += (thread_info_data.user_time.microseconds +
681cb0ef41Sopenharmony_ci             thread_info_data.system_time.microseconds);
691cb0ef41Sopenharmony_ci  return micros;
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci#elif V8_OS_POSIX
721cb0ef41Sopenharmony_ci// Helper function to get results from clock_gettime() and convert to a
731cb0ef41Sopenharmony_ci// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
741cb0ef41Sopenharmony_ci// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
751cb0ef41Sopenharmony_ci// _POSIX_MONOTONIC_CLOCK to -1.
761cb0ef41Sopenharmony_ciV8_INLINE int64_t ClockNow(clockid_t clk_id) {
771cb0ef41Sopenharmony_ci#if (defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
781cb0ef41Sopenharmony_ci  defined(V8_OS_BSD) || defined(V8_OS_ANDROID)
791cb0ef41Sopenharmony_ci#if defined(V8_OS_AIX)
801cb0ef41Sopenharmony_ci  // On AIX clock_gettime for CLOCK_THREAD_CPUTIME_ID outputs time with
811cb0ef41Sopenharmony_ci  // resolution of 10ms. thread_cputime API provides the time in ns.
821cb0ef41Sopenharmony_ci  if (clk_id == CLOCK_THREAD_CPUTIME_ID) {
831cb0ef41Sopenharmony_ci#if defined(__PASE__)  // CLOCK_THREAD_CPUTIME_ID clock not supported on IBMi
841cb0ef41Sopenharmony_ci    return 0;
851cb0ef41Sopenharmony_ci#else
861cb0ef41Sopenharmony_ci    thread_cputime_t tc;
871cb0ef41Sopenharmony_ci    if (thread_cputime(-1, &tc) != 0) {
881cb0ef41Sopenharmony_ci      UNREACHABLE();
891cb0ef41Sopenharmony_ci    }
901cb0ef41Sopenharmony_ci    return (tc.stime / v8::base::Time::kNanosecondsPerMicrosecond)
911cb0ef41Sopenharmony_ci           + (tc.utime / v8::base::Time::kNanosecondsPerMicrosecond);
921cb0ef41Sopenharmony_ci#endif  // defined(__PASE__)
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci#endif  // defined(V8_OS_AIX)
951cb0ef41Sopenharmony_ci  struct timespec ts;
961cb0ef41Sopenharmony_ci  if (clock_gettime(clk_id, &ts) != 0) {
971cb0ef41Sopenharmony_ci    UNREACHABLE();
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci  // Multiplying the seconds by {kMicrosecondsPerSecond}, and adding something
1001cb0ef41Sopenharmony_ci  // in [0, kMicrosecondsPerSecond) must result in a valid {int64_t}.
1011cb0ef41Sopenharmony_ci  static constexpr int64_t kSecondsLimit =
1021cb0ef41Sopenharmony_ci      (std::numeric_limits<int64_t>::max() /
1031cb0ef41Sopenharmony_ci       v8::base::Time::kMicrosecondsPerSecond) -
1041cb0ef41Sopenharmony_ci      1;
1051cb0ef41Sopenharmony_ci  CHECK_GT(kSecondsLimit, ts.tv_sec);
1061cb0ef41Sopenharmony_ci  int64_t result = int64_t{ts.tv_sec} * v8::base::Time::kMicrosecondsPerSecond;
1071cb0ef41Sopenharmony_ci  result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
1081cb0ef41Sopenharmony_ci  return result;
1091cb0ef41Sopenharmony_ci#else  // Monotonic clock not supported.
1101cb0ef41Sopenharmony_ci  return 0;
1111cb0ef41Sopenharmony_ci#endif
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ciV8_INLINE int64_t NanosecondsNow() {
1151cb0ef41Sopenharmony_ci  struct timespec ts;
1161cb0ef41Sopenharmony_ci  clock_gettime(CLOCK_MONOTONIC, &ts);
1171cb0ef41Sopenharmony_ci  return int64_t{ts.tv_sec} * v8::base::Time::kNanosecondsPerSecond +
1181cb0ef41Sopenharmony_ci         ts.tv_nsec;
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ciinline bool IsHighResolutionTimer(clockid_t clk_id) {
1221cb0ef41Sopenharmony_ci  // Currently this is only needed for CLOCK_MONOTONIC. If other clocks need
1231cb0ef41Sopenharmony_ci  // to be checked, care must be taken to support all platforms correctly;
1241cb0ef41Sopenharmony_ci  // see ClockNow() above for precedent.
1251cb0ef41Sopenharmony_ci  DCHECK_EQ(clk_id, CLOCK_MONOTONIC);
1261cb0ef41Sopenharmony_ci  int64_t previous = NanosecondsNow();
1271cb0ef41Sopenharmony_ci  // There should be enough attempts to make the loop run for more than one
1281cb0ef41Sopenharmony_ci  // microsecond if the early return is not taken -- the elapsed time can't
1291cb0ef41Sopenharmony_ci  // be measured in that situation, so we have to estimate it offline.
1301cb0ef41Sopenharmony_ci  constexpr int kAttempts = 100;
1311cb0ef41Sopenharmony_ci  for (int i = 0; i < kAttempts; i++) {
1321cb0ef41Sopenharmony_ci    int64_t next = NanosecondsNow();
1331cb0ef41Sopenharmony_ci    int64_t delta = next - previous;
1341cb0ef41Sopenharmony_ci    if (delta == 0) continue;
1351cb0ef41Sopenharmony_ci    // We expect most systems to take this branch on the first iteration.
1361cb0ef41Sopenharmony_ci    if (delta <= v8::base::Time::kNanosecondsPerMicrosecond) {
1371cb0ef41Sopenharmony_ci      return true;
1381cb0ef41Sopenharmony_ci    }
1391cb0ef41Sopenharmony_ci    previous = next;
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci  // As of 2022, we expect that the loop above has taken at least 2 μs (on
1421cb0ef41Sopenharmony_ci  // a fast desktop). If we still haven't seen a non-zero clock increment
1431cb0ef41Sopenharmony_ci  // in sub-microsecond range, assume a low resolution timer.
1441cb0ef41Sopenharmony_ci  return false;
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci#elif V8_OS_WIN
1481cb0ef41Sopenharmony_ci// Returns the current value of the performance counter.
1491cb0ef41Sopenharmony_ciV8_INLINE uint64_t QPCNowRaw() {
1501cb0ef41Sopenharmony_ci  LARGE_INTEGER perf_counter_now = {};
1511cb0ef41Sopenharmony_ci  // According to the MSDN documentation for QueryPerformanceCounter(), this
1521cb0ef41Sopenharmony_ci  // will never fail on systems that run XP or later.
1531cb0ef41Sopenharmony_ci  // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
1541cb0ef41Sopenharmony_ci  BOOL result = ::QueryPerformanceCounter(&perf_counter_now);
1551cb0ef41Sopenharmony_ci  DCHECK(result);
1561cb0ef41Sopenharmony_ci  USE(result);
1571cb0ef41Sopenharmony_ci  return perf_counter_now.QuadPart;
1581cb0ef41Sopenharmony_ci}
1591cb0ef41Sopenharmony_ci#endif  // V8_OS_DARWIN
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci}  // namespace
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_cinamespace v8 {
1641cb0ef41Sopenharmony_cinamespace base {
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciint TimeDelta::InDays() const {
1671cb0ef41Sopenharmony_ci  if (IsMax()) {
1681cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
1691cb0ef41Sopenharmony_ci    return std::numeric_limits<int>::max();
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci  return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ciint TimeDelta::InHours() const {
1751cb0ef41Sopenharmony_ci  if (IsMax()) {
1761cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
1771cb0ef41Sopenharmony_ci    return std::numeric_limits<int>::max();
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci  return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ciint TimeDelta::InMinutes() const {
1831cb0ef41Sopenharmony_ci  if (IsMax()) {
1841cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
1851cb0ef41Sopenharmony_ci    return std::numeric_limits<int>::max();
1861cb0ef41Sopenharmony_ci  }
1871cb0ef41Sopenharmony_ci  return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
1881cb0ef41Sopenharmony_ci}
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_cidouble TimeDelta::InSecondsF() const {
1911cb0ef41Sopenharmony_ci  if (IsMax()) {
1921cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
1931cb0ef41Sopenharmony_ci    return std::numeric_limits<double>::infinity();
1941cb0ef41Sopenharmony_ci  }
1951cb0ef41Sopenharmony_ci  return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
1961cb0ef41Sopenharmony_ci}
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ciint64_t TimeDelta::InSeconds() const {
1991cb0ef41Sopenharmony_ci  if (IsMax()) {
2001cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
2011cb0ef41Sopenharmony_ci    return std::numeric_limits<int64_t>::max();
2021cb0ef41Sopenharmony_ci  }
2031cb0ef41Sopenharmony_ci  return delta_ / Time::kMicrosecondsPerSecond;
2041cb0ef41Sopenharmony_ci}
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_cidouble TimeDelta::InMillisecondsF() const {
2071cb0ef41Sopenharmony_ci  if (IsMax()) {
2081cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
2091cb0ef41Sopenharmony_ci    return std::numeric_limits<double>::infinity();
2101cb0ef41Sopenharmony_ci  }
2111cb0ef41Sopenharmony_ci  return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ciint64_t TimeDelta::InMilliseconds() const {
2151cb0ef41Sopenharmony_ci  if (IsMax()) {
2161cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
2171cb0ef41Sopenharmony_ci    return std::numeric_limits<int64_t>::max();
2181cb0ef41Sopenharmony_ci  }
2191cb0ef41Sopenharmony_ci  return delta_ / Time::kMicrosecondsPerMillisecond;
2201cb0ef41Sopenharmony_ci}
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ciint64_t TimeDelta::InMillisecondsRoundedUp() const {
2231cb0ef41Sopenharmony_ci  if (IsMax()) {
2241cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
2251cb0ef41Sopenharmony_ci    return std::numeric_limits<int64_t>::max();
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci  return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
2281cb0ef41Sopenharmony_ci         Time::kMicrosecondsPerMillisecond;
2291cb0ef41Sopenharmony_ci}
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ciint64_t TimeDelta::InMicroseconds() const {
2321cb0ef41Sopenharmony_ci  if (IsMax()) {
2331cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
2341cb0ef41Sopenharmony_ci    return std::numeric_limits<int64_t>::max();
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci  return delta_;
2371cb0ef41Sopenharmony_ci}
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ciint64_t TimeDelta::InNanoseconds() const {
2401cb0ef41Sopenharmony_ci  if (IsMax()) {
2411cb0ef41Sopenharmony_ci    // Preserve max to prevent overflow.
2421cb0ef41Sopenharmony_ci    return std::numeric_limits<int64_t>::max();
2431cb0ef41Sopenharmony_ci  }
2441cb0ef41Sopenharmony_ci  return delta_ * Time::kNanosecondsPerMicrosecond;
2451cb0ef41Sopenharmony_ci}
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci#if V8_OS_DARWIN
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ciTimeDelta TimeDelta::FromMachTimespec(struct mach_timespec ts) {
2501cb0ef41Sopenharmony_ci  DCHECK_GE(ts.tv_nsec, 0);
2511cb0ef41Sopenharmony_ci  DCHECK_LT(ts.tv_nsec,
2521cb0ef41Sopenharmony_ci            static_cast<long>(Time::kNanosecondsPerSecond));  // NOLINT
2531cb0ef41Sopenharmony_ci  return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
2541cb0ef41Sopenharmony_ci                   ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
2551cb0ef41Sopenharmony_ci}
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_cistruct mach_timespec TimeDelta::ToMachTimespec() const {
2591cb0ef41Sopenharmony_ci  struct mach_timespec ts;
2601cb0ef41Sopenharmony_ci  DCHECK_GE(delta_, 0);
2611cb0ef41Sopenharmony_ci  ts.tv_sec = static_cast<unsigned>(delta_ / Time::kMicrosecondsPerSecond);
2621cb0ef41Sopenharmony_ci  ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
2631cb0ef41Sopenharmony_ci      Time::kNanosecondsPerMicrosecond;
2641cb0ef41Sopenharmony_ci  return ts;
2651cb0ef41Sopenharmony_ci}
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci#endif  // V8_OS_DARWIN
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci#if V8_OS_POSIX
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ciTimeDelta TimeDelta::FromTimespec(struct timespec ts) {
2721cb0ef41Sopenharmony_ci  DCHECK_GE(ts.tv_nsec, 0);
2731cb0ef41Sopenharmony_ci  DCHECK_LT(ts.tv_nsec,
2741cb0ef41Sopenharmony_ci            static_cast<long>(Time::kNanosecondsPerSecond));  // NOLINT
2751cb0ef41Sopenharmony_ci  return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
2761cb0ef41Sopenharmony_ci                   ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
2771cb0ef41Sopenharmony_ci}
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_cistruct timespec TimeDelta::ToTimespec() const {
2811cb0ef41Sopenharmony_ci  struct timespec ts;
2821cb0ef41Sopenharmony_ci  ts.tv_sec = static_cast<time_t>(delta_ / Time::kMicrosecondsPerSecond);
2831cb0ef41Sopenharmony_ci  ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
2841cb0ef41Sopenharmony_ci      Time::kNanosecondsPerMicrosecond;
2851cb0ef41Sopenharmony_ci  return ts;
2861cb0ef41Sopenharmony_ci}
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci#endif  // V8_OS_POSIX
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci#if V8_OS_WIN
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci// We implement time using the high-resolution timers so that we can get
2941cb0ef41Sopenharmony_ci// timeouts which are smaller than 10-15ms. To avoid any drift, we
2951cb0ef41Sopenharmony_ci// periodically resync the internal clock to the system clock.
2961cb0ef41Sopenharmony_ciclass Clock final {
2971cb0ef41Sopenharmony_ci public:
2981cb0ef41Sopenharmony_ci  Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {}
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  Time Now() {
3011cb0ef41Sopenharmony_ci    // Time between resampling the un-granular clock for this API (1 minute).
3021cb0ef41Sopenharmony_ci    const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1);
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci    MutexGuard lock_guard(&mutex_);
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci    // Determine current time and ticks.
3071cb0ef41Sopenharmony_ci    TimeTicks ticks = GetSystemTicks();
3081cb0ef41Sopenharmony_ci    Time time = GetSystemTime();
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci    // Check if we need to synchronize with the system clock due to a backwards
3111cb0ef41Sopenharmony_ci    // time change or the amount of time elapsed.
3121cb0ef41Sopenharmony_ci    TimeDelta elapsed = ticks - initial_ticks_;
3131cb0ef41Sopenharmony_ci    if (time < initial_time_ || elapsed > kMaxElapsedTime) {
3141cb0ef41Sopenharmony_ci      initial_ticks_ = ticks;
3151cb0ef41Sopenharmony_ci      initial_time_ = time;
3161cb0ef41Sopenharmony_ci      return time;
3171cb0ef41Sopenharmony_ci    }
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci    return initial_time_ + elapsed;
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  Time NowFromSystemTime() {
3231cb0ef41Sopenharmony_ci    MutexGuard lock_guard(&mutex_);
3241cb0ef41Sopenharmony_ci    initial_ticks_ = GetSystemTicks();
3251cb0ef41Sopenharmony_ci    initial_time_ = GetSystemTime();
3261cb0ef41Sopenharmony_ci    return initial_time_;
3271cb0ef41Sopenharmony_ci  }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci private:
3301cb0ef41Sopenharmony_ci  static TimeTicks GetSystemTicks() {
3311cb0ef41Sopenharmony_ci    return TimeTicks::Now();
3321cb0ef41Sopenharmony_ci  }
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  static Time GetSystemTime() {
3351cb0ef41Sopenharmony_ci    FILETIME ft;
3361cb0ef41Sopenharmony_ci    ::GetSystemTimeAsFileTime(&ft);
3371cb0ef41Sopenharmony_ci    return Time::FromFiletime(ft);
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  TimeTicks initial_ticks_;
3411cb0ef41Sopenharmony_ci  Time initial_time_;
3421cb0ef41Sopenharmony_ci  Mutex mutex_;
3431cb0ef41Sopenharmony_ci};
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_cinamespace {
3461cb0ef41Sopenharmony_ciDEFINE_LAZY_LEAKY_OBJECT_GETTER(Clock, GetClock)
3471cb0ef41Sopenharmony_ci}  // namespace
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ciTime Time::Now() { return GetClock()->Now(); }
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ciTime Time::NowFromSystemTime() { return GetClock()->NowFromSystemTime(); }
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci// Time between windows epoch and standard epoch.
3541cb0ef41Sopenharmony_cistatic const int64_t kTimeToEpochInMicroseconds = int64_t{11644473600000000};
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ciTime Time::FromFiletime(FILETIME ft) {
3571cb0ef41Sopenharmony_ci  if (ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0) {
3581cb0ef41Sopenharmony_ci    return Time();
3591cb0ef41Sopenharmony_ci  }
3601cb0ef41Sopenharmony_ci  if (ft.dwLowDateTime == std::numeric_limits<DWORD>::max() &&
3611cb0ef41Sopenharmony_ci      ft.dwHighDateTime == std::numeric_limits<DWORD>::max()) {
3621cb0ef41Sopenharmony_ci    return Max();
3631cb0ef41Sopenharmony_ci  }
3641cb0ef41Sopenharmony_ci  int64_t us = (static_cast<uint64_t>(ft.dwLowDateTime) +
3651cb0ef41Sopenharmony_ci                (static_cast<uint64_t>(ft.dwHighDateTime) << 32)) / 10;
3661cb0ef41Sopenharmony_ci  return Time(us - kTimeToEpochInMicroseconds);
3671cb0ef41Sopenharmony_ci}
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ciFILETIME Time::ToFiletime() const {
3711cb0ef41Sopenharmony_ci  DCHECK_GE(us_, 0);
3721cb0ef41Sopenharmony_ci  FILETIME ft;
3731cb0ef41Sopenharmony_ci  if (IsNull()) {
3741cb0ef41Sopenharmony_ci    ft.dwLowDateTime = 0;
3751cb0ef41Sopenharmony_ci    ft.dwHighDateTime = 0;
3761cb0ef41Sopenharmony_ci    return ft;
3771cb0ef41Sopenharmony_ci  }
3781cb0ef41Sopenharmony_ci  if (IsMax()) {
3791cb0ef41Sopenharmony_ci    ft.dwLowDateTime = std::numeric_limits<DWORD>::max();
3801cb0ef41Sopenharmony_ci    ft.dwHighDateTime = std::numeric_limits<DWORD>::max();
3811cb0ef41Sopenharmony_ci    return ft;
3821cb0ef41Sopenharmony_ci  }
3831cb0ef41Sopenharmony_ci  uint64_t us = static_cast<uint64_t>(us_ + kTimeToEpochInMicroseconds) * 10;
3841cb0ef41Sopenharmony_ci  ft.dwLowDateTime = static_cast<DWORD>(us);
3851cb0ef41Sopenharmony_ci  ft.dwHighDateTime = static_cast<DWORD>(us >> 32);
3861cb0ef41Sopenharmony_ci  return ft;
3871cb0ef41Sopenharmony_ci}
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci#elif V8_OS_POSIX
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ciTime Time::Now() {
3921cb0ef41Sopenharmony_ci  struct timeval tv;
3931cb0ef41Sopenharmony_ci  int result = gettimeofday(&tv, nullptr);
3941cb0ef41Sopenharmony_ci  DCHECK_EQ(0, result);
3951cb0ef41Sopenharmony_ci  USE(result);
3961cb0ef41Sopenharmony_ci  return FromTimeval(tv);
3971cb0ef41Sopenharmony_ci}
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ciTime Time::NowFromSystemTime() {
4011cb0ef41Sopenharmony_ci  return Now();
4021cb0ef41Sopenharmony_ci}
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ciTime Time::FromTimespec(struct timespec ts) {
4061cb0ef41Sopenharmony_ci  DCHECK_GE(ts.tv_nsec, 0);
4071cb0ef41Sopenharmony_ci  DCHECK_LT(ts.tv_nsec, kNanosecondsPerSecond);
4081cb0ef41Sopenharmony_ci  if (ts.tv_nsec == 0 && ts.tv_sec == 0) {
4091cb0ef41Sopenharmony_ci    return Time();
4101cb0ef41Sopenharmony_ci  }
4111cb0ef41Sopenharmony_ci  if (ts.tv_nsec == static_cast<long>(kNanosecondsPerSecond - 1) &&  // NOLINT
4121cb0ef41Sopenharmony_ci      ts.tv_sec == std::numeric_limits<time_t>::max()) {
4131cb0ef41Sopenharmony_ci    return Max();
4141cb0ef41Sopenharmony_ci  }
4151cb0ef41Sopenharmony_ci  return Time(ts.tv_sec * kMicrosecondsPerSecond +
4161cb0ef41Sopenharmony_ci              ts.tv_nsec / kNanosecondsPerMicrosecond);
4171cb0ef41Sopenharmony_ci}
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_cistruct timespec Time::ToTimespec() const {
4211cb0ef41Sopenharmony_ci  struct timespec ts;
4221cb0ef41Sopenharmony_ci  if (IsNull()) {
4231cb0ef41Sopenharmony_ci    ts.tv_sec = 0;
4241cb0ef41Sopenharmony_ci    ts.tv_nsec = 0;
4251cb0ef41Sopenharmony_ci    return ts;
4261cb0ef41Sopenharmony_ci  }
4271cb0ef41Sopenharmony_ci  if (IsMax()) {
4281cb0ef41Sopenharmony_ci    ts.tv_sec = std::numeric_limits<time_t>::max();
4291cb0ef41Sopenharmony_ci    ts.tv_nsec = static_cast<long>(kNanosecondsPerSecond - 1);  // NOLINT
4301cb0ef41Sopenharmony_ci    return ts;
4311cb0ef41Sopenharmony_ci  }
4321cb0ef41Sopenharmony_ci  ts.tv_sec = static_cast<time_t>(us_ / kMicrosecondsPerSecond);
4331cb0ef41Sopenharmony_ci  ts.tv_nsec = (us_ % kMicrosecondsPerSecond) * kNanosecondsPerMicrosecond;
4341cb0ef41Sopenharmony_ci  return ts;
4351cb0ef41Sopenharmony_ci}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ciTime Time::FromTimeval(struct timeval tv) {
4391cb0ef41Sopenharmony_ci  DCHECK_GE(tv.tv_usec, 0);
4401cb0ef41Sopenharmony_ci  DCHECK(tv.tv_usec < static_cast<suseconds_t>(kMicrosecondsPerSecond));
4411cb0ef41Sopenharmony_ci  if (tv.tv_usec == 0 && tv.tv_sec == 0) {
4421cb0ef41Sopenharmony_ci    return Time();
4431cb0ef41Sopenharmony_ci  }
4441cb0ef41Sopenharmony_ci  if (tv.tv_usec == static_cast<suseconds_t>(kMicrosecondsPerSecond - 1) &&
4451cb0ef41Sopenharmony_ci      tv.tv_sec == std::numeric_limits<time_t>::max()) {
4461cb0ef41Sopenharmony_ci    return Max();
4471cb0ef41Sopenharmony_ci  }
4481cb0ef41Sopenharmony_ci  return Time(tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec);
4491cb0ef41Sopenharmony_ci}
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_cistruct timeval Time::ToTimeval() const {
4531cb0ef41Sopenharmony_ci  struct timeval tv;
4541cb0ef41Sopenharmony_ci  if (IsNull()) {
4551cb0ef41Sopenharmony_ci    tv.tv_sec = 0;
4561cb0ef41Sopenharmony_ci    tv.tv_usec = 0;
4571cb0ef41Sopenharmony_ci    return tv;
4581cb0ef41Sopenharmony_ci  }
4591cb0ef41Sopenharmony_ci  if (IsMax()) {
4601cb0ef41Sopenharmony_ci    tv.tv_sec = std::numeric_limits<time_t>::max();
4611cb0ef41Sopenharmony_ci    tv.tv_usec = static_cast<suseconds_t>(kMicrosecondsPerSecond - 1);
4621cb0ef41Sopenharmony_ci    return tv;
4631cb0ef41Sopenharmony_ci  }
4641cb0ef41Sopenharmony_ci  tv.tv_sec = static_cast<time_t>(us_ / kMicrosecondsPerSecond);
4651cb0ef41Sopenharmony_ci  tv.tv_usec = us_ % kMicrosecondsPerSecond;
4661cb0ef41Sopenharmony_ci  return tv;
4671cb0ef41Sopenharmony_ci}
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci#elif V8_OS_STARBOARD
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ciTime Time::Now() { return Time(SbTimeToPosix(SbTimeGetNow())); }
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ciTime Time::NowFromSystemTime() { return Now(); }
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci#endif  // V8_OS_STARBOARD
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ciTime Time::FromJsTime(double ms_since_epoch) {
4781cb0ef41Sopenharmony_ci  // The epoch is a valid time, so this constructor doesn't interpret
4791cb0ef41Sopenharmony_ci  // 0 as the null time.
4801cb0ef41Sopenharmony_ci  if (ms_since_epoch == std::numeric_limits<double>::max()) {
4811cb0ef41Sopenharmony_ci    return Max();
4821cb0ef41Sopenharmony_ci  }
4831cb0ef41Sopenharmony_ci  return Time(
4841cb0ef41Sopenharmony_ci      static_cast<int64_t>(ms_since_epoch * kMicrosecondsPerMillisecond));
4851cb0ef41Sopenharmony_ci}
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_cidouble Time::ToJsTime() const {
4891cb0ef41Sopenharmony_ci  if (IsNull()) {
4901cb0ef41Sopenharmony_ci    // Preserve 0 so the invalid result doesn't depend on the platform.
4911cb0ef41Sopenharmony_ci    return 0;
4921cb0ef41Sopenharmony_ci  }
4931cb0ef41Sopenharmony_ci  if (IsMax()) {
4941cb0ef41Sopenharmony_ci    // Preserve max without offset to prevent overflow.
4951cb0ef41Sopenharmony_ci    return std::numeric_limits<double>::max();
4961cb0ef41Sopenharmony_ci  }
4971cb0ef41Sopenharmony_ci  return static_cast<double>(us_) / kMicrosecondsPerMillisecond;
4981cb0ef41Sopenharmony_ci}
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const Time& time) {
5021cb0ef41Sopenharmony_ci  return os << time.ToJsTime();
5031cb0ef41Sopenharmony_ci}
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci#if V8_OS_WIN
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_cinamespace {
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci// We define a wrapper to adapt between the __stdcall and __cdecl call of the
5111cb0ef41Sopenharmony_ci// mock function, and to avoid a static constructor.  Assigning an import to a
5121cb0ef41Sopenharmony_ci// function pointer directly would require setup code to fetch from the IAT.
5131cb0ef41Sopenharmony_ciDWORD timeGetTimeWrapper() { return timeGetTime(); }
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ciDWORD (*g_tick_function)(void) = &timeGetTimeWrapper;
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci// A structure holding the most significant bits of "last seen" and a
5181cb0ef41Sopenharmony_ci// "rollover" counter.
5191cb0ef41Sopenharmony_ciunion LastTimeAndRolloversState {
5201cb0ef41Sopenharmony_ci  // The state as a single 32-bit opaque value.
5211cb0ef41Sopenharmony_ci  int32_t as_opaque_32;
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ci  // The state as usable values.
5241cb0ef41Sopenharmony_ci  struct {
5251cb0ef41Sopenharmony_ci    // The top 8-bits of the "last" time. This is enough to check for rollovers
5261cb0ef41Sopenharmony_ci    // and the small bit-size means fewer CompareAndSwap operations to store
5271cb0ef41Sopenharmony_ci    // changes in state, which in turn makes for fewer retries.
5281cb0ef41Sopenharmony_ci    uint8_t last_8;
5291cb0ef41Sopenharmony_ci    // A count of the number of detected rollovers. Using this as bits 47-32
5301cb0ef41Sopenharmony_ci    // of the upper half of a 64-bit value results in a 48-bit tick counter.
5311cb0ef41Sopenharmony_ci    // This extends the total rollover period from about 49 days to about 8800
5321cb0ef41Sopenharmony_ci    // years while still allowing it to be stored with last_8 in a single
5331cb0ef41Sopenharmony_ci    // 32-bit value.
5341cb0ef41Sopenharmony_ci    uint16_t rollovers;
5351cb0ef41Sopenharmony_ci  } as_values;
5361cb0ef41Sopenharmony_ci};
5371cb0ef41Sopenharmony_cistd::atomic<int32_t> g_last_time_and_rollovers{0};
5381cb0ef41Sopenharmony_cistatic_assert(sizeof(LastTimeAndRolloversState) <=
5391cb0ef41Sopenharmony_ci                  sizeof(g_last_time_and_rollovers),
5401cb0ef41Sopenharmony_ci              "LastTimeAndRolloversState does not fit in a single atomic word");
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci// We use timeGetTime() to implement TimeTicks::Now().  This can be problematic
5431cb0ef41Sopenharmony_ci// because it returns the number of milliseconds since Windows has started,
5441cb0ef41Sopenharmony_ci// which will roll over the 32-bit value every ~49 days.  We try to track
5451cb0ef41Sopenharmony_ci// rollover ourselves, which works if TimeTicks::Now() is called at least every
5461cb0ef41Sopenharmony_ci// 48.8 days (not 49 days because only changes in the top 8 bits get noticed).
5471cb0ef41Sopenharmony_ciTimeTicks RolloverProtectedNow() {
5481cb0ef41Sopenharmony_ci  LastTimeAndRolloversState state;
5491cb0ef41Sopenharmony_ci  DWORD now;  // DWORD is always unsigned 32 bits.
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ci  // Fetch the "now" and "last" tick values, updating "last" with "now" and
5521cb0ef41Sopenharmony_ci  // incrementing the "rollovers" counter if the tick-value has wrapped back
5531cb0ef41Sopenharmony_ci  // around. Atomic operations ensure that both "last" and "rollovers" are
5541cb0ef41Sopenharmony_ci  // always updated together.
5551cb0ef41Sopenharmony_ci  int32_t original = g_last_time_and_rollovers.load(std::memory_order_acquire);
5561cb0ef41Sopenharmony_ci  while (true) {
5571cb0ef41Sopenharmony_ci    state.as_opaque_32 = original;
5581cb0ef41Sopenharmony_ci    now = g_tick_function();
5591cb0ef41Sopenharmony_ci    uint8_t now_8 = static_cast<uint8_t>(now >> 24);
5601cb0ef41Sopenharmony_ci    if (now_8 < state.as_values.last_8) ++state.as_values.rollovers;
5611cb0ef41Sopenharmony_ci    state.as_values.last_8 = now_8;
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci    // If the state hasn't changed, exit the loop.
5641cb0ef41Sopenharmony_ci    if (state.as_opaque_32 == original) break;
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci    // Save the changed state. If the existing value is unchanged from the
5671cb0ef41Sopenharmony_ci    // original, exit the loop.
5681cb0ef41Sopenharmony_ci    if (g_last_time_and_rollovers.compare_exchange_weak(
5691cb0ef41Sopenharmony_ci            original, state.as_opaque_32, std::memory_order_acq_rel)) {
5701cb0ef41Sopenharmony_ci      break;
5711cb0ef41Sopenharmony_ci    }
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ci    // Another thread has done something in between so retry from the top.
5741cb0ef41Sopenharmony_ci    // {original} has been updated by the {compare_exchange_weak}.
5751cb0ef41Sopenharmony_ci  }
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci  return TimeTicks() +
5781cb0ef41Sopenharmony_ci         TimeDelta::FromMilliseconds(
5791cb0ef41Sopenharmony_ci             now + (static_cast<uint64_t>(state.as_values.rollovers) << 32));
5801cb0ef41Sopenharmony_ci}
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci// Discussion of tick counter options on Windows:
5831cb0ef41Sopenharmony_ci//
5841cb0ef41Sopenharmony_ci// (1) CPU cycle counter. (Retrieved via RDTSC)
5851cb0ef41Sopenharmony_ci// The CPU counter provides the highest resolution time stamp and is the least
5861cb0ef41Sopenharmony_ci// expensive to retrieve. However, on older CPUs, two issues can affect its
5871cb0ef41Sopenharmony_ci// reliability: First it is maintained per processor and not synchronized
5881cb0ef41Sopenharmony_ci// between processors. Also, the counters will change frequency due to thermal
5891cb0ef41Sopenharmony_ci// and power changes, and stop in some states.
5901cb0ef41Sopenharmony_ci//
5911cb0ef41Sopenharmony_ci// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
5921cb0ef41Sopenharmony_ci// resolution (<1 microsecond) time stamp. On most hardware running today, it
5931cb0ef41Sopenharmony_ci// auto-detects and uses the constant-rate RDTSC counter to provide extremely
5941cb0ef41Sopenharmony_ci// efficient and reliable time stamps.
5951cb0ef41Sopenharmony_ci//
5961cb0ef41Sopenharmony_ci// On older CPUs where RDTSC is unreliable, it falls back to using more
5971cb0ef41Sopenharmony_ci// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI
5981cb0ef41Sopenharmony_ci// PM timer, and can involve system calls; and all this is up to the HAL (with
5991cb0ef41Sopenharmony_ci// some help from ACPI). According to
6001cb0ef41Sopenharmony_ci// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the
6011cb0ef41Sopenharmony_ci// worst case, it gets the counter from the rollover interrupt on the
6021cb0ef41Sopenharmony_ci// programmable interrupt timer. In best cases, the HAL may conclude that the
6031cb0ef41Sopenharmony_ci// RDTSC counter runs at a constant frequency, then it uses that instead. On
6041cb0ef41Sopenharmony_ci// multiprocessor machines, it will try to verify the values returned from
6051cb0ef41Sopenharmony_ci// RDTSC on each processor are consistent with each other, and apply a handful
6061cb0ef41Sopenharmony_ci// of workarounds for known buggy hardware. In other words, QPC is supposed to
6071cb0ef41Sopenharmony_ci// give consistent results on a multiprocessor computer, but for older CPUs it
6081cb0ef41Sopenharmony_ci// can be unreliable due bugs in BIOS or HAL.
6091cb0ef41Sopenharmony_ci//
6101cb0ef41Sopenharmony_ci// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6
6111cb0ef41Sopenharmony_ci// milliseconds) time stamp but is comparatively less expensive to retrieve and
6121cb0ef41Sopenharmony_ci// more reliable. Time::EnableHighResolutionTimer() and
6131cb0ef41Sopenharmony_ci// Time::ActivateHighResolutionTimer() can be called to alter the resolution of
6141cb0ef41Sopenharmony_ci// this timer; and also other Windows applications can alter it, affecting this
6151cb0ef41Sopenharmony_ci// one.
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ciTimeTicks InitialTimeTicksNowFunction();
6181cb0ef41Sopenharmony_ci
6191cb0ef41Sopenharmony_ci// See "threading notes" in InitializeNowFunctionPointer() for details on how
6201cb0ef41Sopenharmony_ci// concurrent reads/writes to these globals has been made safe.
6211cb0ef41Sopenharmony_ciusing TimeTicksNowFunction = decltype(&TimeTicks::Now);
6221cb0ef41Sopenharmony_ciTimeTicksNowFunction g_time_ticks_now_function = &InitialTimeTicksNowFunction;
6231cb0ef41Sopenharmony_ciint64_t g_qpc_ticks_per_second = 0;
6241cb0ef41Sopenharmony_ci
6251cb0ef41Sopenharmony_ciTimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) {
6261cb0ef41Sopenharmony_ci  // Ensure that the assignment to |g_qpc_ticks_per_second|, made in
6271cb0ef41Sopenharmony_ci  // InitializeNowFunctionPointer(), has happened by this point.
6281cb0ef41Sopenharmony_ci  std::atomic_thread_fence(std::memory_order_acquire);
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  DCHECK_GT(g_qpc_ticks_per_second, 0);
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci  // If the QPC Value is below the overflow threshold, we proceed with
6331cb0ef41Sopenharmony_ci  // simple multiply and divide.
6341cb0ef41Sopenharmony_ci  if (qpc_value < TimeTicks::kQPCOverflowThreshold) {
6351cb0ef41Sopenharmony_ci    return TimeDelta::FromMicroseconds(
6361cb0ef41Sopenharmony_ci        qpc_value * TimeTicks::kMicrosecondsPerSecond / g_qpc_ticks_per_second);
6371cb0ef41Sopenharmony_ci  }
6381cb0ef41Sopenharmony_ci  // Otherwise, calculate microseconds in a round about manner to avoid
6391cb0ef41Sopenharmony_ci  // overflow and precision issues.
6401cb0ef41Sopenharmony_ci  int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second;
6411cb0ef41Sopenharmony_ci  int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second);
6421cb0ef41Sopenharmony_ci  return TimeDelta::FromMicroseconds(
6431cb0ef41Sopenharmony_ci      (whole_seconds * TimeTicks::kMicrosecondsPerSecond) +
6441cb0ef41Sopenharmony_ci      ((leftover_ticks * TimeTicks::kMicrosecondsPerSecond) /
6451cb0ef41Sopenharmony_ci       g_qpc_ticks_per_second));
6461cb0ef41Sopenharmony_ci}
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ciTimeTicks QPCNow() { return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw()); }
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_civoid InitializeTimeTicksNowFunctionPointer() {
6511cb0ef41Sopenharmony_ci  LARGE_INTEGER ticks_per_sec = {};
6521cb0ef41Sopenharmony_ci  if (!QueryPerformanceFrequency(&ticks_per_sec)) ticks_per_sec.QuadPart = 0;
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ci  // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use
6551cb0ef41Sopenharmony_ci  // the low-resolution clock.
6561cb0ef41Sopenharmony_ci  //
6571cb0ef41Sopenharmony_ci  // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
6581cb0ef41Sopenharmony_ci  // will still use the low-resolution clock. A CPU lacking a non-stop time
6591cb0ef41Sopenharmony_ci  // counter will cause Windows to provide an alternate QPC implementation that
6601cb0ef41Sopenharmony_ci  // works, but is expensive to use. Certain Athlon CPUs are known to make the
6611cb0ef41Sopenharmony_ci  // QPC implementation unreliable.
6621cb0ef41Sopenharmony_ci  //
6631cb0ef41Sopenharmony_ci  // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
6641cb0ef41Sopenharmony_ci  // ~72% of users fall within this category.
6651cb0ef41Sopenharmony_ci  TimeTicksNowFunction now_function;
6661cb0ef41Sopenharmony_ci  CPU cpu;
6671cb0ef41Sopenharmony_ci  if (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter()) {
6681cb0ef41Sopenharmony_ci    now_function = &RolloverProtectedNow;
6691cb0ef41Sopenharmony_ci  } else {
6701cb0ef41Sopenharmony_ci    now_function = &QPCNow;
6711cb0ef41Sopenharmony_ci  }
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_ci  // Threading note 1: In an unlikely race condition, it's possible for two or
6741cb0ef41Sopenharmony_ci  // more threads to enter InitializeNowFunctionPointer() in parallel. This is
6751cb0ef41Sopenharmony_ci  // not a problem since all threads should end up writing out the same values
6761cb0ef41Sopenharmony_ci  // to the global variables.
6771cb0ef41Sopenharmony_ci  //
6781cb0ef41Sopenharmony_ci  // Threading note 2: A release fence is placed here to ensure, from the
6791cb0ef41Sopenharmony_ci  // perspective of other threads using the function pointers, that the
6801cb0ef41Sopenharmony_ci  // assignment to |g_qpc_ticks_per_second| happens before the function pointers
6811cb0ef41Sopenharmony_ci  // are changed.
6821cb0ef41Sopenharmony_ci  g_qpc_ticks_per_second = ticks_per_sec.QuadPart;
6831cb0ef41Sopenharmony_ci  std::atomic_thread_fence(std::memory_order_release);
6841cb0ef41Sopenharmony_ci  g_time_ticks_now_function = now_function;
6851cb0ef41Sopenharmony_ci}
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ciTimeTicks InitialTimeTicksNowFunction() {
6881cb0ef41Sopenharmony_ci  InitializeTimeTicksNowFunctionPointer();
6891cb0ef41Sopenharmony_ci  return g_time_ticks_now_function();
6901cb0ef41Sopenharmony_ci}
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci}  // namespace
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ci// static
6951cb0ef41Sopenharmony_ciTimeTicks TimeTicks::Now() {
6961cb0ef41Sopenharmony_ci  // Make sure we never return 0 here.
6971cb0ef41Sopenharmony_ci  TimeTicks ticks(g_time_ticks_now_function());
6981cb0ef41Sopenharmony_ci  DCHECK(!ticks.IsNull());
6991cb0ef41Sopenharmony_ci  return ticks;
7001cb0ef41Sopenharmony_ci}
7011cb0ef41Sopenharmony_ci
7021cb0ef41Sopenharmony_ci// static
7031cb0ef41Sopenharmony_cibool TimeTicks::IsHighResolution() {
7041cb0ef41Sopenharmony_ci  if (g_time_ticks_now_function == &InitialTimeTicksNowFunction)
7051cb0ef41Sopenharmony_ci    InitializeTimeTicksNowFunctionPointer();
7061cb0ef41Sopenharmony_ci  return g_time_ticks_now_function == &QPCNow;
7071cb0ef41Sopenharmony_ci}
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci#else  // V8_OS_WIN
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ciTimeTicks TimeTicks::Now() {
7121cb0ef41Sopenharmony_ci  int64_t ticks;
7131cb0ef41Sopenharmony_ci#if V8_OS_DARWIN
7141cb0ef41Sopenharmony_ci  static struct mach_timebase_info info;
7151cb0ef41Sopenharmony_ci  if (info.denom == 0) {
7161cb0ef41Sopenharmony_ci    kern_return_t result = mach_timebase_info(&info);
7171cb0ef41Sopenharmony_ci    DCHECK_EQ(KERN_SUCCESS, result);
7181cb0ef41Sopenharmony_ci    USE(result);
7191cb0ef41Sopenharmony_ci  }
7201cb0ef41Sopenharmony_ci  ticks = (mach_absolute_time() / Time::kNanosecondsPerMicrosecond *
7211cb0ef41Sopenharmony_ci           info.numer / info.denom);
7221cb0ef41Sopenharmony_ci#elif V8_OS_SOLARIS
7231cb0ef41Sopenharmony_ci  ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
7241cb0ef41Sopenharmony_ci#elif V8_OS_POSIX
7251cb0ef41Sopenharmony_ci  ticks = ClockNow(CLOCK_MONOTONIC);
7261cb0ef41Sopenharmony_ci#elif V8_OS_STARBOARD
7271cb0ef41Sopenharmony_ci  ticks = SbTimeGetMonotonicNow();
7281cb0ef41Sopenharmony_ci#else
7291cb0ef41Sopenharmony_ci#error platform does not implement TimeTicks::Now.
7301cb0ef41Sopenharmony_ci#endif  // V8_OS_DARWIN
7311cb0ef41Sopenharmony_ci  // Make sure we never return 0 here.
7321cb0ef41Sopenharmony_ci  return TimeTicks(ticks + 1);
7331cb0ef41Sopenharmony_ci}
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci// static
7361cb0ef41Sopenharmony_cibool TimeTicks::IsHighResolution() {
7371cb0ef41Sopenharmony_ci#if V8_OS_DARWIN
7381cb0ef41Sopenharmony_ci  return true;
7391cb0ef41Sopenharmony_ci#elif V8_OS_POSIX
7401cb0ef41Sopenharmony_ci  static const bool is_high_resolution = IsHighResolutionTimer(CLOCK_MONOTONIC);
7411cb0ef41Sopenharmony_ci  return is_high_resolution;
7421cb0ef41Sopenharmony_ci#else
7431cb0ef41Sopenharmony_ci  return true;
7441cb0ef41Sopenharmony_ci#endif
7451cb0ef41Sopenharmony_ci}
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci#endif  // V8_OS_WIN
7481cb0ef41Sopenharmony_ci
7491cb0ef41Sopenharmony_ci
7501cb0ef41Sopenharmony_cibool ThreadTicks::IsSupported() {
7511cb0ef41Sopenharmony_ci#if V8_OS_STARBOARD
7521cb0ef41Sopenharmony_ci#if SB_API_VERSION >= 12
7531cb0ef41Sopenharmony_ci  return SbTimeIsTimeThreadNowSupported();
7541cb0ef41Sopenharmony_ci#elif SB_HAS(TIME_THREAD_NOW)
7551cb0ef41Sopenharmony_ci  return true;
7561cb0ef41Sopenharmony_ci#else
7571cb0ef41Sopenharmony_ci  return false;
7581cb0ef41Sopenharmony_ci#endif
7591cb0ef41Sopenharmony_ci#elif defined(__PASE__)
7601cb0ef41Sopenharmony_ci  // Thread CPU time accounting is unavailable in PASE
7611cb0ef41Sopenharmony_ci  return false;
7621cb0ef41Sopenharmony_ci#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
7631cb0ef41Sopenharmony_ci    defined(V8_OS_DARWIN) || defined(V8_OS_ANDROID) || defined(V8_OS_SOLARIS)
7641cb0ef41Sopenharmony_ci  return true;
7651cb0ef41Sopenharmony_ci#elif defined(V8_OS_WIN)
7661cb0ef41Sopenharmony_ci  return IsSupportedWin();
7671cb0ef41Sopenharmony_ci#else
7681cb0ef41Sopenharmony_ci  return false;
7691cb0ef41Sopenharmony_ci#endif
7701cb0ef41Sopenharmony_ci}
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci
7731cb0ef41Sopenharmony_ciThreadTicks ThreadTicks::Now() {
7741cb0ef41Sopenharmony_ci#if V8_OS_STARBOARD
7751cb0ef41Sopenharmony_ci#if SB_API_VERSION >= 12
7761cb0ef41Sopenharmony_ci  if (SbTimeIsTimeThreadNowSupported())
7771cb0ef41Sopenharmony_ci    return ThreadTicks(SbTimeGetMonotonicThreadNow());
7781cb0ef41Sopenharmony_ci  UNREACHABLE();
7791cb0ef41Sopenharmony_ci#elif SB_HAS(TIME_THREAD_NOW)
7801cb0ef41Sopenharmony_ci  return ThreadTicks(SbTimeGetMonotonicThreadNow());
7811cb0ef41Sopenharmony_ci#else
7821cb0ef41Sopenharmony_ci  UNREACHABLE();
7831cb0ef41Sopenharmony_ci#endif
7841cb0ef41Sopenharmony_ci#elif V8_OS_DARWIN
7851cb0ef41Sopenharmony_ci  return ThreadTicks(ComputeThreadTicks());
7861cb0ef41Sopenharmony_ci#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
7871cb0ef41Sopenharmony_ci  defined(V8_OS_ANDROID)
7881cb0ef41Sopenharmony_ci  return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
7891cb0ef41Sopenharmony_ci#elif V8_OS_SOLARIS
7901cb0ef41Sopenharmony_ci  return ThreadTicks(gethrvtime() / Time::kNanosecondsPerMicrosecond);
7911cb0ef41Sopenharmony_ci#elif V8_OS_WIN
7921cb0ef41Sopenharmony_ci  return ThreadTicks::GetForThread(::GetCurrentThread());
7931cb0ef41Sopenharmony_ci#else
7941cb0ef41Sopenharmony_ci  UNREACHABLE();
7951cb0ef41Sopenharmony_ci#endif
7961cb0ef41Sopenharmony_ci}
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_ci#if V8_OS_WIN
8001cb0ef41Sopenharmony_ciThreadTicks ThreadTicks::GetForThread(const HANDLE& thread_handle) {
8011cb0ef41Sopenharmony_ci  DCHECK(IsSupported());
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci  // Get the number of TSC ticks used by the current thread.
8041cb0ef41Sopenharmony_ci  ULONG64 thread_cycle_time = 0;
8051cb0ef41Sopenharmony_ci  ::QueryThreadCycleTime(thread_handle, &thread_cycle_time);
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_ci  // Get the frequency of the TSC.
8081cb0ef41Sopenharmony_ci  double tsc_ticks_per_second = TSCTicksPerSecond();
8091cb0ef41Sopenharmony_ci  if (tsc_ticks_per_second == 0)
8101cb0ef41Sopenharmony_ci    return ThreadTicks();
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ci  // Return the CPU time of the current thread.
8131cb0ef41Sopenharmony_ci  double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
8141cb0ef41Sopenharmony_ci  return ThreadTicks(
8151cb0ef41Sopenharmony_ci      static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond));
8161cb0ef41Sopenharmony_ci}
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci// static
8191cb0ef41Sopenharmony_cibool ThreadTicks::IsSupportedWin() {
8201cb0ef41Sopenharmony_ci  static bool is_supported = base::CPU().has_non_stop_time_stamp_counter();
8211cb0ef41Sopenharmony_ci  return is_supported;
8221cb0ef41Sopenharmony_ci}
8231cb0ef41Sopenharmony_ci
8241cb0ef41Sopenharmony_ci// static
8251cb0ef41Sopenharmony_civoid ThreadTicks::WaitUntilInitializedWin() {
8261cb0ef41Sopenharmony_ci  while (TSCTicksPerSecond() == 0)
8271cb0ef41Sopenharmony_ci    ::Sleep(10);
8281cb0ef41Sopenharmony_ci}
8291cb0ef41Sopenharmony_ci
8301cb0ef41Sopenharmony_ci#ifdef V8_HOST_ARCH_ARM64
8311cb0ef41Sopenharmony_ci#define ReadCycleCounter() _ReadStatusReg(ARM64_PMCCNTR_EL0)
8321cb0ef41Sopenharmony_ci#else
8331cb0ef41Sopenharmony_ci#define ReadCycleCounter() __rdtsc()
8341cb0ef41Sopenharmony_ci#endif
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_cidouble ThreadTicks::TSCTicksPerSecond() {
8371cb0ef41Sopenharmony_ci  DCHECK(IsSupported());
8381cb0ef41Sopenharmony_ci
8391cb0ef41Sopenharmony_ci  // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
8401cb0ef41Sopenharmony_ci  // frequency, because there is no guarantee that the TSC frequency is equal to
8411cb0ef41Sopenharmony_ci  // the performance counter frequency.
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ci  // The TSC frequency is cached in a static variable because it takes some time
8441cb0ef41Sopenharmony_ci  // to compute it.
8451cb0ef41Sopenharmony_ci  static double tsc_ticks_per_second = 0;
8461cb0ef41Sopenharmony_ci  if (tsc_ticks_per_second != 0)
8471cb0ef41Sopenharmony_ci    return tsc_ticks_per_second;
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_ci  // Increase the thread priority to reduces the chances of having a context
8501cb0ef41Sopenharmony_ci  // switch during a reading of the TSC and the performance counter.
8511cb0ef41Sopenharmony_ci  int previous_priority = ::GetThreadPriority(::GetCurrentThread());
8521cb0ef41Sopenharmony_ci  ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_ci  // The first time that this function is called, make an initial reading of the
8551cb0ef41Sopenharmony_ci  // TSC and the performance counter.
8561cb0ef41Sopenharmony_ci  static const uint64_t tsc_initial = ReadCycleCounter();
8571cb0ef41Sopenharmony_ci  static const uint64_t perf_counter_initial = QPCNowRaw();
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci  // Make a another reading of the TSC and the performance counter every time
8601cb0ef41Sopenharmony_ci  // that this function is called.
8611cb0ef41Sopenharmony_ci  uint64_t tsc_now = ReadCycleCounter();
8621cb0ef41Sopenharmony_ci  uint64_t perf_counter_now = QPCNowRaw();
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci  // Reset the thread priority.
8651cb0ef41Sopenharmony_ci  ::SetThreadPriority(::GetCurrentThread(), previous_priority);
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_ci  // Make sure that at least 50 ms elapsed between the 2 readings. The first
8681cb0ef41Sopenharmony_ci  // time that this function is called, we don't expect this to be the case.
8691cb0ef41Sopenharmony_ci  // Note: The longer the elapsed time between the 2 readings is, the more
8701cb0ef41Sopenharmony_ci  //   accurate the computed TSC frequency will be. The 50 ms value was
8711cb0ef41Sopenharmony_ci  //   chosen because local benchmarks show that it allows us to get a
8721cb0ef41Sopenharmony_ci  //   stddev of less than 1 tick/us between multiple runs.
8731cb0ef41Sopenharmony_ci  // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
8741cb0ef41Sopenharmony_ci  //   this will never fail on systems that run XP or later.
8751cb0ef41Sopenharmony_ci  //   https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
8761cb0ef41Sopenharmony_ci  LARGE_INTEGER perf_counter_frequency = {};
8771cb0ef41Sopenharmony_ci  ::QueryPerformanceFrequency(&perf_counter_frequency);
8781cb0ef41Sopenharmony_ci  DCHECK_GE(perf_counter_now, perf_counter_initial);
8791cb0ef41Sopenharmony_ci  uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
8801cb0ef41Sopenharmony_ci  double elapsed_time_seconds =
8811cb0ef41Sopenharmony_ci      perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
8821cb0ef41Sopenharmony_ci
8831cb0ef41Sopenharmony_ci  const double kMinimumEvaluationPeriodSeconds = 0.05;
8841cb0ef41Sopenharmony_ci  if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
8851cb0ef41Sopenharmony_ci    return 0;
8861cb0ef41Sopenharmony_ci
8871cb0ef41Sopenharmony_ci  // Compute the frequency of the TSC.
8881cb0ef41Sopenharmony_ci  DCHECK_GE(tsc_now, tsc_initial);
8891cb0ef41Sopenharmony_ci  uint64_t tsc_ticks = tsc_now - tsc_initial;
8901cb0ef41Sopenharmony_ci  tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
8911cb0ef41Sopenharmony_ci
8921cb0ef41Sopenharmony_ci  return tsc_ticks_per_second;
8931cb0ef41Sopenharmony_ci}
8941cb0ef41Sopenharmony_ci#undef ReadCycleCounter
8951cb0ef41Sopenharmony_ci#endif  // V8_OS_WIN
8961cb0ef41Sopenharmony_ci
8971cb0ef41Sopenharmony_ci}  // namespace base
8981cb0ef41Sopenharmony_ci}  // namespace v8
899