1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 "base/time/time.h" 6 7 #include <stdint.h> 8 #include <sys/time.h> 9 #include <time.h> 10 #if defined(OS_ANDROID) && !defined(__LP64__) 11 #include <time64.h> 12 #endif 13 #include <unistd.h> 14 15 #include "base/logging.h" 16 #include "base/numerics/safe_math.h" 17 #include "base/time/time_override.h" 18 #include "build/build_config.h" 19 20 // Ensure the Fuchsia and Mac builds do not include this module. Instead, 21 // non-POSIX implementation is used for sampling the system clocks. 22 #if defined(OS_FUCHSIA) || defined(OS_MACOSX) 23 #error "This implementation is for POSIX platforms other than Fuchsia or Mac." 24 #endif 25 26 namespace { 27 ConvertTimespecToMicros(const struct timespec & ts)28int64_t ConvertTimespecToMicros(const struct timespec& ts) { 29 // On 32-bit systems, the calculation cannot overflow int64_t. 30 // 2**32 * 1000000 + 2**64 / 1000 < 2**63 31 if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) { 32 int64_t result = ts.tv_sec; 33 result *= base::Time::kMicrosecondsPerSecond; 34 result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); 35 return result; 36 } else { 37 base::CheckedNumeric<int64_t> result(ts.tv_sec); 38 result *= base::Time::kMicrosecondsPerSecond; 39 result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); 40 return result.ValueOrDie(); 41 } 42 } 43 44 // Helper function to get results from clock_gettime() and convert to a 45 // microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported 46 // on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines 47 // _POSIX_MONOTONIC_CLOCK to -1. 48 #if (defined(OS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \ 49 _POSIX_MONOTONIC_CLOCK >= 0) || \ 50 defined(OS_BSD) || defined(OS_ANDROID) ClockNow(clockid_t clk_id)51int64_t ClockNow(clockid_t clk_id) { 52 struct timespec ts; 53 CHECK(clock_gettime(clk_id, &ts) == 0); 54 return ConvertTimespecToMicros(ts); 55 } 56 #else // _POSIX_MONOTONIC_CLOCK 57 #error No usable tick clock function on this platform. 58 #endif // _POSIX_MONOTONIC_CLOCK 59 60 } // namespace 61 62 namespace base { 63 64 // Time ----------------------------------------------------------------------- 65 66 namespace subtle { TimeNowIgnoringOverride()67Time TimeNowIgnoringOverride() { 68 struct timeval tv; 69 struct timezone tz = {0, 0}; // UTC 70 CHECK(gettimeofday(&tv, &tz) == 0); 71 // Combine seconds and microseconds in a 64-bit field containing microseconds 72 // since the epoch. That's enough for nearly 600 centuries. Adjust from 73 // Unix (1970) to Windows (1601) epoch. 74 return Time() + TimeDelta::FromMicroseconds( 75 (tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) + 76 Time::kTimeTToMicrosecondsOffset); 77 } 78 TimeNowFromSystemTimeIgnoringOverride()79Time TimeNowFromSystemTimeIgnoringOverride() { 80 // Just use TimeNowIgnoringOverride() because it returns the system time. 81 return TimeNowIgnoringOverride(); 82 } 83 } // namespace subtle 84 85 // TimeTicks ------------------------------------------------------------------ 86 87 namespace subtle { TimeTicksNowIgnoringOverride()88TimeTicks TimeTicksNowIgnoringOverride() { 89 return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC)); 90 } 91 } // namespace subtle 92 93 // static GetClock()94TimeTicks::Clock TimeTicks::GetClock() { 95 return Clock::LINUX_CLOCK_MONOTONIC; 96 } 97 98 // static IsHighResolution()99bool TimeTicks::IsHighResolution() { 100 return true; 101 } 102 103 // static IsConsistentAcrossProcesses()104bool TimeTicks::IsConsistentAcrossProcesses() { 105 return true; 106 } 107 108 // ThreadTicks ---------------------------------------------------------------- 109 110 namespace subtle { ThreadTicksNowIgnoringOverride()111ThreadTicks ThreadTicksNowIgnoringOverride() { 112 #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ 113 defined(OS_ANDROID) 114 return ThreadTicks() + 115 TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID)); 116 #else 117 NOTREACHED(); 118 return ThreadTicks(); 119 #endif 120 } 121 } // namespace subtle 122 123 } // namespace base 124