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