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