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 namespace { 30 ConvertTimespecToMicros(const struct timespec & ts)31int64_t ConvertTimespecToMicros(const struct timespec& ts) { 32 // On 32-bit systems, the calculation cannot overflow int64_t. 33 // 2**32 * 1000000 + 2**64 / 1000 < 2**63 34 if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) { 35 int64_t result = ts.tv_sec; 36 result *= base::Time::kMicrosecondsPerSecond; 37 result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); 38 return result; 39 } 40 base::CheckedNumeric<int64_t> result(ts.tv_sec); 41 result *= base::Time::kMicrosecondsPerSecond; 42 result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); 43 return result.ValueOrDie(); 44 } 45 46 // Helper function to get results from clock_gettime() and convert to a 47 // microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported 48 // on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines 49 // _POSIX_MONOTONIC_CLOCK to -1. 50 #if (BUILDFLAG(IS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \ 51 _POSIX_MONOTONIC_CLOCK >= 0) || \ 52 BUILDFLAG(IS_BSD) || BUILDFLAG(IS_ANDROID) ClockNow(clockid_t clk_id)53int64_t ClockNow(clockid_t clk_id) { 54 struct timespec ts; 55 CHECK(clock_gettime(clk_id, &ts) == 0); 56 return ConvertTimespecToMicros(ts); 57 } 58 MaybeClockNow(clockid_t clk_id)59std::optional<int64_t> MaybeClockNow(clockid_t clk_id) { 60 struct timespec ts; 61 int res = clock_gettime(clk_id, &ts); 62 if (res == 0) 63 return ConvertTimespecToMicros(ts); 64 return std::nullopt; 65 } 66 67 #else // _POSIX_MONOTONIC_CLOCK 68 #error No usable tick clock function on this platform. 69 #endif // _POSIX_MONOTONIC_CLOCK 70 71 } // namespace 72 73 namespace base { 74 75 // Time ----------------------------------------------------------------------- 76 77 namespace subtle { TimeNowIgnoringOverride()78Time TimeNowIgnoringOverride() { 79 struct timeval tv; 80 struct timezone tz = {0, 0}; // UTC 81 CHECK(gettimeofday(&tv, &tz) == 0); 82 // Combine seconds and microseconds in a 64-bit field containing microseconds 83 // since the epoch. That's enough for nearly 600 centuries. Adjust from 84 // Unix (1970) to Windows (1601) epoch. 85 return Time() + 86 Microseconds((tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) + 87 Time::kTimeTToMicrosecondsOffset); 88 } 89 TimeNowFromSystemTimeIgnoringOverride()90Time TimeNowFromSystemTimeIgnoringOverride() { 91 // Just use TimeNowIgnoringOverride() because it returns the system time. 92 return TimeNowIgnoringOverride(); 93 } 94 } // namespace subtle 95 96 // TimeTicks ------------------------------------------------------------------ 97 98 namespace subtle { TimeTicksNowIgnoringOverride()99TimeTicks TimeTicksNowIgnoringOverride() { 100 return TimeTicks() + Microseconds(ClockNow(CLOCK_MONOTONIC)); 101 } 102 MaybeTimeTicksNowIgnoringOverride()103std::optional<TimeTicks> MaybeTimeTicksNowIgnoringOverride() { 104 std::optional<int64_t> now = MaybeClockNow(CLOCK_MONOTONIC); 105 if (now.has_value()) 106 return TimeTicks() + Microseconds(now.value()); 107 return std::nullopt; 108 } 109 } // namespace subtle 110 111 // static GetClock()112TimeTicks::Clock TimeTicks::GetClock() { 113 return Clock::LINUX_CLOCK_MONOTONIC; 114 } 115 116 // static IsHighResolution()117bool TimeTicks::IsHighResolution() { 118 return true; 119 } 120 121 // static IsConsistentAcrossProcesses()122bool TimeTicks::IsConsistentAcrossProcesses() { 123 return true; 124 } 125 126 // ThreadTicks ---------------------------------------------------------------- 127 128 namespace subtle { ThreadTicksNowIgnoringOverride()129ThreadTicks ThreadTicksNowIgnoringOverride() { 130 #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ 131 BUILDFLAG(IS_ANDROID) 132 return ThreadTicks() + Microseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID)); 133 #else 134 NOTREACHED(); 135 return ThreadTicks(); 136 #endif 137 } 138 } // namespace subtle 139 140 } // namespace base 141