xref: /aosp_15_r20/external/cronet/base/time/time_apple.mm (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker// Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker#include "base/time/time.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker#import <Foundation/Foundation.h>
8*6777b538SAndroid Build Coastguard Worker#include <mach/mach.h>
9*6777b538SAndroid Build Coastguard Worker#include <mach/mach_time.h>
10*6777b538SAndroid Build Coastguard Worker#include <stddef.h>
11*6777b538SAndroid Build Coastguard Worker#include <stdint.h>
12*6777b538SAndroid Build Coastguard Worker#include <sys/sysctl.h>
13*6777b538SAndroid Build Coastguard Worker#include <sys/time.h>
14*6777b538SAndroid Build Coastguard Worker#include <sys/types.h>
15*6777b538SAndroid Build Coastguard Worker#include <time.h>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker#include "base/apple/mach_logging.h"
18*6777b538SAndroid Build Coastguard Worker#include "base/apple/scoped_cftyperef.h"
19*6777b538SAndroid Build Coastguard Worker#include "base/apple/scoped_mach_port.h"
20*6777b538SAndroid Build Coastguard Worker#include "base/logging.h"
21*6777b538SAndroid Build Coastguard Worker#include "base/numerics/safe_conversions.h"
22*6777b538SAndroid Build Coastguard Worker#include "base/time/time_override.h"
23*6777b538SAndroid Build Coastguard Worker#include "build/build_config.h"
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Workernamespace {
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker// Returns a pointer to the initialized Mach timebase info struct.
28*6777b538SAndroid Build Coastguard Workermach_timebase_info_data_t* MachTimebaseInfo() {
29*6777b538SAndroid Build Coastguard Worker  static mach_timebase_info_data_t timebase_info = []() {
30*6777b538SAndroid Build Coastguard Worker    mach_timebase_info_data_t info;
31*6777b538SAndroid Build Coastguard Worker    kern_return_t kr = mach_timebase_info(&info);
32*6777b538SAndroid Build Coastguard Worker    MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info";
33*6777b538SAndroid Build Coastguard Worker    DCHECK(info.numer);
34*6777b538SAndroid Build Coastguard Worker    DCHECK(info.denom);
35*6777b538SAndroid Build Coastguard Worker    return info;
36*6777b538SAndroid Build Coastguard Worker  }();
37*6777b538SAndroid Build Coastguard Worker  return &timebase_info;
38*6777b538SAndroid Build Coastguard Worker}
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Workerint64_t MachTimeToMicroseconds(uint64_t mach_time) {
41*6777b538SAndroid Build Coastguard Worker  // timebase_info gives us the conversion factor between absolute time tick
42*6777b538SAndroid Build Coastguard Worker  // units and nanoseconds.
43*6777b538SAndroid Build Coastguard Worker  mach_timebase_info_data_t* timebase_info = MachTimebaseInfo();
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker  // Take the fast path when the conversion is 1:1. The result will for sure fit
46*6777b538SAndroid Build Coastguard Worker  // into an int_64 because we're going from nanoseconds to microseconds.
47*6777b538SAndroid Build Coastguard Worker  if (timebase_info->numer == timebase_info->denom) {
48*6777b538SAndroid Build Coastguard Worker    return static_cast<int64_t>(mach_time /
49*6777b538SAndroid Build Coastguard Worker                                base::Time::kNanosecondsPerMicrosecond);
50*6777b538SAndroid Build Coastguard Worker  }
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker  uint64_t microseconds = 0;
53*6777b538SAndroid Build Coastguard Worker  const uint64_t divisor =
54*6777b538SAndroid Build Coastguard Worker      timebase_info->denom * base::Time::kNanosecondsPerMicrosecond;
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker  // Microseconds is mach_time * timebase.numer /
57*6777b538SAndroid Build Coastguard Worker  // (timebase.denom * kNanosecondsPerMicrosecond). Divide first to reduce
58*6777b538SAndroid Build Coastguard Worker  // the chance of overflow. Also stash the remainder right now, a likely
59*6777b538SAndroid Build Coastguard Worker  // byproduct of the division.
60*6777b538SAndroid Build Coastguard Worker  microseconds = mach_time / divisor;
61*6777b538SAndroid Build Coastguard Worker  const uint64_t mach_time_remainder = mach_time % divisor;
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker  // Now multiply, keeping an eye out for overflow.
64*6777b538SAndroid Build Coastguard Worker  CHECK(!__builtin_umulll_overflow(microseconds, timebase_info->numer,
65*6777b538SAndroid Build Coastguard Worker                                   &microseconds));
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker  // By dividing first we lose precision. Regain it by adding back the
68*6777b538SAndroid Build Coastguard Worker  // microseconds from the remainder, with an eye out for overflow.
69*6777b538SAndroid Build Coastguard Worker  uint64_t least_significant_microseconds =
70*6777b538SAndroid Build Coastguard Worker      (mach_time_remainder * timebase_info->numer) / divisor;
71*6777b538SAndroid Build Coastguard Worker  CHECK(!__builtin_uaddll_overflow(microseconds, least_significant_microseconds,
72*6777b538SAndroid Build Coastguard Worker                                   &microseconds));
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker  // Don't bother with the rollover handling that the Windows version does.
75*6777b538SAndroid Build Coastguard Worker  // The returned time in microseconds is enough for 292,277 years (starting
76*6777b538SAndroid Build Coastguard Worker  // from 2^63 because the returned int64_t is signed,
77*6777b538SAndroid Build Coastguard Worker  // 9223372036854775807 / (1e6 * 60 * 60 * 24 * 365.2425) = 292,277).
78*6777b538SAndroid Build Coastguard Worker  return base::checked_cast<int64_t>(microseconds);
79*6777b538SAndroid Build Coastguard Worker}
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker// Returns monotonically growing number of ticks in microseconds since some
82*6777b538SAndroid Build Coastguard Worker// unspecified starting point.
83*6777b538SAndroid Build Coastguard Workerint64_t ComputeCurrentTicks() {
84*6777b538SAndroid Build Coastguard Worker  // mach_absolute_time is it when it comes to ticks on the Mac.  Other calls
85*6777b538SAndroid Build Coastguard Worker  // with less precision (such as TickCount) just call through to
86*6777b538SAndroid Build Coastguard Worker  // mach_absolute_time.
87*6777b538SAndroid Build Coastguard Worker  return MachTimeToMicroseconds(mach_absolute_time());
88*6777b538SAndroid Build Coastguard Worker}
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Workerint64_t ComputeThreadTicks() {
91*6777b538SAndroid Build Coastguard Worker  struct timespec ts = {};
92*6777b538SAndroid Build Coastguard Worker  CHECK(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0);
93*6777b538SAndroid Build Coastguard Worker  base::CheckedNumeric<int64_t> absolute_micros(ts.tv_sec);
94*6777b538SAndroid Build Coastguard Worker  absolute_micros *= base::Time::kMicrosecondsPerSecond;
95*6777b538SAndroid Build Coastguard Worker  absolute_micros += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
96*6777b538SAndroid Build Coastguard Worker  return absolute_micros.ValueOrDie();
97*6777b538SAndroid Build Coastguard Worker}
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker}  // namespace
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Workernamespace base {
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker// The Time routines in this file use Mach and CoreFoundation APIs, since the
104*6777b538SAndroid Build Coastguard Worker// POSIX definition of time_t in macOS wraps around after 2038--and
105*6777b538SAndroid Build Coastguard Worker// there are already cookie expiration dates, etc., past that time out in
106*6777b538SAndroid Build Coastguard Worker// the field.  Using CFDate prevents that problem, and using mach_absolute_time
107*6777b538SAndroid Build Coastguard Worker// for TimeTicks gives us nice high-resolution interval timing.
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker// Time -----------------------------------------------------------------------
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Workernamespace subtle {
112*6777b538SAndroid Build Coastguard WorkerTime TimeNowIgnoringOverride() {
113*6777b538SAndroid Build Coastguard Worker  return Time::FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
114*6777b538SAndroid Build Coastguard Worker}
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard WorkerTime TimeNowFromSystemTimeIgnoringOverride() {
117*6777b538SAndroid Build Coastguard Worker  // Just use TimeNowIgnoringOverride() because it returns the system time.
118*6777b538SAndroid Build Coastguard Worker  return TimeNowIgnoringOverride();
119*6777b538SAndroid Build Coastguard Worker}
120*6777b538SAndroid Build Coastguard Worker}  // namespace subtle
121*6777b538SAndroid Build Coastguard Worker
122*6777b538SAndroid Build Coastguard Worker// static
123*6777b538SAndroid Build Coastguard WorkerTime Time::FromCFAbsoluteTime(CFAbsoluteTime t) {
124*6777b538SAndroid Build Coastguard Worker  static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
125*6777b538SAndroid Build Coastguard Worker                "CFAbsoluteTime must have an infinity value");
126*6777b538SAndroid Build Coastguard Worker  if (t == 0) {
127*6777b538SAndroid Build Coastguard Worker    return Time();  // Consider 0 as a null Time.
128*6777b538SAndroid Build Coastguard Worker  }
129*6777b538SAndroid Build Coastguard Worker  return (t == std::numeric_limits<CFAbsoluteTime>::infinity())
130*6777b538SAndroid Build Coastguard Worker             ? Max()
131*6777b538SAndroid Build Coastguard Worker             : (UnixEpoch() +
132*6777b538SAndroid Build Coastguard Worker                Seconds(double{t + kCFAbsoluteTimeIntervalSince1970}));
133*6777b538SAndroid Build Coastguard Worker}
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard WorkerCFAbsoluteTime Time::ToCFAbsoluteTime() const {
136*6777b538SAndroid Build Coastguard Worker  static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
137*6777b538SAndroid Build Coastguard Worker                "CFAbsoluteTime must have an infinity value");
138*6777b538SAndroid Build Coastguard Worker  if (is_null()) {
139*6777b538SAndroid Build Coastguard Worker    return 0;  // Consider 0 as a null Time.
140*6777b538SAndroid Build Coastguard Worker  }
141*6777b538SAndroid Build Coastguard Worker  return is_max() ? std::numeric_limits<CFAbsoluteTime>::infinity()
142*6777b538SAndroid Build Coastguard Worker                  : (CFAbsoluteTime{(*this - UnixEpoch()).InSecondsF()} -
143*6777b538SAndroid Build Coastguard Worker                     kCFAbsoluteTimeIntervalSince1970);
144*6777b538SAndroid Build Coastguard Worker}
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker// static
147*6777b538SAndroid Build Coastguard WorkerTime Time::FromNSDate(NSDate* date) {
148*6777b538SAndroid Build Coastguard Worker  DCHECK(date);
149*6777b538SAndroid Build Coastguard Worker  return FromCFAbsoluteTime(date.timeIntervalSinceReferenceDate);
150*6777b538SAndroid Build Coastguard Worker}
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard WorkerNSDate* Time::ToNSDate() const {
153*6777b538SAndroid Build Coastguard Worker  return [NSDate dateWithTimeIntervalSinceReferenceDate:ToCFAbsoluteTime()];
154*6777b538SAndroid Build Coastguard Worker}
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker// TimeDelta ------------------------------------------------------------------
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker// static
159*6777b538SAndroid Build Coastguard WorkerTimeDelta TimeDelta::FromMachTime(uint64_t mach_time) {
160*6777b538SAndroid Build Coastguard Worker  return Microseconds(MachTimeToMicroseconds(mach_time));
161*6777b538SAndroid Build Coastguard Worker}
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker// TimeTicks ------------------------------------------------------------------
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Workernamespace subtle {
166*6777b538SAndroid Build Coastguard WorkerTimeTicks TimeTicksNowIgnoringOverride() {
167*6777b538SAndroid Build Coastguard Worker  return TimeTicks() + Microseconds(ComputeCurrentTicks());
168*6777b538SAndroid Build Coastguard Worker}
169*6777b538SAndroid Build Coastguard Worker}  // namespace subtle
170*6777b538SAndroid Build Coastguard Worker
171*6777b538SAndroid Build Coastguard Worker// static
172*6777b538SAndroid Build Coastguard Workerbool TimeTicks::IsHighResolution() {
173*6777b538SAndroid Build Coastguard Worker  return true;
174*6777b538SAndroid Build Coastguard Worker}
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker// static
177*6777b538SAndroid Build Coastguard Workerbool TimeTicks::IsConsistentAcrossProcesses() {
178*6777b538SAndroid Build Coastguard Worker  return true;
179*6777b538SAndroid Build Coastguard Worker}
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker// static
182*6777b538SAndroid Build Coastguard WorkerTimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) {
183*6777b538SAndroid Build Coastguard Worker  return TimeTicks(MachTimeToMicroseconds(mach_absolute_time));
184*6777b538SAndroid Build Coastguard Worker}
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker// static
187*6777b538SAndroid Build Coastguard Workermach_timebase_info_data_t TimeTicks::SetMachTimebaseInfoForTesting(
188*6777b538SAndroid Build Coastguard Worker    mach_timebase_info_data_t timebase) {
189*6777b538SAndroid Build Coastguard Worker  mach_timebase_info_data_t orig_timebase = *MachTimebaseInfo();
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker  *MachTimebaseInfo() = timebase;
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker  return orig_timebase;
194*6777b538SAndroid Build Coastguard Worker}
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker// static
197*6777b538SAndroid Build Coastguard WorkerTimeTicks::Clock TimeTicks::GetClock() {
198*6777b538SAndroid Build Coastguard Worker  return Clock::MAC_MACH_ABSOLUTE_TIME;
199*6777b538SAndroid Build Coastguard Worker}
200*6777b538SAndroid Build Coastguard Worker
201*6777b538SAndroid Build Coastguard Worker// ThreadTicks ----------------------------------------------------------------
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Workernamespace subtle {
204*6777b538SAndroid Build Coastguard WorkerThreadTicks ThreadTicksNowIgnoringOverride() {
205*6777b538SAndroid Build Coastguard Worker  return ThreadTicks() + Microseconds(ComputeThreadTicks());
206*6777b538SAndroid Build Coastguard Worker}
207*6777b538SAndroid Build Coastguard Worker}  // namespace subtle
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker}  // namespace base
210