1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdint.h> 6 #include <sys/time.h> 7 #include <time.h> 8 #include <unistd.h> 9 10 #include <optional> 11 12 #include "base/check.h" 13 #include "base/notreached.h" 14 #include "base/numerics/safe_math.h" 15 #include "base/time/time.h" 16 #include "base/time/time_override.h" 17 #include "build/build_config.h" 18 19 #if BUILDFLAG(IS_ANDROID) && !defined(__LP64__) 20 #include <time64.h> 21 #endif 22 23 // Ensure the Fuchsia and Mac builds do not include this module. Instead, 24 // non-POSIX implementation is used for sampling the system clocks. 25 #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_APPLE) 26 #error "This implementation is for POSIX platforms other than Fuchsia or Mac." 27 #endif 28 29 // NaCl doesn't support CLOCK_MONOTONIC_COARSE. 30 #if BUILDFLAG(IS_NACL) 31 #define TIMETICKS_LOW_RESOLUTION_CLOCK CLOCK_MONOTONIC 32 #else 33 #define TIMETICKS_LOW_RESOLUTION_CLOCK CLOCK_MONOTONIC_COARSE 34 #endif 35 36 namespace { 37 ConvertTimespecToMicros(const struct timespec & ts)38int64_t ConvertTimespecToMicros(const struct timespec& ts) { 39 // On 32-bit systems, the calculation cannot overflow int64_t. 40 // 2**32 * 1000000 + 2**64 / 1000 < 2**63 41 if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) { 42 int64_t result = ts.tv_sec; 43 result *= base::Time::kMicrosecondsPerSecond; 44 result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); 45 return result; 46 } 47 base::CheckedNumeric<int64_t> result(ts.tv_sec); 48 result *= base::Time::kMicrosecondsPerSecond; 49 result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); 50 return result.ValueOrDie(); 51 } 52 53 // Helper function to get results from clock_gettime() and convert to a 54 // microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported 55 // on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines 56 // _POSIX_MONOTONIC_CLOCK to -1. 57 #if (BUILDFLAG(IS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \ 58 _POSIX_MONOTONIC_CLOCK >= 0) || \ 59 BUILDFLAG(IS_BSD) || BUILDFLAG(IS_ANDROID) ClockNow(clockid_t clk_id)60int64_t ClockNow(clockid_t clk_id) { 61 struct timespec ts; 62 CHECK(clock_gettime(clk_id, &ts) == 0); 63 return ConvertTimespecToMicros(ts); 64 } 65 MaybeClockNow(clockid_t clk_id)66std::optional<int64_t> MaybeClockNow(clockid_t clk_id) { 67 struct timespec ts; 68 int res = clock_gettime(clk_id, &ts); 69 if (res == 0) 70 return ConvertTimespecToMicros(ts); 71 return std::nullopt; 72 } 73 74 #else // _POSIX_MONOTONIC_CLOCK 75 #error No usable tick clock function on this platform. 76 #endif // _POSIX_MONOTONIC_CLOCK 77 78 } // namespace 79 80 namespace base { 81 82 // Time ----------------------------------------------------------------------- 83 84 namespace subtle { TimeNowIgnoringOverride()85Time TimeNowIgnoringOverride() { 86 struct timeval tv; 87 struct timezone tz = {0, 0}; // UTC 88 CHECK(gettimeofday(&tv, &tz) == 0); 89 // Combine seconds and microseconds in a 64-bit field containing microseconds 90 // since the epoch. That's enough for nearly 600 centuries. Adjust from 91 // Unix (1970) to Windows (1601) epoch. 92 return Time() + 93 Microseconds((tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) + 94 Time::kTimeTToMicrosecondsOffset); 95 } 96 TimeNowFromSystemTimeIgnoringOverride()97Time TimeNowFromSystemTimeIgnoringOverride() { 98 // Just use TimeNowIgnoringOverride() because it returns the system time. 99 return TimeNowIgnoringOverride(); 100 } 101 } // namespace subtle 102 103 // TimeTicks ------------------------------------------------------------------ 104 105 namespace subtle { TimeTicksNowIgnoringOverride()106TimeTicks TimeTicksNowIgnoringOverride() { 107 return TimeTicks() + Microseconds(ClockNow(CLOCK_MONOTONIC)); 108 } 109 MaybeTimeTicksNowIgnoringOverride()110std::optional<TimeTicks> MaybeTimeTicksNowIgnoringOverride() { 111 std::optional<int64_t> now = MaybeClockNow(CLOCK_MONOTONIC); 112 if (now.has_value()) 113 return TimeTicks() + Microseconds(now.value()); 114 return std::nullopt; 115 } 116 TimeTicksLowResolutionNowIgnoringOverride()117TimeTicks TimeTicksLowResolutionNowIgnoringOverride() { 118 return TimeTicks() + Microseconds(ClockNow(TIMETICKS_LOW_RESOLUTION_CLOCK)); 119 } 120 } // namespace subtle 121 122 // static GetClock()123TimeTicks::Clock TimeTicks::GetClock() { 124 return Clock::LINUX_CLOCK_MONOTONIC; 125 } 126 127 // static IsHighResolution()128bool TimeTicks::IsHighResolution() { 129 return true; 130 } 131 132 // static IsConsistentAcrossProcesses()133bool TimeTicks::IsConsistentAcrossProcesses() { 134 return true; 135 } 136 137 // ThreadTicks ---------------------------------------------------------------- 138 139 namespace subtle { ThreadTicksNowIgnoringOverride()140ThreadTicks ThreadTicksNowIgnoringOverride() { 141 #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ 142 BUILDFLAG(IS_ANDROID) 143 return ThreadTicks() + Microseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID)); 144 #else 145 NOTREACHED(); 146 #endif 147 } 148 } // namespace subtle 149 150 } // namespace base 151