• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)28 int64_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)51 int64_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()67 Time 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()79 Time 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()88 TimeTicks TimeTicksNowIgnoringOverride() {
89   return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC));
90 }
91 }  // namespace subtle
92 
93 // static
GetClock()94 TimeTicks::Clock TimeTicks::GetClock() {
95   return Clock::LINUX_CLOCK_MONOTONIC;
96 }
97 
98 // static
IsHighResolution()99 bool TimeTicks::IsHighResolution() {
100   return true;
101 }
102 
103 // static
IsConsistentAcrossProcesses()104 bool TimeTicks::IsConsistentAcrossProcesses() {
105   return true;
106 }
107 
108 // ThreadTicks ----------------------------------------------------------------
109 
110 namespace subtle {
ThreadTicksNowIgnoringOverride()111 ThreadTicks 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