1 /*
2 * Copyright (C) 2024 The Android Open Source Project
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 * http://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 #ifndef ART_RUNTIME_TRACE_COMMON_H_
18 #define ART_RUNTIME_TRACE_COMMON_H_
19
20 #include "android-base/stringprintf.h"
21 #include "art_method-inl.h"
22 #include "dex/descriptors_names.h"
23 #include "oat/oat_quick_method_header.h"
24
25 using android::base::StringPrintf;
26
27 namespace art HIDDEN {
28
GetMethodInfoLine(ArtMethod * method)29 static std::string GetMethodInfoLine(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
30 method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
31 return StringPrintf("%s\t%s\t%s\t%s\n",
32 PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(),
33 method->GetName(),
34 method->GetSignature().ToString().c_str(),
35 method->GetDeclaringClassSourceFile());
36 }
37
38 class TimestampCounter {
39 public:
GetTimestamp()40 static uint64_t GetTimestamp() {
41 uint64_t t = 0;
42 #if defined(__arm__)
43 // On ARM 32 bit, we don't always have access to the timestamp counters from user space. There
44 // is no easy way to check if it is safe to read the timestamp counters. There is HWCAP_EVTSTRM
45 // which is set when generic timer is available but not necessarily from the user space. Kernel
46 // disables access to generic timer when there are known problems on the target CPUs. Sometimes
47 // access is disabled only for 32-bit processes even when 64-bit processes can accesses the
48 // timer from user space. These are not reflected in the HWCAP_EVTSTRM capability.So just
49 // fallback to clock_gettime on these processes. See b/289178149 for more discussion.
50 t = NanoTime();
51 #elif defined(__aarch64__)
52 // See Arm Architecture Registers Armv8 section System Registers
53 asm volatile("mrs %0, cntvct_el0" : "=r"(t));
54 #elif defined(__i386__) || defined(__x86_64__)
55 // rdtsc returns two 32-bit values in rax and rdx even on 64-bit architectures.
56 unsigned int lo, hi;
57 asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
58 t = (static_cast<uint64_t>(hi) << 32) | lo;
59 #elif defined(__riscv)
60 asm volatile("rdtime %0" : "=r"(t));
61 #else
62 t = NanoTime();
63 #endif
64 return t;
65 }
66
InitializeTimestampCounters()67 static void InitializeTimestampCounters() {
68 // It is sufficient to initialize this once for the entire execution. Just return if it is
69 // already initialized.
70 if (tsc_to_nanosec_scaling_factor > 0.0) {
71 return;
72 }
73
74 #if defined(__arm__)
75 // On ARM 32 bit, we don't always have access to the timestamp counters from
76 // user space. Seem comment in GetTimestamp for more details.
77 tsc_to_nanosec_scaling_factor = 1.0;
78 #elif defined(__aarch64__)
79 double seconds_to_nanoseconds = 1000 * 1000;
80 uint64_t freq = 0;
81 // See Arm Architecture Registers Armv8 section System Registers
82 asm volatile("mrs %0, cntfrq_el0" : "=r"(freq));
83 if (freq == 0) {
84 // It is expected that cntfrq_el0 is correctly setup during system initialization but some
85 // devices don't do this. In such cases fall back to computing the frequency. See b/315139000.
86 tsc_to_nanosec_scaling_factor = computeScalingFactor();
87 } else {
88 tsc_to_nanosec_scaling_factor = seconds_to_nanoseconds / static_cast<double>(freq);
89 }
90 #elif defined(__i386__) || defined(__x86_64__)
91 tsc_to_nanosec_scaling_factor = GetScalingFactorForX86();
92 #else
93 tsc_to_nanosec_scaling_factor = 1.0;
94 #endif
95 }
96
GetNanoTime(uint64_t counter)97 static ALWAYS_INLINE uint64_t GetNanoTime(uint64_t counter) {
98 DCHECK(tsc_to_nanosec_scaling_factor > 0.0) << tsc_to_nanosec_scaling_factor;
99 return tsc_to_nanosec_scaling_factor * counter;
100 }
101
102 private:
103 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
104 // Here we compute the scaling factor by sleeping for a millisecond. Alternatively, we could
105 // generate raw timestamp counter and also time using clock_gettime at the start and the end of
106 // the trace. We can compute the frequency of timestamp counter upadtes in the post processing
107 // step using these two samples. However, that would require a change in Android Studio which is
108 // the main consumer of these profiles. For now, just compute the frequency of tsc updates here.
computeScalingFactor()109 static double computeScalingFactor() {
110 uint64_t start = NanoTime();
111 uint64_t start_tsc = GetTimestamp();
112 // Sleep for one millisecond.
113 usleep(1000);
114 uint64_t diff_tsc = GetTimestamp() - start_tsc;
115 uint64_t diff_time = NanoTime() - start;
116 double scaling_factor = static_cast<double>(diff_time) / diff_tsc;
117 DCHECK(scaling_factor > 0.0) << scaling_factor;
118 return scaling_factor;
119 }
120 #endif
121
122 #if defined(__i386__) || defined(__x86_64__)
GetScalingFactorForX86()123 static double GetScalingFactorForX86() {
124 uint32_t eax, ebx, ecx;
125 asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx) : "a"(0x0), "c"(0));
126 if (eax < 0x15) {
127 // There is no 15H - Timestamp counter and core crystal clock information
128 // leaf. Just compute the frequency.
129 return computeScalingFactor();
130 }
131
132 // From Intel architecture-instruction-set-extensions-programming-reference:
133 // EBX[31:0]/EAX[31:0] indicates the ratio of the TSC frequency and the
134 // core crystal clock frequency.
135 // If EBX[31:0] is 0, the TSC and "core crystal clock" ratio is not enumerated.
136 // If ECX is 0, the nominal core crystal clock frequency is not enumerated.
137 // "TSC frequency" = "core crystal clock frequency" * EBX/EAX.
138 // The core crystal clock may differ from the reference clock, bus clock, or core clock
139 // frequencies.
140 // EAX Bits 31 - 00: An unsigned integer which is the denominator of the
141 // TSC/"core crystal clock" ratio.
142 // EBX Bits 31 - 00: An unsigned integer which is the numerator of the
143 // TSC/"core crystal clock" ratio.
144 // ECX Bits 31 - 00: An unsigned integer which is the nominal frequency of the core
145 // crystal clock in Hz.
146 // EDX Bits 31 - 00: Reserved = 0.
147 asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx) : "a"(0x15), "c"(0));
148 if (ebx == 0 || ecx == 0) {
149 return computeScalingFactor();
150 }
151 double coreCrystalFreq = ecx;
152 // frequency = coreCrystalFreq * (ebx / eax)
153 // scaling_factor = seconds_to_nanoseconds / frequency
154 // = seconds_to_nanoseconds * eax / (coreCrystalFreq * ebx)
155 double seconds_to_nanoseconds = 1000 * 1000;
156 double scaling_factor = (seconds_to_nanoseconds * eax) / (coreCrystalFreq * ebx);
157 return scaling_factor;
158 }
159 #endif
160
161 // Scaling factor to convert timestamp counter into wall clock time reported in nano seconds.
162 // This is initialized at the start of tracing using the timestamp counter update frequency.
163 // See InitializeTimestampCounters for more details.
164 static double tsc_to_nanosec_scaling_factor;
165 };
166
167 } // namespace art
168
169 #endif // ART_RUNTIME_TRACE_COMMON_H_
170