abseil-cpp/absl/base/internal/cycleclock.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 // -----------------------------------------------------------------------------
18 // File: cycleclock.h
19 // -----------------------------------------------------------------------------
20 //
21 // This header file defines a `CycleClock`, which yields the value and frequency
22 // of a cycle counter that increments at a rate that is approximately constant.
23 //
24 // NOTE:
25 //
26 // The cycle counter frequency is not necessarily related to the core clock
27 // frequency and should not be treated as such. That is, `CycleClock` cycles are
28 // not necessarily "CPU cycles" and code should not rely on that behavior, even
29 // if experimentally observed.
30 //
31 // An arbitrary offset may have been added to the counter at power on.
32 //
33 // On some platforms, the rate and offset of the counter may differ
34 // slightly when read from different CPUs of a multiprocessor. Usually,
35 // we try to ensure that the operating system adjusts values periodically
36 // so that values agree approximately. If you need stronger guarantees,
37 // consider using alternate interfaces.
38 //
39 // The CPU is not required to maintain the ordering of a cycle counter read
40 // with respect to surrounding instructions.
41 
42 #ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_H_
43 #define ABSL_BASE_INTERNAL_CYCLECLOCK_H_
44 
45 #include <atomic>
46 #include <cstdint>
47 
48 #include "absl/base/attributes.h"
49 #include "absl/base/config.h"
50 #include "absl/base/internal/unscaledcycleclock.h"
51 
52 namespace absl {
54 namespace base_internal {
55 
57 
58 // -----------------------------------------------------------------------------
59 // CycleClock
60 // -----------------------------------------------------------------------------
61 class CycleClock {
62  public:
63  // CycleClock::Now()
64  //
65  // Returns the value of a cycle counter that counts at a rate that is
66  // approximately constant.
67  static int64_t Now();
68 
69  // CycleClock::Frequency()
70  //
71  // Returns the amount by which `CycleClock::Now()` increases per second. Note
72  // that this value may not necessarily match the core CPU clock frequency.
73  static double Frequency();
74 
75  private:
76 #if ABSL_USE_UNSCALED_CYCLECLOCK
77  static CycleClockSourceFunc LoadCycleClockSource();
78 
79 #ifdef NDEBUG
80 #ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
81  // Not debug mode and the UnscaledCycleClock frequency is the CPU
82  // frequency. Scale the CycleClock to prevent overflow if someone
83  // tries to represent the time as cycles since the Unix epoch.
84  static constexpr int32_t kShift = 1;
85 #else
86  // Not debug mode and the UnscaledCycleClock isn't operating at the
87  // raw CPU frequency. There is no need to do any scaling, so don't
88  // needlessly sacrifice precision.
89  static constexpr int32_t kShift = 0;
90 #endif
91 #else // NDEBUG
92  // In debug mode use a different shift to discourage depending on a
93  // particular shift value.
94  static constexpr int32_t kShift = 2;
95 #endif // NDEBUG
96 
97  static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
98  ABSL_CONST_INIT static std::atomic<CycleClockSourceFunc> cycle_clock_source_;
99 #endif // ABSL_USE_UNSCALED_CYCLECLOC
100 
101  CycleClock() = delete; // no instances
102  CycleClock(const CycleClock&) = delete;
103  CycleClock& operator=(const CycleClock&) = delete;
104 
105  friend class CycleClockSource;
106 };
107 
109  private:
110  // CycleClockSource::Register()
111  //
112  // Register a function that provides an alternate source for the unscaled CPU
113  // cycle count value. The source function must be async signal safe, must not
114  // call CycleClock::Now(), and must have a frequency that matches that of the
115  // unscaled clock used by CycleClock. A nullptr value resets CycleClock to use
116  // the default source.
117  static void Register(CycleClockSourceFunc source);
118 };
119 
120 #if ABSL_USE_UNSCALED_CYCLECLOCK
121 
122 inline CycleClockSourceFunc CycleClock::LoadCycleClockSource() {
123 #if !defined(__x86_64__)
124  // Optimize for the common case (no callback) by first doing a relaxed load;
125  // this is significantly faster on non-x86 platforms.
126  if (cycle_clock_source_.load(std::memory_order_relaxed) == nullptr) {
127  return nullptr;
128  }
129 #endif // !defined(__x86_64__)
130 
131  // This corresponds to the store(std::memory_order_release) in
132  // CycleClockSource::Register, and makes sure that any updates made prior to
133  // registering the callback are visible to this thread before the callback
134  // is invoked.
135  return cycle_clock_source_.load(std::memory_order_acquire);
136 }
137 
138 // Accessing globals in inlined code in Window DLLs is problematic.
139 #ifndef _WIN32
140 inline int64_t CycleClock::Now() {
141  auto fn = LoadCycleClockSource();
142  if (fn == nullptr) {
143  return base_internal::UnscaledCycleClock::Now() >> kShift;
144  }
145  return fn() >> kShift;
146 }
147 #endif
148 
149 inline double CycleClock::Frequency() {
150  return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
151 }
152 
153 #endif // ABSL_USE_UNSCALED_CYCLECLOCK
154 
155 } // namespace base_internal
157 } // namespace absl
158 
159 #endif // ABSL_BASE_INTERNAL_CYCLECLOCK_H_
absl::base_internal::CycleClock::CycleClock
CycleClock()=delete
ABSL_CONST_INIT
#define ABSL_CONST_INIT
Definition: abseil-cpp/absl/base/attributes.h:716
absl::base_internal::CycleClock::Frequency
static double Frequency()
Definition: abseil-cpp/absl/base/internal/cycleclock.cc:69
absl::base_internal::CycleClockSource
Definition: abseil-cpp/absl/base/internal/cycleclock.h:108
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::base_internal::CycleClockSourceFunc
int64_t(*)() CycleClockSourceFunc
Definition: abseil-cpp/absl/base/internal/cycleclock.h:56
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
generate-asm-lcov.fn
fn
Definition: generate-asm-lcov.py:146
absl::base_internal::CycleClock::operator=
CycleClock & operator=(const CycleClock &)=delete
absl::base_internal::CycleClock
Definition: abseil-cpp/absl/base/internal/cycleclock.h:61
absl::base_internal::CycleClock::Now
static int64_t Now()
Definition: abseil-cpp/absl/base/internal/cycleclock.cc:63
absl::Now
ABSL_NAMESPACE_BEGIN Time Now()
Definition: abseil-cpp/absl/time/clock.cc:39
absl::base_internal::CycleClockSource::Register
static void Register(CycleClockSourceFunc source)
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:08