1// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// UnscaledCycleClock
16// An UnscaledCycleClock yields the value and frequency of a cycle counter
17// that increments at a rate that is approximately constant.
18// This class is for internal / whitelisted use only, you should consider
19// using CycleClock instead.
20//
21// Notes:
22// The cycle counter frequency is not necessarily the core clock frequency.
23// That is, CycleCounter cycles are not necessarily "CPU cycles".
24//
25// An arbitrary offset may have been added to the counter at power on.
26//
27// On some platforms, the rate and offset of the counter may differ
28// slightly when read from different CPUs of a multiprocessor. Usually,
29// we try to ensure that the operating system adjusts values periodically
30// so that values agree approximately. If you need stronger guarantees,
31// consider using alternate interfaces.
32//
33// The CPU is not required to maintain the ordering of a cycle counter read
34// with respect to surrounding instructions.
35
36#ifndef ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
37#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
38
39#include <cstdint>
40
41#if defined(__APPLE__)
42#include <TargetConditionals.h>
43#endif
44
45#include "absl/base/port.h"
46
47// The following platforms have an implementation of a hardware counter.
48#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
49 defined(__powerpc__) || defined(__ppc__) || \
50 defined(_M_IX86) || defined(_M_X64)
51#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
52#else
53#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
54#endif
55
56// The following platforms often disable access to the hardware
57// counter (through a sandbox) even if the underlying hardware has a
58// usable counter. The CycleTimer interface also requires a *scaled*
59// CycleClock that runs at atleast 1 MHz. We've found some Android
60// ARM64 devices where this is not the case, so we disable it by
61// default on Android ARM64.
62#if defined(__native_client__) || \
63 (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
64 (defined(__ANDROID__) && defined(__aarch64__))
65#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
66#else
67#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
68#endif
69
70// UnscaledCycleClock is an optional internal feature.
71// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
72// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
73#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
74#define ABSL_USE_UNSCALED_CYCLECLOCK \
75 (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
76 ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
77#endif
78
79#if ABSL_USE_UNSCALED_CYCLECLOCK
80
81// This macro can be used to test if UnscaledCycleClock::Frequency()
82// is NominalCPUFrequency() on a particular platform.
83#if (defined(__i386__) || defined(__x86_64__) || \
84 defined(_M_IX86) || defined(_M_X64))
85#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
86#endif
87
88namespace absl {
89namespace time_internal {
90class UnscaledCycleClockWrapperForGetCurrentTime;
91} // namespace time_internal
92
93namespace base_internal {
94class CycleClock;
95class UnscaledCycleClockWrapperForInitializeFrequency;
96
97class UnscaledCycleClock {
98 private:
99 UnscaledCycleClock() = delete;
100
101 // Return the value of a cycle counter that counts at a rate that is
102 // approximately constant.
103 static int64_t Now();
104
105 // Return the how much UnscaledCycleClock::Now() increases per second.
106 // This is not necessarily the core CPU clock frequency.
107 // It may be the nominal value report by the kernel, rather than a measured
108 // value.
109 static double Frequency();
110
111 // Whitelisted friends.
112 friend class base_internal::CycleClock;
113 friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;
114 friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
115};
116
117} // namespace base_internal
118} // namespace absl
119
120#endif // ABSL_USE_UNSCALED_CYCLECLOCK
121
122#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
123