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)27 int64_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)50 int64_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()66 Time 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()78 Time Time::NowFromSystemTime() {
79   // Just use Now() because Now() returns the system time.
80   return Now();
81 }
82 
83 // TimeTicks ------------------------------------------------------------------
84 
85 // static
Now()86 TimeTicks TimeTicks::Now() {
87   return TimeTicks(ClockNow(CLOCK_MONOTONIC));
88 }
89 
90 // static
GetClock()91 TimeTicks::Clock TimeTicks::GetClock() {
92   return Clock::LINUX_CLOCK_MONOTONIC;
93 }
94 
95 // static
IsHighResolution()96 bool TimeTicks::IsHighResolution() {
97   return true;
98 }
99 
100 // static
IsConsistentAcrossProcesses()101 bool TimeTicks::IsConsistentAcrossProcesses() {
102   return true;
103 }
104 
105 // static
Now()106 ThreadTicks 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