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