blob: 1abed2551cbd523fb65e85c12f47169bd49d4b01 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]8822d972008-11-03 19:36:592// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]89bf27e2013-06-27 18:04:565#include "base/time/time.h"
[email protected]8822d972008-11-03 19:36:596
Elly Fong-Jones2a9b9b82021-03-15 16:49:497#import <Foundation/Foundation.h>
[email protected]4ce59752013-11-07 01:01:468#include <mach/mach.h>
[email protected]8822d972008-11-03 19:36:599#include <mach/mach_time.h>
avi9b6f42932015-12-26 22:15:1410#include <stddef.h>
tfarina32089922015-05-18 22:14:0911#include <stdint.h>
[email protected]f98fb5e2012-12-13 10:18:5812#include <sys/sysctl.h>
[email protected]8822d972008-11-03 19:36:5913#include <sys/time.h>
[email protected]f98fb5e2012-12-13 10:18:5814#include <sys/types.h>
[email protected]8822d972008-11-03 19:36:5915#include <time.h>
16
Avi Drissman0b200712023-08-16 20:35:4917#include "base/apple/mach_logging.h"
Avi Drissmana09d7dd2023-08-17 16:26:5818#include "base/apple/scoped_cftyperef.h"
Avi Drissmandd92b532023-08-16 22:26:1719#include "base/apple/scoped_mach_port.h"
[email protected]8822d972008-11-03 19:36:5920#include "base/logging.h"
miu1ab506a2015-05-29 23:57:1221#include "base/numerics/safe_conversions.h"
Eric Secklera93679352018-01-25 17:04:1222#include "base/time/time_override.h"
avi9b6f42932015-12-26 22:15:1423#include "build/build_config.h"
[email protected]8822d972008-11-03 19:36:5924
[email protected]f98fb5e2012-12-13 10:18:5825namespace {
26
Jayson Adams608e251f2021-05-27 00:26:2927// Returns a pointer to the initialized Mach timebase info struct.
Jayson Adams0c3caf92022-01-06 22:33:0228mach_timebase_info_data_t* MachTimebaseInfo() {
Sorin Jianuad4cc6232024-10-08 19:06:0129 static mach_timebase_info_data_t timebase_info = [] {
Jayson Adams608e251f2021-05-27 00:26:2930 mach_timebase_info_data_t info;
31 kern_return_t kr = mach_timebase_info(&info);
[email protected]07c19ac2014-05-12 18:49:5532 MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info";
Jayson Adams608e251f2021-05-27 00:26:2933 DCHECK(info.numer);
34 DCHECK(info.denom);
35 return info;
36 }();
37 return &timebase_info;
38}
39
40int64_t MachTimeToMicroseconds(uint64_t mach_time) {
41 // timebase_info gives us the conversion factor between absolute time tick
42 // units and nanoseconds.
Jayson Adams0c3caf92022-01-06 22:33:0243 mach_timebase_info_data_t* timebase_info = MachTimebaseInfo();
Jayson Adams608e251f2021-05-27 00:26:2944
45 // Take the fast path when the conversion is 1:1. The result will for sure fit
46 // into an int_64 because we're going from nanoseconds to microseconds.
47 if (timebase_info->numer == timebase_info->denom) {
48 return static_cast<int64_t>(mach_time /
49 base::Time::kNanosecondsPerMicrosecond);
[email protected]f98fb5e2012-12-13 10:18:5850 }
51
Jayson Adams0c3caf92022-01-06 22:33:0252 uint64_t microseconds = 0;
53 const uint64_t divisor =
54 timebase_info->denom * base::Time::kNanosecondsPerMicrosecond;
[email protected]f98fb5e2012-12-13 10:18:5855
Jayson Adams0c3caf92022-01-06 22:33:0256 // Microseconds is mach_time * timebase.numer /
57 // (timebase.denom * kNanosecondsPerMicrosecond). Divide first to reduce
58 // the chance of overflow. Also stash the remainder right now, a likely
59 // byproduct of the division.
60 microseconds = mach_time / divisor;
61 const uint64_t mach_time_remainder = mach_time % divisor;
Jayson Adams608e251f2021-05-27 00:26:2962
Jayson Adams0c3caf92022-01-06 22:33:0263 // Now multiply, keeping an eye out for overflow.
64 CHECK(!__builtin_umulll_overflow(microseconds, timebase_info->numer,
65 &microseconds));
66
67 // By dividing first we lose precision. Regain it by adding back the
68 // microseconds from the remainder, with an eye out for overflow.
69 uint64_t least_significant_microseconds =
70 (mach_time_remainder * timebase_info->numer) / divisor;
71 CHECK(!__builtin_uaddll_overflow(microseconds, least_significant_microseconds,
72 &microseconds));
73
74 // Don't bother with the rollover handling that the Windows version does.
75 // The returned time in microseconds is enough for 292,277 years (starting
76 // from 2^63 because the returned int64_t is signed,
77 // 9223372036854775807 / (1e6 * 60 * 60 * 24 * 365.2425) = 292,277).
Jayson Adams608e251f2021-05-27 00:26:2978 return base::checked_cast<int64_t>(microseconds);
jameswest3de19856c2016-09-30 00:44:5179}
jameswest3de19856c2016-09-30 00:44:5180
kapishnikov5dc9bafa2017-05-24 17:26:0181// Returns monotonically growing number of ticks in microseconds since some
82// unspecified starting point.
jameswest3de19856c2016-09-30 00:44:5183int64_t ComputeCurrentTicks() {
jameswest3de19856c2016-09-30 00:44:5184 // mach_absolute_time is it when it comes to ticks on the Mac. Other calls
85 // with less precision (such as TickCount) just call through to
86 // mach_absolute_time.
Alex Chau9eb03cdd52020-07-13 21:04:5787 return MachTimeToMicroseconds(mach_absolute_time());
[email protected]f98fb5e2012-12-13 10:18:5888}
89
miu1ab506a2015-05-29 23:57:1290int64_t ComputeThreadTicks() {
Mikhail Khokhlovdda73b42023-10-02 17:07:2391 struct timespec ts = {};
92 CHECK(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0);
93 base::CheckedNumeric<int64_t> absolute_micros(ts.tv_sec);
miu1ab506a2015-05-29 23:57:1294 absolute_micros *= base::Time::kMicrosecondsPerSecond;
Mikhail Khokhlovdda73b42023-10-02 17:07:2395 absolute_micros += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
miu1ab506a2015-05-29 23:57:1296 return absolute_micros.ValueOrDie();
[email protected]4ce59752013-11-07 01:01:4697}
98
[email protected]f98fb5e2012-12-13 10:18:5899} // namespace
100
[email protected]8822d972008-11-03 19:36:59101namespace base {
102
103// The Time routines in this file use Mach and CoreFoundation APIs, since the
Avi Drissman6fdbaf082023-06-07 19:35:09104// POSIX definition of time_t in macOS wraps around after 2038--and
[email protected]8822d972008-11-03 19:36:59105// there are already cookie expiration dates, etc., past that time out in
106// the field. Using CFDate prevents that problem, and using mach_absolute_time
107// for TimeTicks gives us nice high-resolution interval timing.
108
109// Time -----------------------------------------------------------------------
110
Eric Secklera93679352018-01-25 17:04:12111namespace subtle {
112Time TimeNowIgnoringOverride() {
113 return Time::FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
[email protected]2e80a192012-07-24 16:30:34114}
115
Eric Secklera93679352018-01-25 17:04:12116Time TimeNowFromSystemTimeIgnoringOverride() {
117 // Just use TimeNowIgnoringOverride() because it returns the system time.
118 return TimeNowIgnoringOverride();
119}
120} // namespace subtle
121
[email protected]2e80a192012-07-24 16:30:34122// static
123Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) {
avi4ec0dff2015-11-24 14:26:24124 static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
125 "CFAbsoluteTime must have an infinity value");
Avi Drissman89c0d152023-08-14 23:04:47126 if (t == 0) {
[email protected]2e80a192012-07-24 16:30:34127 return Time(); // Consider 0 as a null Time.
Avi Drissman89c0d152023-08-14 23:04:47128 }
Peter Kastingcb6f1ec2020-08-20 02:37:36129 return (t == std::numeric_limits<CFAbsoluteTime>::infinity())
130 ? Max()
Peter Kasting53fd6ee2021-10-05 20:40:48131 : (UnixEpoch() +
132 Seconds(double{t + kCFAbsoluteTimeIntervalSince1970}));
[email protected]8822d972008-11-03 19:36:59133}
134
[email protected]2e80a192012-07-24 16:30:34135CFAbsoluteTime Time::ToCFAbsoluteTime() const {
avi4ec0dff2015-11-24 14:26:24136 static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
137 "CFAbsoluteTime must have an infinity value");
Avi Drissman89c0d152023-08-14 23:04:47138 if (is_null()) {
[email protected]2e80a192012-07-24 16:30:34139 return 0; // Consider 0 as a null Time.
Avi Drissman89c0d152023-08-14 23:04:47140 }
Peter Kastingcb6f1ec2020-08-20 02:37:36141 return is_max() ? std::numeric_limits<CFAbsoluteTime>::infinity()
142 : (CFAbsoluteTime{(*this - UnixEpoch()).InSecondsF()} -
143 kCFAbsoluteTimeIntervalSince1970);
[email protected]2e80a192012-07-24 16:30:34144}
145
Elly Fong-Jones2a9b9b82021-03-15 16:49:49146// static
147Time Time::FromNSDate(NSDate* date) {
148 DCHECK(date);
149 return FromCFAbsoluteTime(date.timeIntervalSinceReferenceDate);
150}
151
152NSDate* Time::ToNSDate() const {
153 return [NSDate dateWithTimeIntervalSinceReferenceDate:ToCFAbsoluteTime()];
154}
155
Alex Chau9eb03cdd52020-07-13 21:04:57156// TimeDelta ------------------------------------------------------------------
157
Alex Chau9eb03cdd52020-07-13 21:04:57158// static
159TimeDelta TimeDelta::FromMachTime(uint64_t mach_time) {
Peter Kasting53fd6ee2021-10-05 20:40:48160 return Microseconds(MachTimeToMicroseconds(mach_time));
Alex Chau9eb03cdd52020-07-13 21:04:57161}
Alex Chau9eb03cdd52020-07-13 21:04:57162
[email protected]8822d972008-11-03 19:36:59163// TimeTicks ------------------------------------------------------------------
164
Eric Secklera93679352018-01-25 17:04:12165namespace subtle {
166TimeTicks TimeTicksNowIgnoringOverride() {
Peter Kasting53fd6ee2021-10-05 20:40:48167 return TimeTicks() + Microseconds(ComputeCurrentTicks());
[email protected]8822d972008-11-03 19:36:59168}
Mike Wittmaneab167642024-11-06 20:48:41169
170TimeTicks TimeTicksLowResolutionNowIgnoringOverride() {
171 return TimeTicks() + Microseconds(MachTimeToMicroseconds(
172 clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW_APPROX)));
173}
Eric Secklera93679352018-01-25 17:04:12174} // namespace subtle
[email protected]8822d972008-11-03 19:36:59175
176// static
miu59907192015-01-14 05:33:08177bool TimeTicks::IsHighResolution() {
[email protected]cef72a92013-10-15 23:16:05178 return true;
179}
180
181// static
majidvp4f3e2862016-07-22 21:39:02182bool TimeTicks::IsConsistentAcrossProcesses() {
183 return true;
184}
185
jameswest3de19856c2016-09-30 00:44:51186// static
187TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) {
Alex Chau9eb03cdd52020-07-13 21:04:57188 return TimeTicks(MachTimeToMicroseconds(mach_absolute_time));
jameswest3de19856c2016-09-30 00:44:51189}
Jayson Adams608e251f2021-05-27 00:26:29190
191// static
Jayson Adams0c3caf92022-01-06 22:33:02192mach_timebase_info_data_t TimeTicks::SetMachTimebaseInfoForTesting(
193 mach_timebase_info_data_t timebase) {
194 mach_timebase_info_data_t orig_timebase = *MachTimebaseInfo();
195
196 *MachTimebaseInfo() = timebase;
197
198 return orig_timebase;
Jayson Adams608e251f2021-05-27 00:26:29199}
Jayson Adams0c3caf92022-01-06 22:33:02200
majidvp4f3e2862016-07-22 21:39:02201// static
charlieafdd7d492016-03-31 19:05:18202TimeTicks::Clock TimeTicks::GetClock() {
charlieafdd7d492016-03-31 19:05:18203 return Clock::MAC_MACH_ABSOLUTE_TIME;
charlieafdd7d492016-03-31 19:05:18204}
205
Eric Secklera93679352018-01-25 17:04:12206// ThreadTicks ----------------------------------------------------------------
207
208namespace subtle {
209ThreadTicks ThreadTicksNowIgnoringOverride() {
Peter Kasting53fd6ee2021-10-05 20:40:48210 return ThreadTicks() + Microseconds(ComputeThreadTicks());
[email protected]58cd0282013-07-31 06:36:04211}
Eric Secklera93679352018-01-25 17:04:12212} // namespace subtle
[email protected]58cd0282013-07-31 06:36:04213
[email protected]8822d972008-11-03 19:36:59214} // namespace base