1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "trace.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <sys/uio.h>
20*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
23*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
24*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
34*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
35*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
36*795d594fSAndroid Build Coastguard Worker #include "com_android_art_flags.h"
37*795d594fSAndroid Build Coastguard Worker #include "debugger.h"
38*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "entrypoints/quick/quick_entrypoints.h"
41*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
42*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
43*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
44*795d594fSAndroid Build Coastguard Worker #include "jit/jit_code_cache.h"
45*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
50*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
51*795d594fSAndroid Build Coastguard Worker #include "stack.h"
52*795d594fSAndroid Build Coastguard Worker #include "thread.h"
53*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
54*795d594fSAndroid Build Coastguard Worker #include "trace_profile.h"
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker namespace art_flags = com::android::art::flags;
57*795d594fSAndroid Build Coastguard Worker
58*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
59*795d594fSAndroid Build Coastguard Worker
60*795d594fSAndroid Build Coastguard Worker struct MethodTraceRecord {
61*795d594fSAndroid Build Coastguard Worker ArtMethod* method;
62*795d594fSAndroid Build Coastguard Worker TraceAction action;
63*795d594fSAndroid Build Coastguard Worker uint32_t wall_clock_time;
64*795d594fSAndroid Build Coastguard Worker uint32_t thread_cpu_time;
65*795d594fSAndroid Build Coastguard Worker };
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker static constexpr size_t TraceActionBits = MinimumBitsToStore(
70*795d594fSAndroid Build Coastguard Worker static_cast<size_t>(kTraceMethodActionMask));
71*795d594fSAndroid Build Coastguard Worker static constexpr uint8_t kOpNewMethod = 1U;
72*795d594fSAndroid Build Coastguard Worker static constexpr uint8_t kOpNewThread = 2U;
73*795d594fSAndroid Build Coastguard Worker static constexpr uint8_t kOpTraceSummary = 3U;
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker static const char kTraceTokenChar = '*';
76*795d594fSAndroid Build Coastguard Worker static const uint16_t kTraceHeaderLength = 32;
77*795d594fSAndroid Build Coastguard Worker static const uint32_t kTraceMagicValue = 0x574f4c53;
78*795d594fSAndroid Build Coastguard Worker static const uint16_t kTraceVersionSingleClock = 2;
79*795d594fSAndroid Build Coastguard Worker static const uint16_t kTraceVersionDualClock = 3;
80*795d594fSAndroid Build Coastguard Worker static const uint16_t kTraceRecordSizeSingleClock = 10; // using v2
81*795d594fSAndroid Build Coastguard Worker static const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps
82*795d594fSAndroid Build Coastguard Worker static const size_t kNumTracePoolBuffers = 32;
83*795d594fSAndroid Build Coastguard Worker
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMinBufSize = 18U; // Trace header is up to 18B.
86*795d594fSAndroid Build Coastguard Worker // Size of per-thread buffer size. The value is chosen arbitrarily. This value
87*795d594fSAndroid Build Coastguard Worker // should be greater than kMinBufSize.
88*795d594fSAndroid Build Coastguard Worker static constexpr size_t kPerThreadBufSize = 512 * 1024;
89*795d594fSAndroid Build Coastguard Worker static_assert(kPerThreadBufSize > kMinBufSize);
90*795d594fSAndroid Build Coastguard Worker // On average we need 12 bytes for encoding an entry. We typically use two
91*795d594fSAndroid Build Coastguard Worker // entries in per-thread buffer, the scaling factor is 6.
92*795d594fSAndroid Build Coastguard Worker static constexpr size_t kScalingFactorEncodedEntries = 6;
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker // The key identifying the tracer to update instrumentation.
95*795d594fSAndroid Build Coastguard Worker static constexpr const char* kTracerInstrumentationKey = "Tracer";
96*795d594fSAndroid Build Coastguard Worker
97*795d594fSAndroid Build Coastguard Worker Trace* Trace::the_trace_ = nullptr;
98*795d594fSAndroid Build Coastguard Worker pthread_t Trace::sampling_pthread_ = 0U;
99*795d594fSAndroid Build Coastguard Worker std::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_;
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker
DecodeTraceAction(uint32_t tmid)102*795d594fSAndroid Build Coastguard Worker static TraceAction DecodeTraceAction(uint32_t tmid) {
103*795d594fSAndroid Build Coastguard Worker return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker
106*795d594fSAndroid Build Coastguard Worker namespace {
107*795d594fSAndroid Build Coastguard Worker // Scaling factor to convert timestamp counter into wall clock time reported in micro seconds.
108*795d594fSAndroid Build Coastguard Worker // This is initialized at the start of tracing using the timestamp counter update frequency.
109*795d594fSAndroid Build Coastguard Worker // See InitializeTimestampCounters for more details.
110*795d594fSAndroid Build Coastguard Worker double tsc_to_microsec_scaling_factor = -1.0;
111*795d594fSAndroid Build Coastguard Worker
GetTimestamp()112*795d594fSAndroid Build Coastguard Worker uint64_t GetTimestamp() {
113*795d594fSAndroid Build Coastguard Worker uint64_t t = 0;
114*795d594fSAndroid Build Coastguard Worker #if defined(__arm__)
115*795d594fSAndroid Build Coastguard Worker // On ARM 32 bit, we don't always have access to the timestamp counters from user space. There is
116*795d594fSAndroid Build Coastguard Worker // no easy way to check if it is safe to read the timestamp counters. There is HWCAP_EVTSTRM which
117*795d594fSAndroid Build Coastguard Worker // is set when generic timer is available but not necessarily from the user space. Kernel disables
118*795d594fSAndroid Build Coastguard Worker // access to generic timer when there are known problems on the target CPUs. Sometimes access is
119*795d594fSAndroid Build Coastguard Worker // disabled only for 32-bit processes even when 64-bit processes can accesses the timer from user
120*795d594fSAndroid Build Coastguard Worker // space. These are not reflected in the HWCAP_EVTSTRM capability.So just fallback to
121*795d594fSAndroid Build Coastguard Worker // clock_gettime on these processes. See b/289178149 for more discussion.
122*795d594fSAndroid Build Coastguard Worker t = MicroTime();
123*795d594fSAndroid Build Coastguard Worker #elif defined(__aarch64__)
124*795d594fSAndroid Build Coastguard Worker // See Arm Architecture Registers Armv8 section System Registers
125*795d594fSAndroid Build Coastguard Worker asm volatile("mrs %0, cntvct_el0" : "=r"(t));
126*795d594fSAndroid Build Coastguard Worker #elif defined(__i386__) || defined(__x86_64__)
127*795d594fSAndroid Build Coastguard Worker // rdtsc returns two 32-bit values in rax and rdx even on 64-bit architectures.
128*795d594fSAndroid Build Coastguard Worker unsigned int lo, hi;
129*795d594fSAndroid Build Coastguard Worker asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
130*795d594fSAndroid Build Coastguard Worker t = (static_cast<uint64_t>(hi) << 32) | lo;
131*795d594fSAndroid Build Coastguard Worker #elif defined(__riscv)
132*795d594fSAndroid Build Coastguard Worker asm volatile("rdtime %0" : "=r"(t));
133*795d594fSAndroid Build Coastguard Worker #else
134*795d594fSAndroid Build Coastguard Worker t = MicroTime();
135*795d594fSAndroid Build Coastguard Worker #endif
136*795d594fSAndroid Build Coastguard Worker return t;
137*795d594fSAndroid Build Coastguard Worker }
138*795d594fSAndroid Build Coastguard Worker
139*795d594fSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
140*795d594fSAndroid Build Coastguard Worker // Here we compute the scaling factor by sleeping for a millisecond. Alternatively, we could
141*795d594fSAndroid Build Coastguard Worker // generate raw timestamp counter and also time using clock_gettime at the start and the end of the
142*795d594fSAndroid Build Coastguard Worker // trace. We can compute the frequency of timestamp counter upadtes in the post processing step
143*795d594fSAndroid Build Coastguard Worker // using these two samples. However, that would require a change in Android Studio which is the main
144*795d594fSAndroid Build Coastguard Worker // consumer of these profiles. For now, just compute the frequency of tsc updates here.
computeScalingFactor()145*795d594fSAndroid Build Coastguard Worker double computeScalingFactor() {
146*795d594fSAndroid Build Coastguard Worker uint64_t start = MicroTime();
147*795d594fSAndroid Build Coastguard Worker uint64_t start_tsc = GetTimestamp();
148*795d594fSAndroid Build Coastguard Worker // Sleep for one millisecond.
149*795d594fSAndroid Build Coastguard Worker usleep(1000);
150*795d594fSAndroid Build Coastguard Worker uint64_t diff_tsc = GetTimestamp() - start_tsc;
151*795d594fSAndroid Build Coastguard Worker uint64_t diff_time = MicroTime() - start;
152*795d594fSAndroid Build Coastguard Worker double scaling_factor = static_cast<double>(diff_time) / diff_tsc;
153*795d594fSAndroid Build Coastguard Worker DCHECK(scaling_factor > 0.0) << scaling_factor;
154*795d594fSAndroid Build Coastguard Worker return scaling_factor;
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker #endif
157*795d594fSAndroid Build Coastguard Worker
158*795d594fSAndroid Build Coastguard Worker #if defined(__i386__) || defined(__x86_64__)
GetScalingFactorForX86()159*795d594fSAndroid Build Coastguard Worker double GetScalingFactorForX86() {
160*795d594fSAndroid Build Coastguard Worker uint32_t eax, ebx, ecx;
161*795d594fSAndroid Build Coastguard Worker asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx) : "a"(0x0), "c"(0));
162*795d594fSAndroid Build Coastguard Worker if (eax < 0x15) {
163*795d594fSAndroid Build Coastguard Worker // There is no 15H - Timestamp counter and core crystal clock information
164*795d594fSAndroid Build Coastguard Worker // leaf. Just compute the frequency.
165*795d594fSAndroid Build Coastguard Worker return computeScalingFactor();
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
168*795d594fSAndroid Build Coastguard Worker // From Intel architecture-instruction-set-extensions-programming-reference:
169*795d594fSAndroid Build Coastguard Worker // EBX[31:0]/EAX[31:0] indicates the ratio of the TSC frequency and the
170*795d594fSAndroid Build Coastguard Worker // core crystal clock frequency.
171*795d594fSAndroid Build Coastguard Worker // If EBX[31:0] is 0, the TSC and "core crystal clock" ratio is not enumerated.
172*795d594fSAndroid Build Coastguard Worker // If ECX is 0, the nominal core crystal clock frequency is not enumerated.
173*795d594fSAndroid Build Coastguard Worker // "TSC frequency" = "core crystal clock frequency" * EBX/EAX.
174*795d594fSAndroid Build Coastguard Worker // The core crystal clock may differ from the reference clock, bus clock, or core clock
175*795d594fSAndroid Build Coastguard Worker // frequencies.
176*795d594fSAndroid Build Coastguard Worker // EAX Bits 31 - 00: An unsigned integer which is the denominator of the
177*795d594fSAndroid Build Coastguard Worker // TSC/"core crystal clock" ratio.
178*795d594fSAndroid Build Coastguard Worker // EBX Bits 31 - 00: An unsigned integer which is the numerator of the
179*795d594fSAndroid Build Coastguard Worker // TSC/"core crystal clock" ratio.
180*795d594fSAndroid Build Coastguard Worker // ECX Bits 31 - 00: An unsigned integer which is the nominal frequency of the core
181*795d594fSAndroid Build Coastguard Worker // crystal clock in Hz.
182*795d594fSAndroid Build Coastguard Worker // EDX Bits 31 - 00: Reserved = 0.
183*795d594fSAndroid Build Coastguard Worker asm volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx) : "a"(0x15), "c"(0));
184*795d594fSAndroid Build Coastguard Worker if (ebx == 0 || ecx == 0) {
185*795d594fSAndroid Build Coastguard Worker return computeScalingFactor();
186*795d594fSAndroid Build Coastguard Worker }
187*795d594fSAndroid Build Coastguard Worker double coreCrystalFreq = ecx;
188*795d594fSAndroid Build Coastguard Worker // frequency = coreCrystalFreq * (ebx / eax)
189*795d594fSAndroid Build Coastguard Worker // scaling_factor = seconds_to_microseconds / frequency
190*795d594fSAndroid Build Coastguard Worker // = seconds_to_microseconds * eax / (coreCrystalFreq * ebx)
191*795d594fSAndroid Build Coastguard Worker double seconds_to_microseconds = 1000 * 1000;
192*795d594fSAndroid Build Coastguard Worker double scaling_factor = (seconds_to_microseconds * eax) / (coreCrystalFreq * ebx);
193*795d594fSAndroid Build Coastguard Worker return scaling_factor;
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker #endif
196*795d594fSAndroid Build Coastguard Worker
InitializeTimestampCounters()197*795d594fSAndroid Build Coastguard Worker void InitializeTimestampCounters() {
198*795d594fSAndroid Build Coastguard Worker // It is sufficient to initialize this once for the entire execution. Just return if it is
199*795d594fSAndroid Build Coastguard Worker // already initialized.
200*795d594fSAndroid Build Coastguard Worker if (tsc_to_microsec_scaling_factor > 0.0) {
201*795d594fSAndroid Build Coastguard Worker return;
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker
204*795d594fSAndroid Build Coastguard Worker #if defined(__arm__)
205*795d594fSAndroid Build Coastguard Worker // On ARM 32 bit, we don't always have access to the timestamp counters from
206*795d594fSAndroid Build Coastguard Worker // user space. Seem comment in GetTimestamp for more details.
207*795d594fSAndroid Build Coastguard Worker tsc_to_microsec_scaling_factor = 1.0;
208*795d594fSAndroid Build Coastguard Worker #elif defined(__aarch64__)
209*795d594fSAndroid Build Coastguard Worker double seconds_to_microseconds = 1000 * 1000;
210*795d594fSAndroid Build Coastguard Worker uint64_t freq = 0;
211*795d594fSAndroid Build Coastguard Worker // See Arm Architecture Registers Armv8 section System Registers
212*795d594fSAndroid Build Coastguard Worker asm volatile("mrs %0, cntfrq_el0" : "=r"(freq));
213*795d594fSAndroid Build Coastguard Worker if (freq == 0) {
214*795d594fSAndroid Build Coastguard Worker // It is expected that cntfrq_el0 is correctly setup during system initialization but some
215*795d594fSAndroid Build Coastguard Worker // devices don't do this. In such cases fall back to computing the frequency. See b/315139000.
216*795d594fSAndroid Build Coastguard Worker tsc_to_microsec_scaling_factor = computeScalingFactor();
217*795d594fSAndroid Build Coastguard Worker } else {
218*795d594fSAndroid Build Coastguard Worker tsc_to_microsec_scaling_factor = seconds_to_microseconds / static_cast<double>(freq);
219*795d594fSAndroid Build Coastguard Worker }
220*795d594fSAndroid Build Coastguard Worker #elif defined(__i386__) || defined(__x86_64__)
221*795d594fSAndroid Build Coastguard Worker tsc_to_microsec_scaling_factor = GetScalingFactorForX86();
222*795d594fSAndroid Build Coastguard Worker #else
223*795d594fSAndroid Build Coastguard Worker tsc_to_microsec_scaling_factor = 1.0;
224*795d594fSAndroid Build Coastguard Worker #endif
225*795d594fSAndroid Build Coastguard Worker }
226*795d594fSAndroid Build Coastguard Worker
GetMicroTime(uint64_t counter)227*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE uint64_t GetMicroTime(uint64_t counter) {
228*795d594fSAndroid Build Coastguard Worker DCHECK(tsc_to_microsec_scaling_factor > 0.0) << tsc_to_microsec_scaling_factor;
229*795d594fSAndroid Build Coastguard Worker return tsc_to_microsec_scaling_factor * counter;
230*795d594fSAndroid Build Coastguard Worker }
231*795d594fSAndroid Build Coastguard Worker
GetClockSourceFromFlags(int flags)232*795d594fSAndroid Build Coastguard Worker TraceClockSource GetClockSourceFromFlags(int flags) {
233*795d594fSAndroid Build Coastguard Worker bool need_wall = flags & Trace::TraceFlag::kTraceClockSourceWallClock;
234*795d594fSAndroid Build Coastguard Worker bool need_thread_cpu = flags & Trace::TraceFlag::kTraceClockSourceThreadCpu;
235*795d594fSAndroid Build Coastguard Worker if (need_wall && need_thread_cpu) {
236*795d594fSAndroid Build Coastguard Worker return TraceClockSource::kDual;
237*795d594fSAndroid Build Coastguard Worker } else if (need_wall) {
238*795d594fSAndroid Build Coastguard Worker return TraceClockSource::kWall;
239*795d594fSAndroid Build Coastguard Worker } else if (need_thread_cpu) {
240*795d594fSAndroid Build Coastguard Worker return TraceClockSource::kThreadCpu;
241*795d594fSAndroid Build Coastguard Worker } else {
242*795d594fSAndroid Build Coastguard Worker return kDefaultTraceClockSource;
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker }
245*795d594fSAndroid Build Coastguard Worker
GetTraceFormatVersionFromFlags(int flags)246*795d594fSAndroid Build Coastguard Worker int GetTraceFormatVersionFromFlags(int flags) {
247*795d594fSAndroid Build Coastguard Worker int version = (flags & Trace::kTraceFormatVersionFlagMask) >> Trace::kTraceFormatVersionShift;
248*795d594fSAndroid Build Coastguard Worker return version;
249*795d594fSAndroid Build Coastguard Worker }
250*795d594fSAndroid Build Coastguard Worker
251*795d594fSAndroid Build Coastguard Worker } // namespace
252*795d594fSAndroid Build Coastguard Worker
253*795d594fSAndroid Build Coastguard Worker // Temporary code for debugging b/342768977
254*795d594fSAndroid Build Coastguard Worker int num_trace_starts_ GUARDED_BY(Locks::trace_lock_);
255*795d594fSAndroid Build Coastguard Worker int num_trace_stops_initiated_ GUARDED_BY(Locks::trace_lock_);
256*795d594fSAndroid Build Coastguard Worker std::atomic<int> num_trace_stops_finished_;
GetDebugInformation()257*795d594fSAndroid Build Coastguard Worker std::string Trace::GetDebugInformation() {
258*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
259*795d594fSAndroid Build Coastguard Worker std::stringstream debug_info;
260*795d594fSAndroid Build Coastguard Worker debug_info << "start:" << num_trace_starts_ << "stop:" << num_trace_stops_initiated_ << "done:"
261*795d594fSAndroid Build Coastguard Worker << num_trace_stops_finished_ << "trace:" << the_trace_;
262*795d594fSAndroid Build Coastguard Worker return debug_info.str();
263*795d594fSAndroid Build Coastguard Worker }
264*795d594fSAndroid Build Coastguard Worker
HasMethodEncoding(ArtMethod * method)265*795d594fSAndroid Build Coastguard Worker bool TraceWriter::HasMethodEncoding(ArtMethod* method) {
266*795d594fSAndroid Build Coastguard Worker return art_method_id_map_.find(method) != art_method_id_map_.end();
267*795d594fSAndroid Build Coastguard Worker }
268*795d594fSAndroid Build Coastguard Worker
GetMethodEncoding(ArtMethod * method)269*795d594fSAndroid Build Coastguard Worker std::pair<uint32_t, bool> TraceWriter::GetMethodEncoding(ArtMethod* method) {
270*795d594fSAndroid Build Coastguard Worker auto it = art_method_id_map_.find(method);
271*795d594fSAndroid Build Coastguard Worker if (it != art_method_id_map_.end()) {
272*795d594fSAndroid Build Coastguard Worker return std::pair<uint32_t, bool>(it->second, false);
273*795d594fSAndroid Build Coastguard Worker } else {
274*795d594fSAndroid Build Coastguard Worker uint32_t idx = current_method_index_;
275*795d594fSAndroid Build Coastguard Worker art_method_id_map_.emplace(method, idx);
276*795d594fSAndroid Build Coastguard Worker current_method_index_++;
277*795d594fSAndroid Build Coastguard Worker return std::pair<uint32_t, bool>(idx, true);
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker
GetThreadEncoding(pid_t thread_id)281*795d594fSAndroid Build Coastguard Worker uint16_t TraceWriter::GetThreadEncoding(pid_t thread_id) {
282*795d594fSAndroid Build Coastguard Worker auto it = thread_id_map_.find(thread_id);
283*795d594fSAndroid Build Coastguard Worker if (it != thread_id_map_.end()) {
284*795d594fSAndroid Build Coastguard Worker return it->second;
285*795d594fSAndroid Build Coastguard Worker }
286*795d594fSAndroid Build Coastguard Worker
287*795d594fSAndroid Build Coastguard Worker uint16_t idx = current_thread_index_;
288*795d594fSAndroid Build Coastguard Worker thread_id_map_.emplace(thread_id, current_thread_index_);
289*795d594fSAndroid Build Coastguard Worker DCHECK_LT(current_thread_index_, (1 << 16) - 2);
290*795d594fSAndroid Build Coastguard Worker current_thread_index_++;
291*795d594fSAndroid Build Coastguard Worker return idx;
292*795d594fSAndroid Build Coastguard Worker }
293*795d594fSAndroid Build Coastguard Worker
294*795d594fSAndroid Build Coastguard Worker class TraceWriterTask : public SelfDeletingTask {
295*795d594fSAndroid Build Coastguard Worker public:
TraceWriterTask(TraceWriter * trace_writer,int index,uintptr_t * buffer,size_t cur_offset,size_t thread_id)296*795d594fSAndroid Build Coastguard Worker TraceWriterTask(
297*795d594fSAndroid Build Coastguard Worker TraceWriter* trace_writer, int index, uintptr_t* buffer, size_t cur_offset, size_t thread_id)
298*795d594fSAndroid Build Coastguard Worker : trace_writer_(trace_writer),
299*795d594fSAndroid Build Coastguard Worker index_(index),
300*795d594fSAndroid Build Coastguard Worker buffer_(buffer),
301*795d594fSAndroid Build Coastguard Worker cur_offset_(cur_offset),
302*795d594fSAndroid Build Coastguard Worker thread_id_(thread_id) {}
303*795d594fSAndroid Build Coastguard Worker
Run(Thread * self ATTRIBUTE_UNUSED)304*795d594fSAndroid Build Coastguard Worker void Run(Thread* self ATTRIBUTE_UNUSED) override {
305*795d594fSAndroid Build Coastguard Worker ProcessBuffer(buffer_, cur_offset_, thread_id_);
306*795d594fSAndroid Build Coastguard Worker if (index_ == -1) {
307*795d594fSAndroid Build Coastguard Worker // This was a temporary buffer we allocated since there are no free buffers and it wasn't
308*795d594fSAndroid Build Coastguard Worker // safe to wait for one. This should only happen when we have fewer buffers than the number
309*795d594fSAndroid Build Coastguard Worker // of threads.
310*795d594fSAndroid Build Coastguard Worker delete[] buffer_;
311*795d594fSAndroid Build Coastguard Worker }
312*795d594fSAndroid Build Coastguard Worker trace_writer_->ReleaseBuffer(index_);
313*795d594fSAndroid Build Coastguard Worker }
314*795d594fSAndroid Build Coastguard Worker
315*795d594fSAndroid Build Coastguard Worker virtual void ProcessBuffer(uintptr_t* buffer, size_t cur_offset, size_t thread_id) = 0;
316*795d594fSAndroid Build Coastguard Worker
GetTraceWriter()317*795d594fSAndroid Build Coastguard Worker TraceWriter* GetTraceWriter() { return trace_writer_; }
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker private:
320*795d594fSAndroid Build Coastguard Worker TraceWriter* trace_writer_;
321*795d594fSAndroid Build Coastguard Worker int index_;
322*795d594fSAndroid Build Coastguard Worker uintptr_t* buffer_;
323*795d594fSAndroid Build Coastguard Worker size_t cur_offset_;
324*795d594fSAndroid Build Coastguard Worker size_t thread_id_;
325*795d594fSAndroid Build Coastguard Worker };
326*795d594fSAndroid Build Coastguard Worker
327*795d594fSAndroid Build Coastguard Worker class TraceEntriesWriterTask final : public TraceWriterTask {
328*795d594fSAndroid Build Coastguard Worker public:
TraceEntriesWriterTask(TraceWriter * trace_writer,int index,uintptr_t * buffer,size_t cur_offset,size_t tid)329*795d594fSAndroid Build Coastguard Worker TraceEntriesWriterTask(
330*795d594fSAndroid Build Coastguard Worker TraceWriter* trace_writer, int index, uintptr_t* buffer, size_t cur_offset, size_t tid)
331*795d594fSAndroid Build Coastguard Worker : TraceWriterTask(trace_writer, index, buffer, cur_offset, tid) {}
332*795d594fSAndroid Build Coastguard Worker
ProcessBuffer(uintptr_t * buffer,size_t cur_offset,size_t thread_id)333*795d594fSAndroid Build Coastguard Worker void ProcessBuffer(uintptr_t* buffer, size_t cur_offset, size_t thread_id) override {
334*795d594fSAndroid Build Coastguard Worker std::unordered_map<ArtMethod*, std::string> method_infos;
335*795d594fSAndroid Build Coastguard Worker TraceWriter* trace_writer = GetTraceWriter();
336*795d594fSAndroid Build Coastguard Worker if (trace_writer->GetTraceFormatVersion() == Trace::kFormatV1) {
337*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
338*795d594fSAndroid Build Coastguard Worker trace_writer->PreProcessTraceForMethodInfos(buffer, cur_offset, method_infos);
339*795d594fSAndroid Build Coastguard Worker }
340*795d594fSAndroid Build Coastguard Worker trace_writer->FlushBuffer(buffer, cur_offset, thread_id, method_infos);
341*795d594fSAndroid Build Coastguard Worker }
342*795d594fSAndroid Build Coastguard Worker };
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker class MethodInfoWriterTask final : public TraceWriterTask {
345*795d594fSAndroid Build Coastguard Worker public:
MethodInfoWriterTask(TraceWriter * trace_writer,int index,uintptr_t * buffer,size_t cur_offset)346*795d594fSAndroid Build Coastguard Worker MethodInfoWriterTask(TraceWriter* trace_writer, int index, uintptr_t* buffer, size_t cur_offset)
347*795d594fSAndroid Build Coastguard Worker : TraceWriterTask(trace_writer, index, buffer, cur_offset, 0) {}
348*795d594fSAndroid Build Coastguard Worker
ProcessBuffer(uintptr_t * buffer,size_t cur_offset,size_t thread_id)349*795d594fSAndroid Build Coastguard Worker void ProcessBuffer(uintptr_t* buffer,
350*795d594fSAndroid Build Coastguard Worker size_t cur_offset,
351*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] size_t thread_id) override {
352*795d594fSAndroid Build Coastguard Worker GetTraceWriter()->WriteToFile(reinterpret_cast<uint8_t*>(buffer), cur_offset);
353*795d594fSAndroid Build Coastguard Worker }
354*795d594fSAndroid Build Coastguard Worker };
355*795d594fSAndroid Build Coastguard Worker
AllocStackTrace()356*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*>* Trace::AllocStackTrace() {
357*795d594fSAndroid Build Coastguard Worker return (temp_stack_trace_.get() != nullptr) ? temp_stack_trace_.release() :
358*795d594fSAndroid Build Coastguard Worker new std::vector<ArtMethod*>();
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker
FreeStackTrace(std::vector<ArtMethod * > * stack_trace)361*795d594fSAndroid Build Coastguard Worker void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
362*795d594fSAndroid Build Coastguard Worker stack_trace->clear();
363*795d594fSAndroid Build Coastguard Worker temp_stack_trace_.reset(stack_trace);
364*795d594fSAndroid Build Coastguard Worker }
365*795d594fSAndroid Build Coastguard Worker
GetTraceVersion(TraceClockSource clock_source,int version)366*795d594fSAndroid Build Coastguard Worker static uint16_t GetTraceVersion(TraceClockSource clock_source, int version) {
367*795d594fSAndroid Build Coastguard Worker if (version == Trace::kFormatV1) {
368*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClock :
369*795d594fSAndroid Build Coastguard Worker kTraceVersionSingleClock;
370*795d594fSAndroid Build Coastguard Worker } else {
371*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kDual) ? kTraceVersionDualClockV2 :
372*795d594fSAndroid Build Coastguard Worker kTraceVersionSingleClockV2;
373*795d594fSAndroid Build Coastguard Worker }
374*795d594fSAndroid Build Coastguard Worker }
375*795d594fSAndroid Build Coastguard Worker
GetRecordSize(TraceClockSource clock_source,int version)376*795d594fSAndroid Build Coastguard Worker static uint16_t GetRecordSize(TraceClockSource clock_source, int version) {
377*795d594fSAndroid Build Coastguard Worker if (version == Trace::kFormatV1) {
378*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClock :
379*795d594fSAndroid Build Coastguard Worker kTraceRecordSizeSingleClock;
380*795d594fSAndroid Build Coastguard Worker } else {
381*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kDual) ? kTraceRecordSizeDualClockV2 :
382*795d594fSAndroid Build Coastguard Worker kTraceRecordSizeSingleClockV2;
383*795d594fSAndroid Build Coastguard Worker }
384*795d594fSAndroid Build Coastguard Worker }
385*795d594fSAndroid Build Coastguard Worker
GetNumEntries(TraceClockSource clock_source)386*795d594fSAndroid Build Coastguard Worker static uint16_t GetNumEntries(TraceClockSource clock_source) {
387*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kDual) ? kNumEntriesForDualClock
388*795d594fSAndroid Build Coastguard Worker : kNumEntriesForWallClock;
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker
UseThreadCpuClock(TraceClockSource clock_source)391*795d594fSAndroid Build Coastguard Worker bool UseThreadCpuClock(TraceClockSource clock_source) {
392*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kThreadCpu) ||
393*795d594fSAndroid Build Coastguard Worker (clock_source == TraceClockSource::kDual);
394*795d594fSAndroid Build Coastguard Worker }
395*795d594fSAndroid Build Coastguard Worker
UseWallClock(TraceClockSource clock_source)396*795d594fSAndroid Build Coastguard Worker bool UseWallClock(TraceClockSource clock_source) {
397*795d594fSAndroid Build Coastguard Worker return (clock_source == TraceClockSource::kWall) || (clock_source == TraceClockSource::kDual);
398*795d594fSAndroid Build Coastguard Worker }
399*795d594fSAndroid Build Coastguard Worker
UseFastTraceListeners(TraceClockSource clock_source)400*795d594fSAndroid Build Coastguard Worker bool UseFastTraceListeners(TraceClockSource clock_source) {
401*795d594fSAndroid Build Coastguard Worker // Thread cpu clocks needs a kernel call, so we don't directly support them in JITed code.
402*795d594fSAndroid Build Coastguard Worker bool is_fast_trace = !UseThreadCpuClock(clock_source);
403*795d594fSAndroid Build Coastguard Worker #if defined(__arm__)
404*795d594fSAndroid Build Coastguard Worker // On ARM 32 bit, we don't always have access to the timestamp counters from
405*795d594fSAndroid Build Coastguard Worker // user space. See comment in GetTimestamp for more details.
406*795d594fSAndroid Build Coastguard Worker is_fast_trace = false;
407*795d594fSAndroid Build Coastguard Worker #endif
408*795d594fSAndroid Build Coastguard Worker return is_fast_trace;
409*795d594fSAndroid Build Coastguard Worker }
410*795d594fSAndroid Build Coastguard Worker
MeasureClockOverhead()411*795d594fSAndroid Build Coastguard Worker void Trace::MeasureClockOverhead() {
412*795d594fSAndroid Build Coastguard Worker if (UseThreadCpuClock(clock_source_)) {
413*795d594fSAndroid Build Coastguard Worker Thread::Current()->GetCpuMicroTime();
414*795d594fSAndroid Build Coastguard Worker }
415*795d594fSAndroid Build Coastguard Worker if (UseWallClock(clock_source_)) {
416*795d594fSAndroid Build Coastguard Worker GetTimestamp();
417*795d594fSAndroid Build Coastguard Worker }
418*795d594fSAndroid Build Coastguard Worker }
419*795d594fSAndroid Build Coastguard Worker
420*795d594fSAndroid Build Coastguard Worker // Compute an average time taken to measure clocks.
GetClockOverheadNanoSeconds()421*795d594fSAndroid Build Coastguard Worker uint32_t Trace::GetClockOverheadNanoSeconds() {
422*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
423*795d594fSAndroid Build Coastguard Worker uint64_t start = self->GetCpuMicroTime();
424*795d594fSAndroid Build Coastguard Worker
425*795d594fSAndroid Build Coastguard Worker for (int i = 4000; i > 0; i--) {
426*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
427*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
428*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
429*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
430*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
431*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
432*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
433*795d594fSAndroid Build Coastguard Worker MeasureClockOverhead();
434*795d594fSAndroid Build Coastguard Worker }
435*795d594fSAndroid Build Coastguard Worker
436*795d594fSAndroid Build Coastguard Worker uint64_t elapsed_us = self->GetCpuMicroTime() - start;
437*795d594fSAndroid Build Coastguard Worker return static_cast<uint32_t>(elapsed_us / 32);
438*795d594fSAndroid Build Coastguard Worker }
439*795d594fSAndroid Build Coastguard Worker
GetSample(Thread * thread,void * arg)440*795d594fSAndroid Build Coastguard Worker static void GetSample(Thread* thread, void* arg) REQUIRES_SHARED(Locks::mutator_lock_) {
441*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*>* const stack_trace = Trace::AllocStackTrace();
442*795d594fSAndroid Build Coastguard Worker StackVisitor::WalkStack(
443*795d594fSAndroid Build Coastguard Worker [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
444*795d594fSAndroid Build Coastguard Worker ArtMethod* m = stack_visitor->GetMethod();
445*795d594fSAndroid Build Coastguard Worker // Ignore runtime frames (in particular callee save).
446*795d594fSAndroid Build Coastguard Worker if (!m->IsRuntimeMethod()) {
447*795d594fSAndroid Build Coastguard Worker stack_trace->push_back(m);
448*795d594fSAndroid Build Coastguard Worker }
449*795d594fSAndroid Build Coastguard Worker return true;
450*795d594fSAndroid Build Coastguard Worker },
451*795d594fSAndroid Build Coastguard Worker thread,
452*795d594fSAndroid Build Coastguard Worker /* context= */ nullptr,
453*795d594fSAndroid Build Coastguard Worker art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
454*795d594fSAndroid Build Coastguard Worker Trace* the_trace = reinterpret_cast<Trace*>(arg);
455*795d594fSAndroid Build Coastguard Worker the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker
ClearThreadStackTraceAndClockBase(Thread * thread,void * arg)458*795d594fSAndroid Build Coastguard Worker static void ClearThreadStackTraceAndClockBase(Thread* thread, [[maybe_unused]] void* arg) {
459*795d594fSAndroid Build Coastguard Worker thread->SetTraceClockBase(0);
460*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample();
461*795d594fSAndroid Build Coastguard Worker thread->SetStackTraceSample(nullptr);
462*795d594fSAndroid Build Coastguard Worker delete stack_trace;
463*795d594fSAndroid Build Coastguard Worker }
464*795d594fSAndroid Build Coastguard Worker
CompareAndUpdateStackTrace(Thread * thread,std::vector<ArtMethod * > * stack_trace)465*795d594fSAndroid Build Coastguard Worker void Trace::CompareAndUpdateStackTrace(Thread* thread,
466*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*>* stack_trace) {
467*795d594fSAndroid Build Coastguard Worker CHECK_EQ(pthread_self(), sampling_pthread_);
468*795d594fSAndroid Build Coastguard Worker std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
469*795d594fSAndroid Build Coastguard Worker // Update the thread's stack trace sample.
470*795d594fSAndroid Build Coastguard Worker thread->SetStackTraceSample(stack_trace);
471*795d594fSAndroid Build Coastguard Worker // Read timer clocks to use for all events in this trace.
472*795d594fSAndroid Build Coastguard Worker uint32_t thread_clock_diff = 0;
473*795d594fSAndroid Build Coastguard Worker uint64_t timestamp_counter = 0;
474*795d594fSAndroid Build Coastguard Worker ReadClocks(thread, &thread_clock_diff, ×tamp_counter);
475*795d594fSAndroid Build Coastguard Worker if (old_stack_trace == nullptr) {
476*795d594fSAndroid Build Coastguard Worker // If there's no previous stack trace sample for this thread, log an entry event for all
477*795d594fSAndroid Build Coastguard Worker // methods in the trace.
478*795d594fSAndroid Build Coastguard Worker for (auto rit = stack_trace->rbegin(); rit != stack_trace->rend(); ++rit) {
479*795d594fSAndroid Build Coastguard Worker LogMethodTraceEvent(thread, *rit, kTraceMethodEnter, thread_clock_diff, timestamp_counter);
480*795d594fSAndroid Build Coastguard Worker }
481*795d594fSAndroid Build Coastguard Worker } else {
482*795d594fSAndroid Build Coastguard Worker // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
483*795d594fSAndroid Build Coastguard Worker // events accordingly.
484*795d594fSAndroid Build Coastguard Worker auto old_rit = old_stack_trace->rbegin();
485*795d594fSAndroid Build Coastguard Worker auto rit = stack_trace->rbegin();
486*795d594fSAndroid Build Coastguard Worker // Iterate bottom-up over both traces until there's a difference between them.
487*795d594fSAndroid Build Coastguard Worker while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
488*795d594fSAndroid Build Coastguard Worker old_rit++;
489*795d594fSAndroid Build Coastguard Worker rit++;
490*795d594fSAndroid Build Coastguard Worker }
491*795d594fSAndroid Build Coastguard Worker // Iterate top-down over the old trace until the point where they differ, emitting exit events.
492*795d594fSAndroid Build Coastguard Worker for (auto old_it = old_stack_trace->begin(); old_it != old_rit.base(); ++old_it) {
493*795d594fSAndroid Build Coastguard Worker LogMethodTraceEvent(thread, *old_it, kTraceMethodExit, thread_clock_diff, timestamp_counter);
494*795d594fSAndroid Build Coastguard Worker }
495*795d594fSAndroid Build Coastguard Worker // Iterate bottom-up over the new trace from the point where they differ, emitting entry events.
496*795d594fSAndroid Build Coastguard Worker for (; rit != stack_trace->rend(); ++rit) {
497*795d594fSAndroid Build Coastguard Worker LogMethodTraceEvent(thread, *rit, kTraceMethodEnter, thread_clock_diff, timestamp_counter);
498*795d594fSAndroid Build Coastguard Worker }
499*795d594fSAndroid Build Coastguard Worker FreeStackTrace(old_stack_trace);
500*795d594fSAndroid Build Coastguard Worker }
501*795d594fSAndroid Build Coastguard Worker }
502*795d594fSAndroid Build Coastguard Worker
RunSamplingThread(void * arg)503*795d594fSAndroid Build Coastguard Worker void* Trace::RunSamplingThread(void* arg) {
504*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
505*795d594fSAndroid Build Coastguard Worker intptr_t interval_us = reinterpret_cast<intptr_t>(arg);
506*795d594fSAndroid Build Coastguard Worker CHECK_GE(interval_us, 0);
507*795d594fSAndroid Build Coastguard Worker CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(),
508*795d594fSAndroid Build Coastguard Worker !runtime->IsAotCompiler()));
509*795d594fSAndroid Build Coastguard Worker
510*795d594fSAndroid Build Coastguard Worker while (true) {
511*795d594fSAndroid Build Coastguard Worker usleep(interval_us);
512*795d594fSAndroid Build Coastguard Worker ScopedTrace trace("Profile sampling");
513*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
514*795d594fSAndroid Build Coastguard Worker Trace* the_trace;
515*795d594fSAndroid Build Coastguard Worker {
516*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
517*795d594fSAndroid Build Coastguard Worker the_trace = the_trace_;
518*795d594fSAndroid Build Coastguard Worker if (the_trace_->stop_tracing_) {
519*795d594fSAndroid Build Coastguard Worker break;
520*795d594fSAndroid Build Coastguard Worker }
521*795d594fSAndroid Build Coastguard Worker }
522*795d594fSAndroid Build Coastguard Worker {
523*795d594fSAndroid Build Coastguard Worker // Avoid a deadlock between a thread doing garbage collection
524*795d594fSAndroid Build Coastguard Worker // and the profile sampling thread, by blocking GC when sampling
525*795d594fSAndroid Build Coastguard Worker // thread stacks (see b/73624630).
526*795d594fSAndroid Build Coastguard Worker gc::ScopedGCCriticalSection gcs(self,
527*795d594fSAndroid Build Coastguard Worker art::gc::kGcCauseInstrumentation,
528*795d594fSAndroid Build Coastguard Worker art::gc::kCollectorTypeInstrumentation);
529*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa(__FUNCTION__);
530*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::thread_list_lock_);
531*795d594fSAndroid Build Coastguard Worker runtime->GetThreadList()->ForEach(GetSample, the_trace);
532*795d594fSAndroid Build Coastguard Worker }
533*795d594fSAndroid Build Coastguard Worker }
534*795d594fSAndroid Build Coastguard Worker
535*795d594fSAndroid Build Coastguard Worker runtime->DetachCurrentThread();
536*795d594fSAndroid Build Coastguard Worker return nullptr;
537*795d594fSAndroid Build Coastguard Worker }
538*795d594fSAndroid Build Coastguard Worker
539*795d594fSAndroid Build Coastguard Worker // Visitor used to record all methods currently loaded in the runtime. This is done at the start of
540*795d594fSAndroid Build Coastguard Worker // method tracing.
541*795d594fSAndroid Build Coastguard Worker class RecordMethodInfoClassVisitor : public ClassVisitor {
542*795d594fSAndroid Build Coastguard Worker public:
RecordMethodInfoClassVisitor(Trace * trace)543*795d594fSAndroid Build Coastguard Worker explicit RecordMethodInfoClassVisitor(Trace* trace)
544*795d594fSAndroid Build Coastguard Worker : trace_(trace), offset_(0), buffer_(nullptr) {}
545*795d594fSAndroid Build Coastguard Worker
operator ()(ObjPtr<mirror::Class> klass)546*795d594fSAndroid Build Coastguard Worker bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES(Locks::mutator_lock_) {
547*795d594fSAndroid Build Coastguard Worker // We use a buffer to aggregate method infos from different classes to avoid multiple small
548*795d594fSAndroid Build Coastguard Worker // writes to the file. The RecordMethodInfo handles the overflows by enqueueing a task to
549*795d594fSAndroid Build Coastguard Worker // flush the old buffer and allocates a new buffer.
550*795d594fSAndroid Build Coastguard Worker trace_->GetTraceWriter()->RecordMethodInfoV2(klass.Ptr(), &buffer_, &offset_);
551*795d594fSAndroid Build Coastguard Worker return true; // Visit all classes.
552*795d594fSAndroid Build Coastguard Worker }
553*795d594fSAndroid Build Coastguard Worker
FlushBuffer()554*795d594fSAndroid Build Coastguard Worker void FlushBuffer() REQUIRES_SHARED(Locks::mutator_lock_) {
555*795d594fSAndroid Build Coastguard Worker // Flushes any data in the buffer to the file. Called at the end of visit to write any
556*795d594fSAndroid Build Coastguard Worker // remaining data to the file.
557*795d594fSAndroid Build Coastguard Worker trace_->GetTraceWriter()->AddMethodInfoWriteTask(
558*795d594fSAndroid Build Coastguard Worker buffer_, offset_, Thread::Current()->GetTid(), true);
559*795d594fSAndroid Build Coastguard Worker }
560*795d594fSAndroid Build Coastguard Worker
561*795d594fSAndroid Build Coastguard Worker private:
562*795d594fSAndroid Build Coastguard Worker Trace* const trace_;
563*795d594fSAndroid Build Coastguard Worker // Use a buffer to aggregate method infos of all classes to avoid multiple smaller writes to file.
564*795d594fSAndroid Build Coastguard Worker size_t offset_ = 0;
565*795d594fSAndroid Build Coastguard Worker uint8_t* buffer_ = nullptr;
566*795d594fSAndroid Build Coastguard Worker };
567*795d594fSAndroid Build Coastguard Worker
ClassPrepare(Handle<mirror::Class> temp_klass,Handle<mirror::Class> klass)568*795d594fSAndroid Build Coastguard Worker void Trace::ClassPrepare([[maybe_unused]] Handle<mirror::Class> temp_klass,
569*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> klass) {
570*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
571*795d594fSAndroid Build Coastguard Worker if (the_trace_ == nullptr) {
572*795d594fSAndroid Build Coastguard Worker return;
573*795d594fSAndroid Build Coastguard Worker }
574*795d594fSAndroid Build Coastguard Worker size_t offset = 0;
575*795d594fSAndroid Build Coastguard Worker size_t tid = Thread::Current()->GetTid();
576*795d594fSAndroid Build Coastguard Worker uint8_t* buffer = nullptr;
577*795d594fSAndroid Build Coastguard Worker // Write the method infos of the newly loaded class.
578*795d594fSAndroid Build Coastguard Worker the_trace_->GetTraceWriter()->RecordMethodInfoV2(klass.Get(), &buffer, &offset);
579*795d594fSAndroid Build Coastguard Worker the_trace_->GetTraceWriter()->AddMethodInfoWriteTask(buffer, offset, tid, true);
580*795d594fSAndroid Build Coastguard Worker }
581*795d594fSAndroid Build Coastguard Worker
AddMethodInfoWriteTask(uint8_t * buffer,size_t offset,size_t tid,bool release)582*795d594fSAndroid Build Coastguard Worker uint8_t* TraceWriter::AddMethodInfoWriteTask(uint8_t* buffer,
583*795d594fSAndroid Build Coastguard Worker size_t offset,
584*795d594fSAndroid Build Coastguard Worker size_t tid,
585*795d594fSAndroid Build Coastguard Worker bool release) {
586*795d594fSAndroid Build Coastguard Worker int old_index = GetMethodTraceIndex(reinterpret_cast<uintptr_t*>(buffer));
587*795d594fSAndroid Build Coastguard Worker uintptr_t* new_buf = nullptr;
588*795d594fSAndroid Build Coastguard Worker thread_pool_->AddTask(
589*795d594fSAndroid Build Coastguard Worker Thread::Current(),
590*795d594fSAndroid Build Coastguard Worker new MethodInfoWriterTask(this, old_index, reinterpret_cast<uintptr_t*>(buffer), offset));
591*795d594fSAndroid Build Coastguard Worker if (!release) {
592*795d594fSAndroid Build Coastguard Worker new_buf = AcquireTraceBuffer(tid);
593*795d594fSAndroid Build Coastguard Worker }
594*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<uint8_t*>(new_buf);
595*795d594fSAndroid Build Coastguard Worker }
596*795d594fSAndroid Build Coastguard Worker
WriteToFile(uint8_t * buffer,size_t offset)597*795d594fSAndroid Build Coastguard Worker void TraceWriter::WriteToFile(uint8_t* buffer, size_t offset) {
598*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
599*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buffer, offset)) {
600*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
601*795d594fSAndroid Build Coastguard Worker }
602*795d594fSAndroid Build Coastguard Worker }
603*795d594fSAndroid Build Coastguard Worker
RecordMethodInfoV2(mirror::Class * klass,uint8_t ** buffer,size_t * offset)604*795d594fSAndroid Build Coastguard Worker void TraceWriter::RecordMethodInfoV2(mirror::Class* klass, uint8_t** buffer, size_t* offset) {
605*795d594fSAndroid Build Coastguard Worker // For the v1 format, we record methods when we first execute them.
606*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(trace_format_version_, Trace::kFormatV2);
607*795d594fSAndroid Build Coastguard Worker
608*795d594fSAndroid Build Coastguard Worker auto methods = klass->GetMethods(kRuntimePointerSize);
609*795d594fSAndroid Build Coastguard Worker if (methods.empty()) {
610*795d594fSAndroid Build Coastguard Worker return;
611*795d594fSAndroid Build Coastguard Worker }
612*795d594fSAndroid Build Coastguard Worker
613*795d594fSAndroid Build Coastguard Worker size_t tid = Thread::Current()->GetTid();
614*795d594fSAndroid Build Coastguard Worker size_t buffer_size = kPerThreadBufSize * sizeof(uintptr_t);
615*795d594fSAndroid Build Coastguard Worker size_t index = *offset;
616*795d594fSAndroid Build Coastguard Worker uint8_t* buf = *buffer;
617*795d594fSAndroid Build Coastguard Worker if (buf == nullptr) {
618*795d594fSAndroid Build Coastguard Worker buf = reinterpret_cast<uint8_t*>(AcquireTraceBuffer(tid));
619*795d594fSAndroid Build Coastguard Worker }
620*795d594fSAndroid Build Coastguard Worker
621*795d594fSAndroid Build Coastguard Worker std::string class_name_current = klass->PrettyDescriptor();
622*795d594fSAndroid Build Coastguard Worker const char* source_file_current = klass->GetSourceFile();
623*795d594fSAndroid Build Coastguard Worker if (source_file_current == nullptr) {
624*795d594fSAndroid Build Coastguard Worker // Generated classes have no source file.
625*795d594fSAndroid Build Coastguard Worker source_file_current = "";
626*795d594fSAndroid Build Coastguard Worker }
627*795d594fSAndroid Build Coastguard Worker for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) {
628*795d594fSAndroid Build Coastguard Worker if (!method.IsInvokable()) {
629*795d594fSAndroid Build Coastguard Worker continue;
630*795d594fSAndroid Build Coastguard Worker }
631*795d594fSAndroid Build Coastguard Worker
632*795d594fSAndroid Build Coastguard Worker std::string class_name;
633*795d594fSAndroid Build Coastguard Worker const char* source_file;
634*795d594fSAndroid Build Coastguard Worker if (method.IsCopied()) {
635*795d594fSAndroid Build Coastguard Worker // For copied methods use method's declaring class which may not be the current class.
636*795d594fSAndroid Build Coastguard Worker class_name = method.GetDeclaringClass()->PrettyDescriptor();
637*795d594fSAndroid Build Coastguard Worker source_file = method.GetDeclaringClass()->GetSourceFile();
638*795d594fSAndroid Build Coastguard Worker } else {
639*795d594fSAndroid Build Coastguard Worker DCHECK(klass == method.GetDeclaringClass());
640*795d594fSAndroid Build Coastguard Worker class_name = class_name_current;
641*795d594fSAndroid Build Coastguard Worker source_file = source_file_current;
642*795d594fSAndroid Build Coastguard Worker }
643*795d594fSAndroid Build Coastguard Worker int class_name_len = class_name.length();
644*795d594fSAndroid Build Coastguard Worker int source_file_len = strlen(source_file);
645*795d594fSAndroid Build Coastguard Worker
646*795d594fSAndroid Build Coastguard Worker uint64_t method_id = reinterpret_cast<uint64_t>(&method);
647*795d594fSAndroid Build Coastguard Worker // TODO(mythria): Change how we report method infos in V2 to reduce the
648*795d594fSAndroid Build Coastguard Worker // repetition of the information about class and the source file.
649*795d594fSAndroid Build Coastguard Worker const char* name = method.GetName();
650*795d594fSAndroid Build Coastguard Worker int name_len = strlen(name);
651*795d594fSAndroid Build Coastguard Worker std::string signature = method.GetSignature().ToString();
652*795d594fSAndroid Build Coastguard Worker int signature_len = signature.length();
653*795d594fSAndroid Build Coastguard Worker // We need 3 tabs in between and a \n at the end and hence 4 additional characters.
654*795d594fSAndroid Build Coastguard Worker int method_info_length = class_name_len + name_len + signature_len + source_file_len + 4;
655*795d594fSAndroid Build Coastguard Worker // 1 byte header + 8 bytes method id + 2 bytes method_info_length
656*795d594fSAndroid Build Coastguard Worker int header_length = 11;
657*795d594fSAndroid Build Coastguard Worker if (index + header_length + method_info_length >= buffer_size) {
658*795d594fSAndroid Build Coastguard Worker buf = AddMethodInfoWriteTask(buf, index, tid, false);
659*795d594fSAndroid Build Coastguard Worker index = 0;
660*795d594fSAndroid Build Coastguard Worker }
661*795d594fSAndroid Build Coastguard Worker // Write the header to the buffer
662*795d594fSAndroid Build Coastguard Worker buf[index] = kMethodInfoHeaderV2;
663*795d594fSAndroid Build Coastguard Worker Append8LE(buf + index + 1, method_id);
664*795d594fSAndroid Build Coastguard Worker Append2LE(buf + index + 9, method_info_length);
665*795d594fSAndroid Build Coastguard Worker index += header_length;
666*795d594fSAndroid Build Coastguard Worker
667*795d594fSAndroid Build Coastguard Worker // Copy method line into the buffer
668*795d594fSAndroid Build Coastguard Worker memcpy(buf + index, class_name.c_str(), class_name_len);
669*795d594fSAndroid Build Coastguard Worker buf[index + class_name_len] = '\t';
670*795d594fSAndroid Build Coastguard Worker index += class_name_len + 1;
671*795d594fSAndroid Build Coastguard Worker memcpy(buf + index, name, name_len);
672*795d594fSAndroid Build Coastguard Worker buf[index + name_len] = '\t';
673*795d594fSAndroid Build Coastguard Worker index += name_len + 1;
674*795d594fSAndroid Build Coastguard Worker memcpy(buf + index, signature.c_str(), signature_len);
675*795d594fSAndroid Build Coastguard Worker buf[index + signature_len] = '\t';
676*795d594fSAndroid Build Coastguard Worker index += signature_len + 1;
677*795d594fSAndroid Build Coastguard Worker memcpy(buf + index, source_file, source_file_len);
678*795d594fSAndroid Build Coastguard Worker buf[index + source_file_len] = '\n';
679*795d594fSAndroid Build Coastguard Worker index += source_file_len + 1;
680*795d594fSAndroid Build Coastguard Worker }
681*795d594fSAndroid Build Coastguard Worker *offset = index;
682*795d594fSAndroid Build Coastguard Worker *buffer = buf;
683*795d594fSAndroid Build Coastguard Worker }
684*795d594fSAndroid Build Coastguard Worker
Start(const char * trace_filename,size_t buffer_size,int flags,TraceOutputMode output_mode,TraceMode trace_mode,int interval_us)685*795d594fSAndroid Build Coastguard Worker void Trace::Start(const char* trace_filename,
686*795d594fSAndroid Build Coastguard Worker size_t buffer_size,
687*795d594fSAndroid Build Coastguard Worker int flags,
688*795d594fSAndroid Build Coastguard Worker TraceOutputMode output_mode,
689*795d594fSAndroid Build Coastguard Worker TraceMode trace_mode,
690*795d594fSAndroid Build Coastguard Worker int interval_us) {
691*795d594fSAndroid Build Coastguard Worker std::unique_ptr<File> file(OS::CreateEmptyFileWriteOnly(trace_filename));
692*795d594fSAndroid Build Coastguard Worker if (file == nullptr) {
693*795d594fSAndroid Build Coastguard Worker std::string msg = android::base::StringPrintf("Unable to open trace file '%s'", trace_filename);
694*795d594fSAndroid Build Coastguard Worker PLOG(ERROR) << msg;
695*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
696*795d594fSAndroid Build Coastguard Worker Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", msg.c_str());
697*795d594fSAndroid Build Coastguard Worker return;
698*795d594fSAndroid Build Coastguard Worker }
699*795d594fSAndroid Build Coastguard Worker Start(std::move(file), buffer_size, flags, output_mode, trace_mode, interval_us);
700*795d594fSAndroid Build Coastguard Worker }
701*795d594fSAndroid Build Coastguard Worker
Start(int trace_fd,size_t buffer_size,int flags,TraceOutputMode output_mode,TraceMode trace_mode,int interval_us)702*795d594fSAndroid Build Coastguard Worker void Trace::Start(int trace_fd,
703*795d594fSAndroid Build Coastguard Worker size_t buffer_size,
704*795d594fSAndroid Build Coastguard Worker int flags,
705*795d594fSAndroid Build Coastguard Worker TraceOutputMode output_mode,
706*795d594fSAndroid Build Coastguard Worker TraceMode trace_mode,
707*795d594fSAndroid Build Coastguard Worker int interval_us) {
708*795d594fSAndroid Build Coastguard Worker if (trace_fd < 0) {
709*795d594fSAndroid Build Coastguard Worker std::string msg = android::base::StringPrintf("Unable to start tracing with invalid fd %d",
710*795d594fSAndroid Build Coastguard Worker trace_fd);
711*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << msg;
712*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
713*795d594fSAndroid Build Coastguard Worker Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", msg.c_str());
714*795d594fSAndroid Build Coastguard Worker return;
715*795d594fSAndroid Build Coastguard Worker }
716*795d594fSAndroid Build Coastguard Worker std::unique_ptr<File> file(new File(trace_fd, /* path= */ "tracefile", /* check_usage= */ true));
717*795d594fSAndroid Build Coastguard Worker Start(std::move(file), buffer_size, flags, output_mode, trace_mode, interval_us);
718*795d594fSAndroid Build Coastguard Worker }
719*795d594fSAndroid Build Coastguard Worker
StartDDMS(size_t buffer_size,int flags,TraceMode trace_mode,int interval_us)720*795d594fSAndroid Build Coastguard Worker void Trace::StartDDMS(size_t buffer_size,
721*795d594fSAndroid Build Coastguard Worker int flags,
722*795d594fSAndroid Build Coastguard Worker TraceMode trace_mode,
723*795d594fSAndroid Build Coastguard Worker int interval_us) {
724*795d594fSAndroid Build Coastguard Worker Start(std::unique_ptr<File>(),
725*795d594fSAndroid Build Coastguard Worker buffer_size,
726*795d594fSAndroid Build Coastguard Worker flags,
727*795d594fSAndroid Build Coastguard Worker TraceOutputMode::kDDMS,
728*795d594fSAndroid Build Coastguard Worker trace_mode,
729*795d594fSAndroid Build Coastguard Worker interval_us);
730*795d594fSAndroid Build Coastguard Worker }
731*795d594fSAndroid Build Coastguard Worker
Start(std::unique_ptr<File> && trace_file_in,size_t buffer_size,int flags,TraceOutputMode output_mode,TraceMode trace_mode,int interval_us)732*795d594fSAndroid Build Coastguard Worker void Trace::Start(std::unique_ptr<File>&& trace_file_in,
733*795d594fSAndroid Build Coastguard Worker size_t buffer_size,
734*795d594fSAndroid Build Coastguard Worker int flags,
735*795d594fSAndroid Build Coastguard Worker TraceOutputMode output_mode,
736*795d594fSAndroid Build Coastguard Worker TraceMode trace_mode,
737*795d594fSAndroid Build Coastguard Worker int interval_us) {
738*795d594fSAndroid Build Coastguard Worker // We own trace_file now and are responsible for closing it. To account for error situations, use
739*795d594fSAndroid Build Coastguard Worker // a specialized unique_ptr to ensure we close it on the way out (if it hasn't been passed to a
740*795d594fSAndroid Build Coastguard Worker // Trace instance).
741*795d594fSAndroid Build Coastguard Worker auto deleter = [](File* file) {
742*795d594fSAndroid Build Coastguard Worker if (file != nullptr) {
743*795d594fSAndroid Build Coastguard Worker file->MarkUnchecked(); // Don't deal with flushing requirements.
744*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] int result = file->Close();
745*795d594fSAndroid Build Coastguard Worker delete file;
746*795d594fSAndroid Build Coastguard Worker }
747*795d594fSAndroid Build Coastguard Worker };
748*795d594fSAndroid Build Coastguard Worker std::unique_ptr<File, decltype(deleter)> trace_file(trace_file_in.release(), deleter);
749*795d594fSAndroid Build Coastguard Worker
750*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
751*795d594fSAndroid Build Coastguard Worker {
752*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
753*795d594fSAndroid Build Coastguard Worker if (the_trace_ != nullptr) {
754*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Trace already in progress, ignoring this request";
755*795d594fSAndroid Build Coastguard Worker return;
756*795d594fSAndroid Build Coastguard Worker }
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker
759*795d594fSAndroid Build Coastguard Worker // Check interval if sampling is enabled
760*795d594fSAndroid Build Coastguard Worker if (trace_mode == TraceMode::kSampling && interval_us <= 0) {
761*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Invalid sampling interval: " << interval_us;
762*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
763*795d594fSAndroid Build Coastguard Worker ThrowRuntimeException("Invalid sampling interval: %d", interval_us);
764*795d594fSAndroid Build Coastguard Worker return;
765*795d594fSAndroid Build Coastguard Worker }
766*795d594fSAndroid Build Coastguard Worker
767*795d594fSAndroid Build Coastguard Worker // Initialize the frequency of timestamp counter updates here. This is needed
768*795d594fSAndroid Build Coastguard Worker // to get wallclock time from timestamp counter values.
769*795d594fSAndroid Build Coastguard Worker InitializeTimestampCounters();
770*795d594fSAndroid Build Coastguard Worker
771*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
772*795d594fSAndroid Build Coastguard Worker
773*795d594fSAndroid Build Coastguard Worker // Enable count of allocs if specified in the flags.
774*795d594fSAndroid Build Coastguard Worker bool enable_stats = false;
775*795d594fSAndroid Build Coastguard Worker
776*795d594fSAndroid Build Coastguard Worker // Create Trace object.
777*795d594fSAndroid Build Coastguard Worker {
778*795d594fSAndroid Build Coastguard Worker // Suspend JIT here since we are switching runtime to debuggable. Debuggable runtimes cannot use
779*795d594fSAndroid Build Coastguard Worker // JITed code from before so we need to invalidated all JITed code here. Enter suspend JIT scope
780*795d594fSAndroid Build Coastguard Worker // to prevent any races with ongoing JIT compilations.
781*795d594fSAndroid Build Coastguard Worker jit::ScopedJitSuspend suspend_jit;
782*795d594fSAndroid Build Coastguard Worker // Required since EnableMethodTracing calls ConfigureStubs which visits class linker classes.
783*795d594fSAndroid Build Coastguard Worker gc::ScopedGCCriticalSection gcs(self,
784*795d594fSAndroid Build Coastguard Worker gc::kGcCauseInstrumentation,
785*795d594fSAndroid Build Coastguard Worker gc::kCollectorTypeInstrumentation);
786*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa(__FUNCTION__);
787*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
788*795d594fSAndroid Build Coastguard Worker if (TraceProfiler::IsTraceProfileInProgress()) {
789*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "On-demand profile in progress, ignoring this request";
790*795d594fSAndroid Build Coastguard Worker return;
791*795d594fSAndroid Build Coastguard Worker }
792*795d594fSAndroid Build Coastguard Worker
793*795d594fSAndroid Build Coastguard Worker if (Trace::IsTracingEnabledLocked()) {
794*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Trace already in progress, ignoring this request";
795*795d594fSAndroid Build Coastguard Worker return;
796*795d594fSAndroid Build Coastguard Worker }
797*795d594fSAndroid Build Coastguard Worker
798*795d594fSAndroid Build Coastguard Worker enable_stats = (flags & kTraceCountAllocs) != 0;
799*795d594fSAndroid Build Coastguard Worker bool is_trace_format_v2 = GetTraceFormatVersionFromFlags(flags) == Trace::kFormatV2;
800*795d594fSAndroid Build Coastguard Worker the_trace_ = new Trace(trace_file.release(), buffer_size, flags, output_mode, trace_mode);
801*795d594fSAndroid Build Coastguard Worker num_trace_starts_++;
802*795d594fSAndroid Build Coastguard Worker if (is_trace_format_v2) {
803*795d594fSAndroid Build Coastguard Worker // Record all the methods that are currently loaded. We log all methods when any new class
804*795d594fSAndroid Build Coastguard Worker // is loaded. This will allow us to process the trace entries without requiring a mutator
805*795d594fSAndroid Build Coastguard Worker // lock.
806*795d594fSAndroid Build Coastguard Worker RecordMethodInfoClassVisitor visitor(the_trace_);
807*795d594fSAndroid Build Coastguard Worker runtime->GetClassLinker()->VisitClasses(&visitor);
808*795d594fSAndroid Build Coastguard Worker visitor.FlushBuffer();
809*795d594fSAndroid Build Coastguard Worker }
810*795d594fSAndroid Build Coastguard Worker if (trace_mode == TraceMode::kSampling) {
811*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
812*795d594fSAndroid Build Coastguard Worker reinterpret_cast<void*>(interval_us)),
813*795d594fSAndroid Build Coastguard Worker "Sampling profiler thread");
814*795d594fSAndroid Build Coastguard Worker the_trace_->interval_us_ = interval_us;
815*795d594fSAndroid Build Coastguard Worker } else {
816*795d594fSAndroid Build Coastguard Worker if (!runtime->IsJavaDebuggable()) {
817*795d594fSAndroid Build Coastguard Worker art::jit::Jit* jit = runtime->GetJit();
818*795d594fSAndroid Build Coastguard Worker if (jit != nullptr) {
819*795d594fSAndroid Build Coastguard Worker jit->GetCodeCache()->InvalidateAllCompiledCode();
820*795d594fSAndroid Build Coastguard Worker jit->GetCodeCache()->TransitionToDebuggable();
821*795d594fSAndroid Build Coastguard Worker jit->GetJitCompiler()->SetDebuggableCompilerOption(true);
822*795d594fSAndroid Build Coastguard Worker }
823*795d594fSAndroid Build Coastguard Worker runtime->SetRuntimeDebugState(art::Runtime::RuntimeDebugState::kJavaDebuggable);
824*795d594fSAndroid Build Coastguard Worker runtime->GetInstrumentation()->UpdateEntrypointsForDebuggable();
825*795d594fSAndroid Build Coastguard Worker runtime->DeoptimizeBootImage();
826*795d594fSAndroid Build Coastguard Worker }
827*795d594fSAndroid Build Coastguard Worker if (is_trace_format_v2) {
828*795d594fSAndroid Build Coastguard Worker // Add ClassLoadCallback to record methods on class load.
829*795d594fSAndroid Build Coastguard Worker runtime->GetRuntimeCallbacks()->AddClassLoadCallback(the_trace_);
830*795d594fSAndroid Build Coastguard Worker }
831*795d594fSAndroid Build Coastguard Worker runtime->GetInstrumentation()->AddListener(
832*795d594fSAndroid Build Coastguard Worker the_trace_,
833*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodEntered |
834*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodExited |
835*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodUnwind,
836*795d594fSAndroid Build Coastguard Worker UseFastTraceListeners(the_trace_->GetClockSource()));
837*795d594fSAndroid Build Coastguard Worker runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey,
838*795d594fSAndroid Build Coastguard Worker the_trace_,
839*795d594fSAndroid Build Coastguard Worker /*needs_interpreter=*/false);
840*795d594fSAndroid Build Coastguard Worker }
841*795d594fSAndroid Build Coastguard Worker
842*795d594fSAndroid Build Coastguard Worker if (art_flags::always_enable_profile_code()) {
843*795d594fSAndroid Build Coastguard Worker // Reset the trace low overhead trace entry points to be a nop.
844*795d594fSAndroid Build Coastguard Worker MutexLock thread_list_mutex(self, *Locks::thread_list_lock_);
845*795d594fSAndroid Build Coastguard Worker for (Thread* thread : Runtime::Current()->GetThreadList()->GetList()) {
846*795d594fSAndroid Build Coastguard Worker thread->UpdateTlsLowOverheadTraceEntrypoints(/*enable= */ false);
847*795d594fSAndroid Build Coastguard Worker }
848*795d594fSAndroid Build Coastguard Worker }
849*795d594fSAndroid Build Coastguard Worker }
850*795d594fSAndroid Build Coastguard Worker
851*795d594fSAndroid Build Coastguard Worker // Can't call this when holding the mutator lock.
852*795d594fSAndroid Build Coastguard Worker if (enable_stats) {
853*795d594fSAndroid Build Coastguard Worker runtime->SetStatsEnabled(true);
854*795d594fSAndroid Build Coastguard Worker }
855*795d594fSAndroid Build Coastguard Worker }
856*795d594fSAndroid Build Coastguard Worker
StopTracing(bool flush_entries)857*795d594fSAndroid Build Coastguard Worker void Trace::StopTracing(bool flush_entries) {
858*795d594fSAndroid Build Coastguard Worker Runtime* const runtime = Runtime::Current();
859*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
860*795d594fSAndroid Build Coastguard Worker
861*795d594fSAndroid Build Coastguard Worker pthread_t sampling_pthread = 0U;
862*795d594fSAndroid Build Coastguard Worker {
863*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
864*795d594fSAndroid Build Coastguard Worker num_trace_stops_initiated_++;
865*795d594fSAndroid Build Coastguard Worker if (the_trace_ == nullptr || the_trace_->stop_tracing_) {
866*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Trace stop requested, but no trace currently running or trace is being"
867*795d594fSAndroid Build Coastguard Worker << " stopped concurrently on another thread";
868*795d594fSAndroid Build Coastguard Worker return;
869*795d594fSAndroid Build Coastguard Worker }
870*795d594fSAndroid Build Coastguard Worker // Tell sampling_pthread_ to stop tracing.
871*795d594fSAndroid Build Coastguard Worker the_trace_->stop_tracing_ = true;
872*795d594fSAndroid Build Coastguard Worker sampling_pthread = sampling_pthread_;
873*795d594fSAndroid Build Coastguard Worker }
874*795d594fSAndroid Build Coastguard Worker
875*795d594fSAndroid Build Coastguard Worker // Make sure that we join before we delete the trace since we don't want to have
876*795d594fSAndroid Build Coastguard Worker // the sampling thread access a stale pointer. This finishes since the sampling thread exits when
877*795d594fSAndroid Build Coastguard Worker // the_trace_ is null.
878*795d594fSAndroid Build Coastguard Worker if (sampling_pthread != 0U) {
879*795d594fSAndroid Build Coastguard Worker CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, nullptr), "sampling thread shutdown");
880*795d594fSAndroid Build Coastguard Worker }
881*795d594fSAndroid Build Coastguard Worker
882*795d594fSAndroid Build Coastguard Worker // Wakeup any threads waiting for a buffer and abort allocating a buffer.
883*795d594fSAndroid Build Coastguard Worker the_trace_->trace_writer_->StopTracing();
884*795d594fSAndroid Build Coastguard Worker
885*795d594fSAndroid Build Coastguard Worker // Make a copy of the_trace_, so it can be flushed later. We want to reset
886*795d594fSAndroid Build Coastguard Worker // the_trace_ to nullptr in suspend all scope to prevent any races
887*795d594fSAndroid Build Coastguard Worker Trace* the_trace = the_trace_;
888*795d594fSAndroid Build Coastguard Worker bool stop_alloc_counting = (the_trace->flags_ & Trace::kTraceCountAllocs) != 0;
889*795d594fSAndroid Build Coastguard Worker // Stop the trace sources adding more entries to the trace buffer and synchronise stores.
890*795d594fSAndroid Build Coastguard Worker {
891*795d594fSAndroid Build Coastguard Worker gc::ScopedGCCriticalSection gcs(
892*795d594fSAndroid Build Coastguard Worker self, gc::kGcCauseInstrumentation, gc::kCollectorTypeInstrumentation);
893*795d594fSAndroid Build Coastguard Worker jit::ScopedJitSuspend suspend_jit;
894*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa(__FUNCTION__);
895*795d594fSAndroid Build Coastguard Worker
896*795d594fSAndroid Build Coastguard Worker if (the_trace->trace_mode_ == TraceMode::kSampling) {
897*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::thread_list_lock_);
898*795d594fSAndroid Build Coastguard Worker runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, nullptr);
899*795d594fSAndroid Build Coastguard Worker } else {
900*795d594fSAndroid Build Coastguard Worker runtime->GetRuntimeCallbacks()->RemoveClassLoadCallback(the_trace_);
901*795d594fSAndroid Build Coastguard Worker runtime->GetInstrumentation()->RemoveListener(
902*795d594fSAndroid Build Coastguard Worker the_trace,
903*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodEntered |
904*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodExited |
905*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodUnwind,
906*795d594fSAndroid Build Coastguard Worker UseFastTraceListeners(the_trace_->GetClockSource()));
907*795d594fSAndroid Build Coastguard Worker runtime->GetInstrumentation()->DisableMethodTracing(kTracerInstrumentationKey);
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker
910*795d594fSAndroid Build Coastguard Worker // Flush thread specific buffer from all threads before resetting the_trace_ to nullptr.
911*795d594fSAndroid Build Coastguard Worker // We also flush the buffer when destroying a thread which expects the_trace_ to be valid so
912*795d594fSAndroid Build Coastguard Worker // make sure that the per-thread buffer is reset before resetting the_trace_.
913*795d594fSAndroid Build Coastguard Worker {
914*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
915*795d594fSAndroid Build Coastguard Worker MutexLock tl_lock(Thread::Current(), *Locks::thread_list_lock_);
916*795d594fSAndroid Build Coastguard Worker // Flush the per-thread buffers and reset the trace inside the trace_lock_ to avoid any
917*795d594fSAndroid Build Coastguard Worker // race if the thread is detaching and trying to flush the buffer too. Since we hold the
918*795d594fSAndroid Build Coastguard Worker // trace_lock_ both here and when flushing on a thread detach only one of them will succeed
919*795d594fSAndroid Build Coastguard Worker // in actually flushing the buffer.
920*795d594fSAndroid Build Coastguard Worker for (Thread* thread : Runtime::Current()->GetThreadList()->GetList()) {
921*795d594fSAndroid Build Coastguard Worker if (thread->GetMethodTraceBuffer() != nullptr) {
922*795d594fSAndroid Build Coastguard Worker // We may have pending requests to flush the data. So just enqueue a
923*795d594fSAndroid Build Coastguard Worker // request to flush the current buffer so all the requests are
924*795d594fSAndroid Build Coastguard Worker // processed in order.
925*795d594fSAndroid Build Coastguard Worker the_trace->trace_writer_->FlushBuffer(
926*795d594fSAndroid Build Coastguard Worker thread, /* is_sync= */ false, /* free_buffer= */ true);
927*795d594fSAndroid Build Coastguard Worker }
928*795d594fSAndroid Build Coastguard Worker
929*795d594fSAndroid Build Coastguard Worker if (art_flags::always_enable_profile_code()) {
930*795d594fSAndroid Build Coastguard Worker thread->UpdateTlsLowOverheadTraceEntrypoints(/*enable= */ true);
931*795d594fSAndroid Build Coastguard Worker }
932*795d594fSAndroid Build Coastguard Worker }
933*795d594fSAndroid Build Coastguard Worker the_trace_ = nullptr;
934*795d594fSAndroid Build Coastguard Worker sampling_pthread_ = 0U;
935*795d594fSAndroid Build Coastguard Worker }
936*795d594fSAndroid Build Coastguard Worker }
937*795d594fSAndroid Build Coastguard Worker
938*795d594fSAndroid Build Coastguard Worker // At this point, code may read buf_ as its writers are shutdown
939*795d594fSAndroid Build Coastguard Worker // and the ScopedSuspendAll above has ensured all stores to buf_
940*795d594fSAndroid Build Coastguard Worker // are now visible.
941*795d594fSAndroid Build Coastguard Worker the_trace->trace_writer_->FinishTracing(the_trace->flags_, flush_entries);
942*795d594fSAndroid Build Coastguard Worker delete the_trace;
943*795d594fSAndroid Build Coastguard Worker num_trace_stops_finished_++;
944*795d594fSAndroid Build Coastguard Worker
945*795d594fSAndroid Build Coastguard Worker if (stop_alloc_counting) {
946*795d594fSAndroid Build Coastguard Worker // Can be racy since SetStatsEnabled is not guarded by any locks.
947*795d594fSAndroid Build Coastguard Worker runtime->SetStatsEnabled(false);
948*795d594fSAndroid Build Coastguard Worker }
949*795d594fSAndroid Build Coastguard Worker }
950*795d594fSAndroid Build Coastguard Worker
RemoveListeners()951*795d594fSAndroid Build Coastguard Worker void Trace::RemoveListeners() {
952*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
953*795d594fSAndroid Build Coastguard Worker // This is expected to be called in SuspendAll scope.
954*795d594fSAndroid Build Coastguard Worker DCHECK(Locks::mutator_lock_->IsExclusiveHeld(self));
955*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
956*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
957*795d594fSAndroid Build Coastguard Worker runtime->GetRuntimeCallbacks()->RemoveClassLoadCallback(the_trace_);
958*795d594fSAndroid Build Coastguard Worker runtime->GetInstrumentation()->RemoveListener(
959*795d594fSAndroid Build Coastguard Worker the_trace_,
960*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodEntered |
961*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodExited |
962*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::kMethodUnwind,
963*795d594fSAndroid Build Coastguard Worker UseFastTraceListeners(the_trace_->GetClockSource()));
964*795d594fSAndroid Build Coastguard Worker }
965*795d594fSAndroid Build Coastguard Worker
FlushThreadBuffer(Thread * self)966*795d594fSAndroid Build Coastguard Worker void Trace::FlushThreadBuffer(Thread* self) {
967*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
968*795d594fSAndroid Build Coastguard Worker // Check if we still need to flush inside the trace_lock_. If we are stopping tracing it is
969*795d594fSAndroid Build Coastguard Worker // possible we already deleted the trace and flushed the buffer too.
970*795d594fSAndroid Build Coastguard Worker if (the_trace_ == nullptr) {
971*795d594fSAndroid Build Coastguard Worker if (art_flags::always_enable_profile_code()) {
972*795d594fSAndroid Build Coastguard Worker TraceProfiler::ReleaseThreadBuffer(self);
973*795d594fSAndroid Build Coastguard Worker }
974*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(self->GetMethodTraceBuffer(), nullptr);
975*795d594fSAndroid Build Coastguard Worker return;
976*795d594fSAndroid Build Coastguard Worker }
977*795d594fSAndroid Build Coastguard Worker the_trace_->trace_writer_->FlushBuffer(self, /* is_sync= */ false, /* free_buffer= */ true);
978*795d594fSAndroid Build Coastguard Worker }
979*795d594fSAndroid Build Coastguard Worker
ReleaseThreadBuffer(Thread * self)980*795d594fSAndroid Build Coastguard Worker void Trace::ReleaseThreadBuffer(Thread* self) {
981*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, *Locks::trace_lock_);
982*795d594fSAndroid Build Coastguard Worker // Check if we still need to flush inside the trace_lock_. If we are stopping tracing it is
983*795d594fSAndroid Build Coastguard Worker // possible we already deleted the trace and flushed the buffer too.
984*795d594fSAndroid Build Coastguard Worker if (the_trace_ == nullptr) {
985*795d594fSAndroid Build Coastguard Worker if (art_flags::always_enable_profile_code()) {
986*795d594fSAndroid Build Coastguard Worker TraceProfiler::ReleaseThreadBuffer(self);
987*795d594fSAndroid Build Coastguard Worker }
988*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(self->GetMethodTraceBuffer(), nullptr);
989*795d594fSAndroid Build Coastguard Worker return;
990*795d594fSAndroid Build Coastguard Worker }
991*795d594fSAndroid Build Coastguard Worker the_trace_->trace_writer_->ReleaseBufferForThread(self);
992*795d594fSAndroid Build Coastguard Worker self->SetMethodTraceBuffer(nullptr, 0);
993*795d594fSAndroid Build Coastguard Worker }
994*795d594fSAndroid Build Coastguard Worker
Abort()995*795d594fSAndroid Build Coastguard Worker void Trace::Abort() {
996*795d594fSAndroid Build Coastguard Worker // Do not write anything anymore.
997*795d594fSAndroid Build Coastguard Worker StopTracing(/* flush_entries= */ false);
998*795d594fSAndroid Build Coastguard Worker }
999*795d594fSAndroid Build Coastguard Worker
Stop()1000*795d594fSAndroid Build Coastguard Worker void Trace::Stop() {
1001*795d594fSAndroid Build Coastguard Worker // Finish writing.
1002*795d594fSAndroid Build Coastguard Worker StopTracing(/* flush_entries= */ true);
1003*795d594fSAndroid Build Coastguard Worker }
1004*795d594fSAndroid Build Coastguard Worker
Shutdown()1005*795d594fSAndroid Build Coastguard Worker void Trace::Shutdown() {
1006*795d594fSAndroid Build Coastguard Worker if (GetMethodTracingMode() != kTracingInactive) {
1007*795d594fSAndroid Build Coastguard Worker Stop();
1008*795d594fSAndroid Build Coastguard Worker }
1009*795d594fSAndroid Build Coastguard Worker }
1010*795d594fSAndroid Build Coastguard Worker
GetMethodTracingMode()1011*795d594fSAndroid Build Coastguard Worker TracingMode Trace::GetMethodTracingMode() {
1012*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1013*795d594fSAndroid Build Coastguard Worker if (the_trace_ == nullptr) {
1014*795d594fSAndroid Build Coastguard Worker return kTracingInactive;
1015*795d594fSAndroid Build Coastguard Worker } else {
1016*795d594fSAndroid Build Coastguard Worker switch (the_trace_->trace_mode_) {
1017*795d594fSAndroid Build Coastguard Worker case TraceMode::kSampling:
1018*795d594fSAndroid Build Coastguard Worker return kSampleProfilingActive;
1019*795d594fSAndroid Build Coastguard Worker case TraceMode::kMethodTracing:
1020*795d594fSAndroid Build Coastguard Worker return kMethodTracingActive;
1021*795d594fSAndroid Build Coastguard Worker }
1022*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
1023*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
1024*795d594fSAndroid Build Coastguard Worker }
1025*795d594fSAndroid Build Coastguard Worker }
1026*795d594fSAndroid Build Coastguard Worker
TraceWriter(File * trace_file,TraceOutputMode output_mode,TraceClockSource clock_source,size_t buffer_size,int num_trace_buffers,int trace_format_version,uint32_t clock_overhead_ns)1027*795d594fSAndroid Build Coastguard Worker TraceWriter::TraceWriter(File* trace_file,
1028*795d594fSAndroid Build Coastguard Worker TraceOutputMode output_mode,
1029*795d594fSAndroid Build Coastguard Worker TraceClockSource clock_source,
1030*795d594fSAndroid Build Coastguard Worker size_t buffer_size,
1031*795d594fSAndroid Build Coastguard Worker int num_trace_buffers,
1032*795d594fSAndroid Build Coastguard Worker int trace_format_version,
1033*795d594fSAndroid Build Coastguard Worker uint32_t clock_overhead_ns)
1034*795d594fSAndroid Build Coastguard Worker : trace_file_(trace_file),
1035*795d594fSAndroid Build Coastguard Worker trace_output_mode_(output_mode),
1036*795d594fSAndroid Build Coastguard Worker clock_source_(clock_source),
1037*795d594fSAndroid Build Coastguard Worker buf_(new uint8_t[std::max(kMinBufSize, buffer_size)]()),
1038*795d594fSAndroid Build Coastguard Worker buffer_size_(std::max(kMinBufSize, buffer_size)),
1039*795d594fSAndroid Build Coastguard Worker trace_format_version_(trace_format_version),
1040*795d594fSAndroid Build Coastguard Worker start_time_(GetMicroTime(GetTimestamp())),
1041*795d594fSAndroid Build Coastguard Worker overflow_(false),
1042*795d594fSAndroid Build Coastguard Worker num_records_(0),
1043*795d594fSAndroid Build Coastguard Worker clock_overhead_ns_(clock_overhead_ns),
1044*795d594fSAndroid Build Coastguard Worker owner_tids_(num_trace_buffers),
1045*795d594fSAndroid Build Coastguard Worker buffer_pool_lock_("tracing buffer pool lock", kDefaultMutexLevel),
1046*795d594fSAndroid Build Coastguard Worker buffer_available_("buffer available condition", buffer_pool_lock_),
1047*795d594fSAndroid Build Coastguard Worker num_waiters_zero_cond_("Num waiters zero", buffer_pool_lock_),
1048*795d594fSAndroid Build Coastguard Worker num_waiters_for_buffer_(0),
1049*795d594fSAndroid Build Coastguard Worker trace_writer_lock_("trace writer lock", LockLevel::kTracingStreamingLock) {
1050*795d594fSAndroid Build Coastguard Worker // We initialize the start_time_ from the timestamp counter. This may not match
1051*795d594fSAndroid Build Coastguard Worker // with the monotonic timer but we only use this time to calculate the elapsed
1052*795d594fSAndroid Build Coastguard Worker // time from this point which should be the same for both cases.
1053*795d594fSAndroid Build Coastguard Worker // We record monotonic time at the start of the trace, because Android Studio
1054*795d594fSAndroid Build Coastguard Worker // fetches the monotonic timer from other places and matches these times to
1055*795d594fSAndroid Build Coastguard Worker // construct a cpu profile. See b/318052824 for more context.
1056*795d594fSAndroid Build Coastguard Worker uint64_t start_time_monotonic = start_time_ + (MicroTime() - GetMicroTime(GetTimestamp()));
1057*795d594fSAndroid Build Coastguard Worker uint16_t trace_version = GetTraceVersion(clock_source_, trace_format_version_);
1058*795d594fSAndroid Build Coastguard Worker if (output_mode == TraceOutputMode::kStreaming) {
1059*795d594fSAndroid Build Coastguard Worker trace_version |= 0xF0U;
1060*795d594fSAndroid Build Coastguard Worker }
1061*795d594fSAndroid Build Coastguard Worker
1062*795d594fSAndroid Build Coastguard Worker // Set up the beginning of the trace.
1063*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1) {
1064*795d594fSAndroid Build Coastguard Worker memset(buf_.get(), 0, kTraceHeaderLength);
1065*795d594fSAndroid Build Coastguard Worker Append4LE(buf_.get(), kTraceMagicValue);
1066*795d594fSAndroid Build Coastguard Worker Append2LE(buf_.get() + 4, trace_version);
1067*795d594fSAndroid Build Coastguard Worker Append2LE(buf_.get() + 6, kTraceHeaderLength);
1068*795d594fSAndroid Build Coastguard Worker Append8LE(buf_.get() + 8, start_time_monotonic);
1069*795d594fSAndroid Build Coastguard Worker if (trace_version >= kTraceVersionDualClock) {
1070*795d594fSAndroid Build Coastguard Worker uint16_t record_size = GetRecordSize(clock_source_, trace_format_version_);
1071*795d594fSAndroid Build Coastguard Worker Append2LE(buf_.get() + 16, record_size);
1072*795d594fSAndroid Build Coastguard Worker }
1073*795d594fSAndroid Build Coastguard Worker static_assert(18 <= kMinBufSize, "Minimum buffer size not large enough for trace header");
1074*795d594fSAndroid Build Coastguard Worker
1075*795d594fSAndroid Build Coastguard Worker cur_offset_ = kTraceHeaderLength;
1076*795d594fSAndroid Build Coastguard Worker } else {
1077*795d594fSAndroid Build Coastguard Worker memset(buf_.get(), 0, kTraceHeaderLengthV2);
1078*795d594fSAndroid Build Coastguard Worker Append4LE(buf_.get(), kTraceMagicValue);
1079*795d594fSAndroid Build Coastguard Worker Append2LE(buf_.get() + 4, trace_version);
1080*795d594fSAndroid Build Coastguard Worker Append8LE(buf_.get() + 6, start_time_monotonic);
1081*795d594fSAndroid Build Coastguard Worker cur_offset_ = kTraceHeaderLengthV2;
1082*795d594fSAndroid Build Coastguard Worker }
1083*795d594fSAndroid Build Coastguard Worker
1084*795d594fSAndroid Build Coastguard Worker if (output_mode == TraceOutputMode::kStreaming || trace_format_version_ == Trace::kFormatV2) {
1085*795d594fSAndroid Build Coastguard Worker // Flush the header information to the file. We use a per thread buffer, so
1086*795d594fSAndroid Build Coastguard Worker // it is easier to just write the header information directly to file.
1087*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buf_.get(), kTraceHeaderLength)) {
1088*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1089*795d594fSAndroid Build Coastguard Worker }
1090*795d594fSAndroid Build Coastguard Worker cur_offset_ = 0;
1091*795d594fSAndroid Build Coastguard Worker }
1092*795d594fSAndroid Build Coastguard Worker // Thread index of 0 is a special identifier used to distinguish between trace
1093*795d594fSAndroid Build Coastguard Worker // event entries and thread / method info entries.
1094*795d594fSAndroid Build Coastguard Worker current_thread_index_ = 1;
1095*795d594fSAndroid Build Coastguard Worker
1096*795d594fSAndroid Build Coastguard Worker // Don't create threadpool for a zygote. This would cause slowdown when forking because we need
1097*795d594fSAndroid Build Coastguard Worker // to stop and start this thread pool. Method tracing on zygote isn't a frequent use case and
1098*795d594fSAndroid Build Coastguard Worker // it is okay to flush on the main thread in such cases.
1099*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->IsZygote()) {
1100*795d594fSAndroid Build Coastguard Worker thread_pool_.reset(TraceWriterThreadPool::Create("Trace writer pool"));
1101*795d594fSAndroid Build Coastguard Worker thread_pool_->StartWorkers(Thread::Current());
1102*795d594fSAndroid Build Coastguard Worker }
1103*795d594fSAndroid Build Coastguard Worker
1104*795d594fSAndroid Build Coastguard Worker // Initialize the pool of per-thread buffers.
1105*795d594fSAndroid Build Coastguard Worker InitializeTraceBuffers();
1106*795d594fSAndroid Build Coastguard Worker }
1107*795d594fSAndroid Build Coastguard Worker
Trace(File * trace_file,size_t buffer_size,int flags,TraceOutputMode output_mode,TraceMode trace_mode)1108*795d594fSAndroid Build Coastguard Worker Trace::Trace(File* trace_file,
1109*795d594fSAndroid Build Coastguard Worker size_t buffer_size,
1110*795d594fSAndroid Build Coastguard Worker int flags,
1111*795d594fSAndroid Build Coastguard Worker TraceOutputMode output_mode,
1112*795d594fSAndroid Build Coastguard Worker TraceMode trace_mode)
1113*795d594fSAndroid Build Coastguard Worker : flags_(flags),
1114*795d594fSAndroid Build Coastguard Worker trace_mode_(trace_mode),
1115*795d594fSAndroid Build Coastguard Worker clock_source_(GetClockSourceFromFlags(flags)),
1116*795d594fSAndroid Build Coastguard Worker interval_us_(0),
1117*795d594fSAndroid Build Coastguard Worker stop_tracing_(false) {
1118*795d594fSAndroid Build Coastguard Worker CHECK_IMPLIES(trace_file == nullptr, output_mode == TraceOutputMode::kDDMS);
1119*795d594fSAndroid Build Coastguard Worker
1120*795d594fSAndroid Build Coastguard Worker int trace_format_version = GetTraceFormatVersionFromFlags(flags_);
1121*795d594fSAndroid Build Coastguard Worker // In streaming mode, we only need a buffer big enough to store data per each
1122*795d594fSAndroid Build Coastguard Worker // thread buffer. In non-streaming mode this is specified by the user and we
1123*795d594fSAndroid Build Coastguard Worker // stop tracing when the buffer is full.
1124*795d594fSAndroid Build Coastguard Worker size_t buf_size = (output_mode == TraceOutputMode::kStreaming) ?
1125*795d594fSAndroid Build Coastguard Worker kPerThreadBufSize * kScalingFactorEncodedEntries :
1126*795d594fSAndroid Build Coastguard Worker buffer_size;
1127*795d594fSAndroid Build Coastguard Worker trace_writer_.reset(new TraceWriter(trace_file,
1128*795d594fSAndroid Build Coastguard Worker output_mode,
1129*795d594fSAndroid Build Coastguard Worker clock_source_,
1130*795d594fSAndroid Build Coastguard Worker buf_size,
1131*795d594fSAndroid Build Coastguard Worker kNumTracePoolBuffers,
1132*795d594fSAndroid Build Coastguard Worker trace_format_version,
1133*795d594fSAndroid Build Coastguard Worker GetClockOverheadNanoSeconds()));
1134*795d594fSAndroid Build Coastguard Worker }
1135*795d594fSAndroid Build Coastguard Worker
CreateSummary(int flags)1136*795d594fSAndroid Build Coastguard Worker std::string TraceWriter::CreateSummary(int flags) {
1137*795d594fSAndroid Build Coastguard Worker std::ostringstream os;
1138*795d594fSAndroid Build Coastguard Worker // Compute elapsed time.
1139*795d594fSAndroid Build Coastguard Worker uint64_t elapsed = GetMicroTime(GetTimestamp()) - start_time_;
1140*795d594fSAndroid Build Coastguard Worker os << StringPrintf("%cversion\n", kTraceTokenChar);
1141*795d594fSAndroid Build Coastguard Worker os << StringPrintf("%d\n", GetTraceVersion(clock_source_, trace_format_version_));
1142*795d594fSAndroid Build Coastguard Worker os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false");
1143*795d594fSAndroid Build Coastguard Worker if (UseThreadCpuClock(clock_source_)) {
1144*795d594fSAndroid Build Coastguard Worker if (UseWallClock(clock_source_)) {
1145*795d594fSAndroid Build Coastguard Worker os << StringPrintf("clock=dual\n");
1146*795d594fSAndroid Build Coastguard Worker } else {
1147*795d594fSAndroid Build Coastguard Worker os << StringPrintf("clock=thread-cpu\n");
1148*795d594fSAndroid Build Coastguard Worker }
1149*795d594fSAndroid Build Coastguard Worker } else {
1150*795d594fSAndroid Build Coastguard Worker os << StringPrintf("clock=wall\n");
1151*795d594fSAndroid Build Coastguard Worker }
1152*795d594fSAndroid Build Coastguard Worker os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed);
1153*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ != TraceOutputMode::kStreaming) {
1154*795d594fSAndroid Build Coastguard Worker os << StringPrintf("num-method-calls=%zd\n", num_records_);
1155*795d594fSAndroid Build Coastguard Worker }
1156*795d594fSAndroid Build Coastguard Worker os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns_);
1157*795d594fSAndroid Build Coastguard Worker os << StringPrintf("vm=art\n");
1158*795d594fSAndroid Build Coastguard Worker os << StringPrintf("pid=%d\n", getpid());
1159*795d594fSAndroid Build Coastguard Worker if ((flags & Trace::kTraceCountAllocs) != 0) {
1160*795d594fSAndroid Build Coastguard Worker os << "alloc-count=" << Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS) << "\n";
1161*795d594fSAndroid Build Coastguard Worker os << "alloc-size=" << Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES) << "\n";
1162*795d594fSAndroid Build Coastguard Worker os << "gc-count=" << Runtime::Current()->GetStat(KIND_GC_INVOCATIONS) << "\n";
1163*795d594fSAndroid Build Coastguard Worker }
1164*795d594fSAndroid Build Coastguard Worker
1165*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1) {
1166*795d594fSAndroid Build Coastguard Worker os << StringPrintf("%cthreads\n", kTraceTokenChar);
1167*795d594fSAndroid Build Coastguard Worker DumpThreadList(os);
1168*795d594fSAndroid Build Coastguard Worker os << StringPrintf("%cmethods\n", kTraceTokenChar);
1169*795d594fSAndroid Build Coastguard Worker DumpMethodList(os);
1170*795d594fSAndroid Build Coastguard Worker }
1171*795d594fSAndroid Build Coastguard Worker os << StringPrintf("%cend\n", kTraceTokenChar);
1172*795d594fSAndroid Build Coastguard Worker return os.str();
1173*795d594fSAndroid Build Coastguard Worker }
1174*795d594fSAndroid Build Coastguard Worker
FinishTracing(int flags,bool flush_entries)1175*795d594fSAndroid Build Coastguard Worker void TraceWriter::FinishTracing(int flags, bool flush_entries) {
1176*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1177*795d594fSAndroid Build Coastguard Worker
1178*795d594fSAndroid Build Coastguard Worker if (!flush_entries) {
1179*795d594fSAndroid Build Coastguard Worker // This is only called from the child process post fork to abort the trace.
1180*795d594fSAndroid Build Coastguard Worker // We shouldn't have any workers in the thread pool here.
1181*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(thread_pool_, nullptr);
1182*795d594fSAndroid Build Coastguard Worker trace_file_->MarkUnchecked(); // Do not trigger guard.
1183*795d594fSAndroid Build Coastguard Worker if (trace_file_->Close() != 0) {
1184*795d594fSAndroid Build Coastguard Worker PLOG(ERROR) << "Could not close trace file.";
1185*795d594fSAndroid Build Coastguard Worker }
1186*795d594fSAndroid Build Coastguard Worker return;
1187*795d594fSAndroid Build Coastguard Worker }
1188*795d594fSAndroid Build Coastguard Worker
1189*795d594fSAndroid Build Coastguard Worker if (thread_pool_ != nullptr) {
1190*795d594fSAndroid Build Coastguard Worker // Wait for any workers to be created. If we are stopping tracing as a part of runtime
1191*795d594fSAndroid Build Coastguard Worker // shutdown, any unstarted workers can create problems if they try attaching while shutting
1192*795d594fSAndroid Build Coastguard Worker // down.
1193*795d594fSAndroid Build Coastguard Worker thread_pool_->WaitForWorkersToBeCreated();
1194*795d594fSAndroid Build Coastguard Worker // Wait for any outstanding writer tasks to finish. Let the thread pool worker finish the
1195*795d594fSAndroid Build Coastguard Worker // tasks to avoid any re-ordering when processing tasks.
1196*795d594fSAndroid Build Coastguard Worker thread_pool_->Wait(self, /* do_work= */ false, /* may_hold_locks= */ true);
1197*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(thread_pool_->GetTaskCount(self), 0u);
1198*795d594fSAndroid Build Coastguard Worker thread_pool_->StopWorkers(self);
1199*795d594fSAndroid Build Coastguard Worker }
1200*795d594fSAndroid Build Coastguard Worker
1201*795d594fSAndroid Build Coastguard Worker size_t final_offset = 0;
1202*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ != TraceOutputMode::kStreaming) {
1203*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
1204*795d594fSAndroid Build Coastguard Worker final_offset = cur_offset_;
1205*795d594fSAndroid Build Coastguard Worker }
1206*795d594fSAndroid Build Coastguard Worker
1207*795d594fSAndroid Build Coastguard Worker std::string summary = CreateSummary(flags);
1208*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1) {
1209*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ == TraceOutputMode::kStreaming) {
1210*795d594fSAndroid Build Coastguard Worker DCHECK_NE(trace_file_.get(), nullptr);
1211*795d594fSAndroid Build Coastguard Worker // It is expected that this method is called when all other threads are suspended, so there
1212*795d594fSAndroid Build Coastguard Worker // cannot be any writes to trace_file_ after finish tracing.
1213*795d594fSAndroid Build Coastguard Worker // Write a special token to mark the end of trace records and the start of
1214*795d594fSAndroid Build Coastguard Worker // trace summary.
1215*795d594fSAndroid Build Coastguard Worker uint8_t buf[7];
1216*795d594fSAndroid Build Coastguard Worker Append2LE(buf, 0);
1217*795d594fSAndroid Build Coastguard Worker buf[2] = kOpTraceSummary;
1218*795d594fSAndroid Build Coastguard Worker Append4LE(buf + 3, static_cast<uint32_t>(summary.length()));
1219*795d594fSAndroid Build Coastguard Worker // Write the trace summary. The summary is identical to the file header when
1220*795d594fSAndroid Build Coastguard Worker // the output mode is not streaming (except for methods).
1221*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buf, sizeof(buf)) ||
1222*795d594fSAndroid Build Coastguard Worker !trace_file_->WriteFully(summary.c_str(), summary.length())) {
1223*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1224*795d594fSAndroid Build Coastguard Worker }
1225*795d594fSAndroid Build Coastguard Worker } else if (trace_output_mode_ == TraceOutputMode::kFile) {
1226*795d594fSAndroid Build Coastguard Worker DCHECK_NE(trace_file_.get(), nullptr);
1227*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(summary.c_str(), summary.length()) ||
1228*795d594fSAndroid Build Coastguard Worker !trace_file_->WriteFully(buf_.get(), final_offset)) {
1229*795d594fSAndroid Build Coastguard Worker std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
1230*795d594fSAndroid Build Coastguard Worker PLOG(ERROR) << detail;
1231*795d594fSAndroid Build Coastguard Worker ThrowRuntimeException("%s", detail.c_str());
1232*795d594fSAndroid Build Coastguard Worker }
1233*795d594fSAndroid Build Coastguard Worker } else {
1234*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(trace_file_.get(), nullptr);
1235*795d594fSAndroid Build Coastguard Worker DCHECK(trace_output_mode_ == TraceOutputMode::kDDMS);
1236*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> data;
1237*795d594fSAndroid Build Coastguard Worker data.resize(summary.length() + final_offset);
1238*795d594fSAndroid Build Coastguard Worker memcpy(data.data(), summary.c_str(), summary.length());
1239*795d594fSAndroid Build Coastguard Worker memcpy(data.data() + summary.length(), buf_.get(), final_offset);
1240*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetRuntimeCallbacks()->DdmPublishChunk(CHUNK_TYPE("MPSE"),
1241*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t>(data));
1242*795d594fSAndroid Build Coastguard Worker }
1243*795d594fSAndroid Build Coastguard Worker } else {
1244*795d594fSAndroid Build Coastguard Worker DCHECK(trace_format_version_ == Trace::kFormatV2);
1245*795d594fSAndroid Build Coastguard Worker DCHECK(trace_output_mode_ != TraceOutputMode::kDDMS);
1246*795d594fSAndroid Build Coastguard Worker
1247*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ == TraceOutputMode::kFile) {
1248*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buf_.get(), final_offset)) {
1249*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed to write trace output";
1250*795d594fSAndroid Build Coastguard Worker }
1251*795d594fSAndroid Build Coastguard Worker }
1252*795d594fSAndroid Build Coastguard Worker
1253*795d594fSAndroid Build Coastguard Worker // Write the summary packet
1254*795d594fSAndroid Build Coastguard Worker uint8_t buf[3];
1255*795d594fSAndroid Build Coastguard Worker buf[0] = kSummaryHeaderV2;
1256*795d594fSAndroid Build Coastguard Worker Append2LE(buf + 1, static_cast<uint32_t>(summary.length()));
1257*795d594fSAndroid Build Coastguard Worker // Write the trace summary. Reports information about tracing mode, number of records and
1258*795d594fSAndroid Build Coastguard Worker // clock overhead in plain text format.
1259*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buf, sizeof(buf)) ||
1260*795d594fSAndroid Build Coastguard Worker !trace_file_->WriteFully(summary.c_str(), summary.length())) {
1261*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1262*795d594fSAndroid Build Coastguard Worker }
1263*795d594fSAndroid Build Coastguard Worker }
1264*795d594fSAndroid Build Coastguard Worker
1265*795d594fSAndroid Build Coastguard Worker if (trace_file_.get() != nullptr) {
1266*795d594fSAndroid Build Coastguard Worker // Do not try to erase, so flush and close explicitly.
1267*795d594fSAndroid Build Coastguard Worker if (trace_file_->Flush() != 0) {
1268*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Could not flush trace file.";
1269*795d594fSAndroid Build Coastguard Worker }
1270*795d594fSAndroid Build Coastguard Worker if (trace_file_->Close() != 0) {
1271*795d594fSAndroid Build Coastguard Worker PLOG(ERROR) << "Could not close trace file.";
1272*795d594fSAndroid Build Coastguard Worker }
1273*795d594fSAndroid Build Coastguard Worker }
1274*795d594fSAndroid Build Coastguard Worker }
1275*795d594fSAndroid Build Coastguard Worker
DexPcMoved(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t new_dex_pc)1276*795d594fSAndroid Build Coastguard Worker void Trace::DexPcMoved([[maybe_unused]] Thread* thread,
1277*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::Object> this_object,
1278*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1279*795d594fSAndroid Build Coastguard Worker uint32_t new_dex_pc) {
1280*795d594fSAndroid Build Coastguard Worker // We're not recorded to listen to this kind of event, so complain.
1281*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected dex PC event in tracing " << ArtMethod::PrettyMethod(method)
1282*795d594fSAndroid Build Coastguard Worker << " " << new_dex_pc;
1283*795d594fSAndroid Build Coastguard Worker }
1284*795d594fSAndroid Build Coastguard Worker
FieldRead(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field)1285*795d594fSAndroid Build Coastguard Worker void Trace::FieldRead([[maybe_unused]] Thread* thread,
1286*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::Object> this_object,
1287*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1288*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc,
1289*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) {
1290*795d594fSAndroid Build Coastguard Worker // We're not recorded to listen to this kind of event, so complain.
1291*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected field read event in tracing " << ArtMethod::PrettyMethod(method)
1292*795d594fSAndroid Build Coastguard Worker << " " << dex_pc;
1293*795d594fSAndroid Build Coastguard Worker }
1294*795d594fSAndroid Build Coastguard Worker
FieldWritten(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field,const JValue & field_value)1295*795d594fSAndroid Build Coastguard Worker void Trace::FieldWritten([[maybe_unused]] Thread* thread,
1296*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::Object> this_object,
1297*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1298*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc,
1299*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] ArtField* field,
1300*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const JValue& field_value)
1301*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1302*795d594fSAndroid Build Coastguard Worker // We're not recorded to listen to this kind of event, so complain.
1303*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected field write event in tracing " << ArtMethod::PrettyMethod(method)
1304*795d594fSAndroid Build Coastguard Worker << " " << dex_pc;
1305*795d594fSAndroid Build Coastguard Worker }
1306*795d594fSAndroid Build Coastguard Worker
MethodEntered(Thread * thread,ArtMethod * method)1307*795d594fSAndroid Build Coastguard Worker void Trace::MethodEntered(Thread* thread, ArtMethod* method) {
1308*795d594fSAndroid Build Coastguard Worker uint32_t thread_clock_diff = 0;
1309*795d594fSAndroid Build Coastguard Worker uint64_t timestamp_counter = 0;
1310*795d594fSAndroid Build Coastguard Worker ReadClocks(thread, &thread_clock_diff, ×tamp_counter);
1311*795d594fSAndroid Build Coastguard Worker LogMethodTraceEvent(thread, method, kTraceMethodEnter, thread_clock_diff, timestamp_counter);
1312*795d594fSAndroid Build Coastguard Worker }
1313*795d594fSAndroid Build Coastguard Worker
MethodExited(Thread * thread,ArtMethod * method,instrumentation::OptionalFrame frame,JValue & return_value)1314*795d594fSAndroid Build Coastguard Worker void Trace::MethodExited(Thread* thread,
1315*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1316*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] instrumentation::OptionalFrame frame,
1317*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] JValue& return_value) {
1318*795d594fSAndroid Build Coastguard Worker uint32_t thread_clock_diff = 0;
1319*795d594fSAndroid Build Coastguard Worker uint64_t timestamp_counter = 0;
1320*795d594fSAndroid Build Coastguard Worker ReadClocks(thread, &thread_clock_diff, ×tamp_counter);
1321*795d594fSAndroid Build Coastguard Worker LogMethodTraceEvent(thread, method, kTraceMethodExit, thread_clock_diff, timestamp_counter);
1322*795d594fSAndroid Build Coastguard Worker }
1323*795d594fSAndroid Build Coastguard Worker
MethodUnwind(Thread * thread,ArtMethod * method,uint32_t dex_pc)1324*795d594fSAndroid Build Coastguard Worker void Trace::MethodUnwind(Thread* thread, ArtMethod* method, [[maybe_unused]] uint32_t dex_pc) {
1325*795d594fSAndroid Build Coastguard Worker uint32_t thread_clock_diff = 0;
1326*795d594fSAndroid Build Coastguard Worker uint64_t timestamp_counter = 0;
1327*795d594fSAndroid Build Coastguard Worker ReadClocks(thread, &thread_clock_diff, ×tamp_counter);
1328*795d594fSAndroid Build Coastguard Worker LogMethodTraceEvent(thread, method, kTraceUnroll, thread_clock_diff, timestamp_counter);
1329*795d594fSAndroid Build Coastguard Worker }
1330*795d594fSAndroid Build Coastguard Worker
ExceptionThrown(Thread * thread,Handle<mirror::Throwable> exception_object)1331*795d594fSAndroid Build Coastguard Worker void Trace::ExceptionThrown([[maybe_unused]] Thread* thread,
1332*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::Throwable> exception_object)
1333*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1334*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected exception thrown event in tracing";
1335*795d594fSAndroid Build Coastguard Worker }
1336*795d594fSAndroid Build Coastguard Worker
ExceptionHandled(Thread * thread,Handle<mirror::Throwable> exception_object)1337*795d594fSAndroid Build Coastguard Worker void Trace::ExceptionHandled([[maybe_unused]] Thread* thread,
1338*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] Handle<mirror::Throwable> exception_object)
1339*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1340*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected exception thrown event in tracing";
1341*795d594fSAndroid Build Coastguard Worker }
1342*795d594fSAndroid Build Coastguard Worker
Branch(Thread *,ArtMethod * method,uint32_t,int32_t)1343*795d594fSAndroid Build Coastguard Worker void Trace::Branch(Thread* /*thread*/, ArtMethod* method,
1344*795d594fSAndroid Build Coastguard Worker uint32_t /*dex_pc*/, int32_t /*dex_pc_offset*/)
1345*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1346*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected branch event in tracing" << ArtMethod::PrettyMethod(method);
1347*795d594fSAndroid Build Coastguard Worker }
1348*795d594fSAndroid Build Coastguard Worker
WatchedFramePop(Thread * self,const ShadowFrame & frame)1349*795d594fSAndroid Build Coastguard Worker void Trace::WatchedFramePop([[maybe_unused]] Thread* self,
1350*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const ShadowFrame& frame) {
1351*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected WatchedFramePop event in tracing";
1352*795d594fSAndroid Build Coastguard Worker }
1353*795d594fSAndroid Build Coastguard Worker
ReadClocks(Thread * thread,uint32_t * thread_clock_diff,uint64_t * timestamp_counter)1354*795d594fSAndroid Build Coastguard Worker void Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint64_t* timestamp_counter) {
1355*795d594fSAndroid Build Coastguard Worker if (UseThreadCpuClock(clock_source_)) {
1356*795d594fSAndroid Build Coastguard Worker uint64_t clock_base = thread->GetTraceClockBase();
1357*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(clock_base == 0)) {
1358*795d594fSAndroid Build Coastguard Worker // First event, record the base time in the map.
1359*795d594fSAndroid Build Coastguard Worker uint64_t time = thread->GetCpuMicroTime();
1360*795d594fSAndroid Build Coastguard Worker thread->SetTraceClockBase(time);
1361*795d594fSAndroid Build Coastguard Worker } else {
1362*795d594fSAndroid Build Coastguard Worker *thread_clock_diff = thread->GetCpuMicroTime() - clock_base;
1363*795d594fSAndroid Build Coastguard Worker }
1364*795d594fSAndroid Build Coastguard Worker }
1365*795d594fSAndroid Build Coastguard Worker if (UseWallClock(clock_source_)) {
1366*795d594fSAndroid Build Coastguard Worker *timestamp_counter = GetTimestamp();
1367*795d594fSAndroid Build Coastguard Worker }
1368*795d594fSAndroid Build Coastguard Worker }
1369*795d594fSAndroid Build Coastguard Worker
GetMethodLine(const std::string & method_line,uint32_t method_index)1370*795d594fSAndroid Build Coastguard Worker std::string TraceWriter::GetMethodLine(const std::string& method_line, uint32_t method_index) {
1371*795d594fSAndroid Build Coastguard Worker return StringPrintf("%#x\t%s", (method_index << TraceActionBits), method_line.c_str());
1372*795d594fSAndroid Build Coastguard Worker }
1373*795d594fSAndroid Build Coastguard Worker
GetMethodInfoLine(ArtMethod * method)1374*795d594fSAndroid Build Coastguard Worker std::string TraceWriter::GetMethodInfoLine(ArtMethod* method) {
1375*795d594fSAndroid Build Coastguard Worker method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
1376*795d594fSAndroid Build Coastguard Worker return StringPrintf("%s\t%s\t%s\t%s\n",
1377*795d594fSAndroid Build Coastguard Worker PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(),
1378*795d594fSAndroid Build Coastguard Worker method->GetName(),
1379*795d594fSAndroid Build Coastguard Worker method->GetSignature().ToString().c_str(),
1380*795d594fSAndroid Build Coastguard Worker method->GetDeclaringClassSourceFile());
1381*795d594fSAndroid Build Coastguard Worker }
1382*795d594fSAndroid Build Coastguard Worker
RecordThreadInfo(Thread * thread)1383*795d594fSAndroid Build Coastguard Worker void TraceWriter::RecordThreadInfo(Thread* thread) {
1384*795d594fSAndroid Build Coastguard Worker // This is the first event from this thread, so first record information about the thread.
1385*795d594fSAndroid Build Coastguard Worker std::string thread_name;
1386*795d594fSAndroid Build Coastguard Worker thread->GetThreadName(thread_name);
1387*795d594fSAndroid Build Coastguard Worker
1388*795d594fSAndroid Build Coastguard Worker // In tests, we destroy VM after already detaching the current thread. We re-attach the current
1389*795d594fSAndroid Build Coastguard Worker // thread again as a "Shutdown thread" during the process of shutting down. So don't record
1390*795d594fSAndroid Build Coastguard Worker // information about shutdown threads since it overwrites the actual thread_name.
1391*795d594fSAndroid Build Coastguard Worker if (thread_name.compare("Shutdown thread") == 0) {
1392*795d594fSAndroid Build Coastguard Worker return;
1393*795d594fSAndroid Build Coastguard Worker }
1394*795d594fSAndroid Build Coastguard Worker
1395*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
1396*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1 &&
1397*795d594fSAndroid Build Coastguard Worker trace_output_mode_ != TraceOutputMode::kStreaming) {
1398*795d594fSAndroid Build Coastguard Worker threads_list_.Overwrite(GetThreadEncoding(thread->GetTid()), thread_name);
1399*795d594fSAndroid Build Coastguard Worker return;
1400*795d594fSAndroid Build Coastguard Worker }
1401*795d594fSAndroid Build Coastguard Worker
1402*795d594fSAndroid Build Coastguard Worker static constexpr size_t kThreadNameHeaderSize = 7;
1403*795d594fSAndroid Build Coastguard Worker uint8_t header[kThreadNameHeaderSize];
1404*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1) {
1405*795d594fSAndroid Build Coastguard Worker Append2LE(header, 0);
1406*795d594fSAndroid Build Coastguard Worker header[2] = kOpNewThread;
1407*795d594fSAndroid Build Coastguard Worker Append2LE(header + 3, GetThreadEncoding(thread->GetTid()));
1408*795d594fSAndroid Build Coastguard Worker } else {
1409*795d594fSAndroid Build Coastguard Worker header[0] = kThreadInfoHeaderV2;
1410*795d594fSAndroid Build Coastguard Worker Append4LE(header + 1, thread->GetTid());
1411*795d594fSAndroid Build Coastguard Worker }
1412*795d594fSAndroid Build Coastguard Worker DCHECK(thread_name.length() < (1 << 16));
1413*795d594fSAndroid Build Coastguard Worker Append2LE(header + 5, static_cast<uint16_t>(thread_name.length()));
1414*795d594fSAndroid Build Coastguard Worker
1415*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(header, kThreadNameHeaderSize) ||
1416*795d594fSAndroid Build Coastguard Worker !trace_file_->WriteFully(reinterpret_cast<const uint8_t*>(thread_name.c_str()),
1417*795d594fSAndroid Build Coastguard Worker thread_name.length())) {
1418*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1419*795d594fSAndroid Build Coastguard Worker }
1420*795d594fSAndroid Build Coastguard Worker }
1421*795d594fSAndroid Build Coastguard Worker
PreProcessTraceForMethodInfos(uintptr_t * method_trace_entries,size_t current_offset,std::unordered_map<ArtMethod *,std::string> & method_infos)1422*795d594fSAndroid Build Coastguard Worker void TraceWriter::PreProcessTraceForMethodInfos(
1423*795d594fSAndroid Build Coastguard Worker uintptr_t* method_trace_entries,
1424*795d594fSAndroid Build Coastguard Worker size_t current_offset,
1425*795d594fSAndroid Build Coastguard Worker std::unordered_map<ArtMethod*, std::string>& method_infos) {
1426*795d594fSAndroid Build Coastguard Worker // Compute the method infos before we process the entries. We don't want to assign an encoding
1427*795d594fSAndroid Build Coastguard Worker // for the method here. The expectation is that once we assign a method id we write it to the
1428*795d594fSAndroid Build Coastguard Worker // file before any other thread can see the method id. So we should assign method encoding while
1429*795d594fSAndroid Build Coastguard Worker // holding the trace_writer_lock_ and not release it till we flush the method info to the file. We
1430*795d594fSAndroid Build Coastguard Worker // don't want to flush entries to file while holding the mutator lock. We need the mutator lock to
1431*795d594fSAndroid Build Coastguard Worker // get method info. So we just precompute method infos without assigning a method encoding here.
1432*795d594fSAndroid Build Coastguard Worker // There may be a race and multiple threads computing the method info but only one of them would
1433*795d594fSAndroid Build Coastguard Worker // actually put into the method_id_map_.
1434*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
1435*795d594fSAndroid Build Coastguard Worker size_t num_entries = GetNumEntries(clock_source_);
1436*795d594fSAndroid Build Coastguard Worker DCHECK_EQ((kPerThreadBufSize - current_offset) % num_entries, 0u);
1437*795d594fSAndroid Build Coastguard Worker for (size_t entry_index = kPerThreadBufSize; entry_index != current_offset;) {
1438*795d594fSAndroid Build Coastguard Worker entry_index -= num_entries;
1439*795d594fSAndroid Build Coastguard Worker uintptr_t method_and_action = method_trace_entries[entry_index];
1440*795d594fSAndroid Build Coastguard Worker ArtMethod* method = reinterpret_cast<ArtMethod*>(method_and_action & kMaskTraceAction);
1441*795d594fSAndroid Build Coastguard Worker if (!HasMethodEncoding(method) && method_infos.find(method) == method_infos.end()) {
1442*795d594fSAndroid Build Coastguard Worker method_infos.emplace(method, GetMethodInfoLine(method));
1443*795d594fSAndroid Build Coastguard Worker }
1444*795d594fSAndroid Build Coastguard Worker }
1445*795d594fSAndroid Build Coastguard Worker }
1446*795d594fSAndroid Build Coastguard Worker
RecordMethodInfoV1(const std::string & method_info_line,uint64_t method_id)1447*795d594fSAndroid Build Coastguard Worker void TraceWriter::RecordMethodInfoV1(const std::string& method_info_line, uint64_t method_id) {
1448*795d594fSAndroid Build Coastguard Worker // Write a special block with the name.
1449*795d594fSAndroid Build Coastguard Worker std::string method_line;
1450*795d594fSAndroid Build Coastguard Worker size_t header_size;
1451*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMethodNameHeaderSize = 5;
1452*795d594fSAndroid Build Coastguard Worker DCHECK_LT(kMethodNameHeaderSize, kPerThreadBufSize);
1453*795d594fSAndroid Build Coastguard Worker uint8_t method_header[kMethodNameHeaderSize];
1454*795d594fSAndroid Build Coastguard Worker uint16_t method_line_length = static_cast<uint16_t>(method_line.length());
1455*795d594fSAndroid Build Coastguard Worker DCHECK(method_line.length() < (1 << 16));
1456*795d594fSAndroid Build Coastguard Worker // Write a special block with the name.
1457*795d594fSAndroid Build Coastguard Worker Append2LE(method_header, 0);
1458*795d594fSAndroid Build Coastguard Worker method_header[2] = kOpNewMethod;
1459*795d594fSAndroid Build Coastguard Worker method_line = GetMethodLine(method_info_line, method_id);
1460*795d594fSAndroid Build Coastguard Worker method_line_length = static_cast<uint16_t>(method_line.length());
1461*795d594fSAndroid Build Coastguard Worker Append2LE(method_header + 3, method_line_length);
1462*795d594fSAndroid Build Coastguard Worker header_size = kMethodNameHeaderSize;
1463*795d594fSAndroid Build Coastguard Worker
1464*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr = reinterpret_cast<const uint8_t*>(method_line.c_str());
1465*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(method_header, header_size) ||
1466*795d594fSAndroid Build Coastguard Worker !trace_file_->WriteFully(ptr, method_line_length)) {
1467*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1468*795d594fSAndroid Build Coastguard Worker }
1469*795d594fSAndroid Build Coastguard Worker }
1470*795d594fSAndroid Build Coastguard Worker
FlushAllThreadBuffers()1471*795d594fSAndroid Build Coastguard Worker void TraceWriter::FlushAllThreadBuffers() {
1472*795d594fSAndroid Build Coastguard Worker ScopedThreadStateChange stsc(Thread::Current(), ThreadState::kSuspended);
1473*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa(__FUNCTION__);
1474*795d594fSAndroid Build Coastguard Worker {
1475*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
1476*795d594fSAndroid Build Coastguard Worker for (Thread* thread : Runtime::Current()->GetThreadList()->GetList()) {
1477*795d594fSAndroid Build Coastguard Worker if (thread->GetMethodTraceBuffer() != nullptr) {
1478*795d594fSAndroid Build Coastguard Worker FlushBuffer(thread, /* is_sync= */ true, /* free_buffer= */ false);
1479*795d594fSAndroid Build Coastguard Worker // We cannot flush anynore data, so just break.
1480*795d594fSAndroid Build Coastguard Worker if (overflow_) {
1481*795d594fSAndroid Build Coastguard Worker break;
1482*795d594fSAndroid Build Coastguard Worker }
1483*795d594fSAndroid Build Coastguard Worker }
1484*795d594fSAndroid Build Coastguard Worker }
1485*795d594fSAndroid Build Coastguard Worker }
1486*795d594fSAndroid Build Coastguard Worker Trace::RemoveListeners();
1487*795d594fSAndroid Build Coastguard Worker return;
1488*795d594fSAndroid Build Coastguard Worker }
1489*795d594fSAndroid Build Coastguard Worker
PrepareBufferForNewEntries(Thread * thread)1490*795d594fSAndroid Build Coastguard Worker uintptr_t* TraceWriter::PrepareBufferForNewEntries(Thread* thread) {
1491*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ == TraceOutputMode::kStreaming) {
1492*795d594fSAndroid Build Coastguard Worker // In streaming mode, just flush the per-thread buffer and reuse the
1493*795d594fSAndroid Build Coastguard Worker // existing buffer for new entries.
1494*795d594fSAndroid Build Coastguard Worker FlushBuffer(thread, /* is_sync= */ false, /* free_buffer= */ false);
1495*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(overflow_, false);
1496*795d594fSAndroid Build Coastguard Worker } else {
1497*795d594fSAndroid Build Coastguard Worker // For non-streaming mode, flush all the threads to check if we have space in the common
1498*795d594fSAndroid Build Coastguard Worker // buffer to record any future events.
1499*795d594fSAndroid Build Coastguard Worker FlushAllThreadBuffers();
1500*795d594fSAndroid Build Coastguard Worker }
1501*795d594fSAndroid Build Coastguard Worker if (overflow_) {
1502*795d594fSAndroid Build Coastguard Worker return nullptr;
1503*795d594fSAndroid Build Coastguard Worker }
1504*795d594fSAndroid Build Coastguard Worker return thread->GetMethodTraceBuffer();
1505*795d594fSAndroid Build Coastguard Worker }
1506*795d594fSAndroid Build Coastguard Worker
InitializeTraceBuffers()1507*795d594fSAndroid Build Coastguard Worker void TraceWriter::InitializeTraceBuffers() {
1508*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < owner_tids_.size(); i++) {
1509*795d594fSAndroid Build Coastguard Worker owner_tids_[i].store(0);
1510*795d594fSAndroid Build Coastguard Worker }
1511*795d594fSAndroid Build Coastguard Worker
1512*795d594fSAndroid Build Coastguard Worker trace_buffer_.reset(new uintptr_t[kPerThreadBufSize * owner_tids_.size()]);
1513*795d594fSAndroid Build Coastguard Worker CHECK(trace_buffer_.get() != nullptr);
1514*795d594fSAndroid Build Coastguard Worker }
1515*795d594fSAndroid Build Coastguard Worker
AcquireTraceBuffer(size_t tid)1516*795d594fSAndroid Build Coastguard Worker uintptr_t* TraceWriter::AcquireTraceBuffer(size_t tid) {
1517*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1518*795d594fSAndroid Build Coastguard Worker
1519*795d594fSAndroid Build Coastguard Worker // Fast path, check if there is a free buffer in the pool
1520*795d594fSAndroid Build Coastguard Worker for (size_t index = 0; index < owner_tids_.size(); index++) {
1521*795d594fSAndroid Build Coastguard Worker size_t owner = 0;
1522*795d594fSAndroid Build Coastguard Worker if (owner_tids_[index].compare_exchange_strong(owner, tid)) {
1523*795d594fSAndroid Build Coastguard Worker return trace_buffer_.get() + index * kPerThreadBufSize;
1524*795d594fSAndroid Build Coastguard Worker }
1525*795d594fSAndroid Build Coastguard Worker }
1526*795d594fSAndroid Build Coastguard Worker
1527*795d594fSAndroid Build Coastguard Worker // Increment a counter so we know how many threads are potentially suspended in the tracing code.
1528*795d594fSAndroid Build Coastguard Worker // We need this when stopping tracing. We need to wait for all these threads to finish executing
1529*795d594fSAndroid Build Coastguard Worker // this code so we can safely delete the trace related data.
1530*795d594fSAndroid Build Coastguard Worker num_waiters_for_buffer_.fetch_add(1);
1531*795d594fSAndroid Build Coastguard Worker
1532*795d594fSAndroid Build Coastguard Worker uintptr_t* buffer = nullptr;
1533*795d594fSAndroid Build Coastguard Worker // If finish_tracing_ is set to true we shouldn't suspend ourselves. So check for finish_tracing_
1534*795d594fSAndroid Build Coastguard Worker // before the thread suspension. As an example, consider the following:
1535*795d594fSAndroid Build Coastguard Worker // T2 is looking for a free buffer in the loop above
1536*795d594fSAndroid Build Coastguard Worker // T1 calls stop tracing -> Sets finish_tracing_ to true -> Checks that there are no waiters ->
1537*795d594fSAndroid Build Coastguard Worker // Waiting to suspend all threads.
1538*795d594fSAndroid Build Coastguard Worker // T2 doesn't find a buffer.
1539*795d594fSAndroid Build Coastguard Worker // If T2 suspends before checking for finish_tracing_ there is a possibility T1 succeeds entering
1540*795d594fSAndroid Build Coastguard Worker // SuspendAllScope while thread T2 is still in the TraceWriter code.
1541*795d594fSAndroid Build Coastguard Worker // To avoid this, we increment the num_waiters_for_buffer and then check for finish_tracing
1542*795d594fSAndroid Build Coastguard Worker // before suspending the thread. StopTracing sets finish_tracing_ to true first and then checks
1543*795d594fSAndroid Build Coastguard Worker // for num_waiters_for_buffer. Both these are atomic variables and we use sequential consistency
1544*795d594fSAndroid Build Coastguard Worker // (acquire for load and release for stores), so all threads see the updates for these variables
1545*795d594fSAndroid Build Coastguard Worker // in the same order. That ensures we don't suspend in the tracing logic after Trace::StopTracing
1546*795d594fSAndroid Build Coastguard Worker // has returned. This is required so that we can safely delete tracing data.
1547*795d594fSAndroid Build Coastguard Worker if (self->IsThreadSuspensionAllowable() && !finish_tracing_.load()) {
1548*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kSuspended);
1549*795d594fSAndroid Build Coastguard Worker while (1) {
1550*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, buffer_pool_lock_);
1551*795d594fSAndroid Build Coastguard Worker // Tracing is being stopped, so don't wait for a free buffer. Just return early.
1552*795d594fSAndroid Build Coastguard Worker if (finish_tracing_.load()) {
1553*795d594fSAndroid Build Coastguard Worker break;
1554*795d594fSAndroid Build Coastguard Worker }
1555*795d594fSAndroid Build Coastguard Worker
1556*795d594fSAndroid Build Coastguard Worker // Check if there's a free buffer in the pool
1557*795d594fSAndroid Build Coastguard Worker for (size_t index = 0; index < owner_tids_.size(); index++) {
1558*795d594fSAndroid Build Coastguard Worker size_t owner = 0;
1559*795d594fSAndroid Build Coastguard Worker if (owner_tids_[index].compare_exchange_strong(owner, tid)) {
1560*795d594fSAndroid Build Coastguard Worker buffer = trace_buffer_.get() + index * kPerThreadBufSize;
1561*795d594fSAndroid Build Coastguard Worker break;
1562*795d594fSAndroid Build Coastguard Worker }
1563*795d594fSAndroid Build Coastguard Worker }
1564*795d594fSAndroid Build Coastguard Worker
1565*795d594fSAndroid Build Coastguard Worker // Found a buffer
1566*795d594fSAndroid Build Coastguard Worker if (buffer != nullptr) {
1567*795d594fSAndroid Build Coastguard Worker break;
1568*795d594fSAndroid Build Coastguard Worker }
1569*795d594fSAndroid Build Coastguard Worker
1570*795d594fSAndroid Build Coastguard Worker if (thread_pool_ == nullptr ||
1571*795d594fSAndroid Build Coastguard Worker (thread_pool_->GetTaskCount(self) < num_waiters_for_buffer_.load())) {
1572*795d594fSAndroid Build Coastguard Worker // We have fewer buffers than active threads, just allocate a new one.
1573*795d594fSAndroid Build Coastguard Worker break;
1574*795d594fSAndroid Build Coastguard Worker }
1575*795d594fSAndroid Build Coastguard Worker
1576*795d594fSAndroid Build Coastguard Worker buffer_available_.WaitHoldingLocks(self);
1577*795d594fSAndroid Build Coastguard Worker }
1578*795d594fSAndroid Build Coastguard Worker }
1579*795d594fSAndroid Build Coastguard Worker
1580*795d594fSAndroid Build Coastguard Worker // The thread is no longer in the suspend scope, so decrement the counter.
1581*795d594fSAndroid Build Coastguard Worker num_waiters_for_buffer_.fetch_sub(1);
1582*795d594fSAndroid Build Coastguard Worker if (num_waiters_for_buffer_.load() == 0 && finish_tracing_.load()) {
1583*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, buffer_pool_lock_);
1584*795d594fSAndroid Build Coastguard Worker num_waiters_zero_cond_.Broadcast(self);
1585*795d594fSAndroid Build Coastguard Worker }
1586*795d594fSAndroid Build Coastguard Worker
1587*795d594fSAndroid Build Coastguard Worker if (buffer == nullptr) {
1588*795d594fSAndroid Build Coastguard Worker // Allocate a new buffer. We either don't want to wait or have too few buffers.
1589*795d594fSAndroid Build Coastguard Worker buffer = new uintptr_t[kPerThreadBufSize];
1590*795d594fSAndroid Build Coastguard Worker CHECK(buffer != nullptr);
1591*795d594fSAndroid Build Coastguard Worker }
1592*795d594fSAndroid Build Coastguard Worker return buffer;
1593*795d594fSAndroid Build Coastguard Worker }
1594*795d594fSAndroid Build Coastguard Worker
StopTracing()1595*795d594fSAndroid Build Coastguard Worker void TraceWriter::StopTracing() {
1596*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1597*795d594fSAndroid Build Coastguard Worker MutexLock mu(self, buffer_pool_lock_);
1598*795d594fSAndroid Build Coastguard Worker finish_tracing_.store(true);
1599*795d594fSAndroid Build Coastguard Worker while (num_waiters_for_buffer_.load() != 0) {
1600*795d594fSAndroid Build Coastguard Worker buffer_available_.Broadcast(self);
1601*795d594fSAndroid Build Coastguard Worker num_waiters_zero_cond_.WaitHoldingLocks(self);
1602*795d594fSAndroid Build Coastguard Worker }
1603*795d594fSAndroid Build Coastguard Worker }
1604*795d594fSAndroid Build Coastguard Worker
ReleaseBuffer(int index)1605*795d594fSAndroid Build Coastguard Worker void TraceWriter::ReleaseBuffer(int index) {
1606*795d594fSAndroid Build Coastguard Worker // Only the trace_writer_ thread can release the buffer.
1607*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), buffer_pool_lock_);
1608*795d594fSAndroid Build Coastguard Worker if (index != -1) {
1609*795d594fSAndroid Build Coastguard Worker owner_tids_[index].store(0);
1610*795d594fSAndroid Build Coastguard Worker }
1611*795d594fSAndroid Build Coastguard Worker buffer_available_.Signal(Thread::Current());
1612*795d594fSAndroid Build Coastguard Worker }
1613*795d594fSAndroid Build Coastguard Worker
ReleaseBufferForThread(Thread * self)1614*795d594fSAndroid Build Coastguard Worker void TraceWriter::ReleaseBufferForThread(Thread* self) {
1615*795d594fSAndroid Build Coastguard Worker uintptr_t* buffer = self->GetMethodTraceBuffer();
1616*795d594fSAndroid Build Coastguard Worker int index = GetMethodTraceIndex(buffer);
1617*795d594fSAndroid Build Coastguard Worker if (index == -1) {
1618*795d594fSAndroid Build Coastguard Worker delete[] buffer;
1619*795d594fSAndroid Build Coastguard Worker } else {
1620*795d594fSAndroid Build Coastguard Worker ReleaseBuffer(index);
1621*795d594fSAndroid Build Coastguard Worker }
1622*795d594fSAndroid Build Coastguard Worker }
1623*795d594fSAndroid Build Coastguard Worker
GetMethodTraceIndex(uintptr_t * current_buffer)1624*795d594fSAndroid Build Coastguard Worker int TraceWriter::GetMethodTraceIndex(uintptr_t* current_buffer) {
1625*795d594fSAndroid Build Coastguard Worker if (current_buffer < trace_buffer_.get() ||
1626*795d594fSAndroid Build Coastguard Worker current_buffer > trace_buffer_.get() + (owner_tids_.size() - 1) * kPerThreadBufSize) {
1627*795d594fSAndroid Build Coastguard Worker // This was the temporary buffer we allocated.
1628*795d594fSAndroid Build Coastguard Worker return -1;
1629*795d594fSAndroid Build Coastguard Worker }
1630*795d594fSAndroid Build Coastguard Worker return (current_buffer - trace_buffer_.get()) / kPerThreadBufSize;
1631*795d594fSAndroid Build Coastguard Worker }
1632*795d594fSAndroid Build Coastguard Worker
FlushBuffer(Thread * thread,bool is_sync,bool release)1633*795d594fSAndroid Build Coastguard Worker void TraceWriter::FlushBuffer(Thread* thread, bool is_sync, bool release) {
1634*795d594fSAndroid Build Coastguard Worker uintptr_t* method_trace_entries = thread->GetMethodTraceBuffer();
1635*795d594fSAndroid Build Coastguard Worker uintptr_t** current_entry_ptr = thread->GetTraceBufferCurrEntryPtr();
1636*795d594fSAndroid Build Coastguard Worker size_t current_offset = *current_entry_ptr - method_trace_entries;
1637*795d594fSAndroid Build Coastguard Worker size_t tid = thread->GetTid();
1638*795d594fSAndroid Build Coastguard Worker DCHECK(method_trace_entries != nullptr);
1639*795d594fSAndroid Build Coastguard Worker
1640*795d594fSAndroid Build Coastguard Worker if (is_sync || thread_pool_ == nullptr) {
1641*795d594fSAndroid Build Coastguard Worker std::unordered_map<ArtMethod*, std::string> method_infos;
1642*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1) {
1643*795d594fSAndroid Build Coastguard Worker PreProcessTraceForMethodInfos(method_trace_entries, current_offset, method_infos);
1644*795d594fSAndroid Build Coastguard Worker }
1645*795d594fSAndroid Build Coastguard Worker FlushBuffer(method_trace_entries, current_offset, tid, method_infos);
1646*795d594fSAndroid Build Coastguard Worker
1647*795d594fSAndroid Build Coastguard Worker // This is a synchronous flush, so no need to allocate a new buffer. This is used either
1648*795d594fSAndroid Build Coastguard Worker // when the tracing has finished or in non-streaming mode.
1649*795d594fSAndroid Build Coastguard Worker // Just reset the buffer pointer to the initial value, so we can reuse the same buffer.
1650*795d594fSAndroid Build Coastguard Worker if (release) {
1651*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBuffer(nullptr, 0);
1652*795d594fSAndroid Build Coastguard Worker } else {
1653*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBufferCurrentEntry(kPerThreadBufSize);
1654*795d594fSAndroid Build Coastguard Worker }
1655*795d594fSAndroid Build Coastguard Worker } else {
1656*795d594fSAndroid Build Coastguard Worker int old_index = GetMethodTraceIndex(method_trace_entries);
1657*795d594fSAndroid Build Coastguard Worker // The TraceWriterTask takes the ownership of the buffer and releases the buffer once the
1658*795d594fSAndroid Build Coastguard Worker // entries are flushed.
1659*795d594fSAndroid Build Coastguard Worker thread_pool_->AddTask(
1660*795d594fSAndroid Build Coastguard Worker Thread::Current(),
1661*795d594fSAndroid Build Coastguard Worker new TraceEntriesWriterTask(this, old_index, method_trace_entries, current_offset, tid));
1662*795d594fSAndroid Build Coastguard Worker if (release) {
1663*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBuffer(nullptr, 0);
1664*795d594fSAndroid Build Coastguard Worker } else {
1665*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBuffer(AcquireTraceBuffer(tid), kPerThreadBufSize);
1666*795d594fSAndroid Build Coastguard Worker }
1667*795d594fSAndroid Build Coastguard Worker }
1668*795d594fSAndroid Build Coastguard Worker
1669*795d594fSAndroid Build Coastguard Worker return;
1670*795d594fSAndroid Build Coastguard Worker }
1671*795d594fSAndroid Build Coastguard Worker
ReadValuesFromRecord(uintptr_t * method_trace_entries,size_t record_index,MethodTraceRecord & record,bool has_thread_cpu_clock,bool has_wall_clock)1672*795d594fSAndroid Build Coastguard Worker void TraceWriter::ReadValuesFromRecord(uintptr_t* method_trace_entries,
1673*795d594fSAndroid Build Coastguard Worker size_t record_index,
1674*795d594fSAndroid Build Coastguard Worker MethodTraceRecord& record,
1675*795d594fSAndroid Build Coastguard Worker bool has_thread_cpu_clock,
1676*795d594fSAndroid Build Coastguard Worker bool has_wall_clock) {
1677*795d594fSAndroid Build Coastguard Worker uintptr_t method_and_action = method_trace_entries[record_index++];
1678*795d594fSAndroid Build Coastguard Worker record.method = reinterpret_cast<ArtMethod*>(method_and_action & kMaskTraceAction);
1679*795d594fSAndroid Build Coastguard Worker CHECK(record.method != nullptr);
1680*795d594fSAndroid Build Coastguard Worker record.action = DecodeTraceAction(method_and_action);
1681*795d594fSAndroid Build Coastguard Worker
1682*795d594fSAndroid Build Coastguard Worker record.thread_cpu_time = 0;
1683*795d594fSAndroid Build Coastguard Worker record.wall_clock_time = 0;
1684*795d594fSAndroid Build Coastguard Worker if (has_thread_cpu_clock) {
1685*795d594fSAndroid Build Coastguard Worker record.thread_cpu_time = method_trace_entries[record_index++];
1686*795d594fSAndroid Build Coastguard Worker }
1687*795d594fSAndroid Build Coastguard Worker if (has_wall_clock) {
1688*795d594fSAndroid Build Coastguard Worker uint64_t timestamp = method_trace_entries[record_index++];
1689*795d594fSAndroid Build Coastguard Worker if (art::kRuntimePointerSize == PointerSize::k32) {
1690*795d594fSAndroid Build Coastguard Worker // On 32-bit architectures timestamp is stored as two 32-bit values.
1691*795d594fSAndroid Build Coastguard Worker uint64_t high_timestamp = method_trace_entries[record_index++];
1692*795d594fSAndroid Build Coastguard Worker timestamp = (high_timestamp << 32 | timestamp);
1693*795d594fSAndroid Build Coastguard Worker }
1694*795d594fSAndroid Build Coastguard Worker record.wall_clock_time = GetMicroTime(timestamp) - start_time_;
1695*795d594fSAndroid Build Coastguard Worker }
1696*795d594fSAndroid Build Coastguard Worker }
1697*795d594fSAndroid Build Coastguard Worker
FlushEntriesFormatV1(uintptr_t * method_trace_entries,size_t tid,const std::unordered_map<ArtMethod *,std::string> & method_infos,size_t end_offset,size_t * current_index,uint8_t * buffer_ptr)1698*795d594fSAndroid Build Coastguard Worker void TraceWriter::FlushEntriesFormatV1(
1699*795d594fSAndroid Build Coastguard Worker uintptr_t* method_trace_entries,
1700*795d594fSAndroid Build Coastguard Worker size_t tid,
1701*795d594fSAndroid Build Coastguard Worker const std::unordered_map<ArtMethod*, std::string>& method_infos,
1702*795d594fSAndroid Build Coastguard Worker size_t end_offset,
1703*795d594fSAndroid Build Coastguard Worker size_t* current_index,
1704*795d594fSAndroid Build Coastguard Worker uint8_t* buffer_ptr) {
1705*795d594fSAndroid Build Coastguard Worker uint16_t thread_id = GetThreadEncoding(tid);
1706*795d594fSAndroid Build Coastguard Worker bool has_thread_cpu_clock = UseThreadCpuClock(clock_source_);
1707*795d594fSAndroid Build Coastguard Worker bool has_wall_clock = UseWallClock(clock_source_);
1708*795d594fSAndroid Build Coastguard Worker size_t buffer_index = *current_index;
1709*795d594fSAndroid Build Coastguard Worker size_t num_entries = GetNumEntries(clock_source_);
1710*795d594fSAndroid Build Coastguard Worker const size_t record_size = GetRecordSize(clock_source_, trace_format_version_);
1711*795d594fSAndroid Build Coastguard Worker
1712*795d594fSAndroid Build Coastguard Worker for (size_t entry_index = kPerThreadBufSize; entry_index != end_offset;) {
1713*795d594fSAndroid Build Coastguard Worker entry_index -= num_entries;
1714*795d594fSAndroid Build Coastguard Worker
1715*795d594fSAndroid Build Coastguard Worker MethodTraceRecord record;
1716*795d594fSAndroid Build Coastguard Worker ReadValuesFromRecord(
1717*795d594fSAndroid Build Coastguard Worker method_trace_entries, entry_index, record, has_thread_cpu_clock, has_wall_clock);
1718*795d594fSAndroid Build Coastguard Worker
1719*795d594fSAndroid Build Coastguard Worker auto [method_id, is_new_method] = GetMethodEncoding(record.method);
1720*795d594fSAndroid Build Coastguard Worker if (is_new_method && trace_output_mode_ == TraceOutputMode::kStreaming) {
1721*795d594fSAndroid Build Coastguard Worker RecordMethodInfoV1(method_infos.find(record.method)->second, method_id);
1722*795d594fSAndroid Build Coastguard Worker }
1723*795d594fSAndroid Build Coastguard Worker
1724*795d594fSAndroid Build Coastguard Worker DCHECK_LT(buffer_index + record_size, buffer_size_);
1725*795d594fSAndroid Build Coastguard Worker EncodeEventEntry(buffer_ptr + buffer_index,
1726*795d594fSAndroid Build Coastguard Worker thread_id,
1727*795d594fSAndroid Build Coastguard Worker method_id,
1728*795d594fSAndroid Build Coastguard Worker record.action,
1729*795d594fSAndroid Build Coastguard Worker record.thread_cpu_time,
1730*795d594fSAndroid Build Coastguard Worker record.wall_clock_time);
1731*795d594fSAndroid Build Coastguard Worker buffer_index += record_size;
1732*795d594fSAndroid Build Coastguard Worker }
1733*795d594fSAndroid Build Coastguard Worker *current_index = buffer_index;
1734*795d594fSAndroid Build Coastguard Worker }
1735*795d594fSAndroid Build Coastguard Worker
FlushEntriesFormatV2(uintptr_t * method_trace_entries,size_t tid,size_t num_records,size_t * current_index,uint8_t * init_buffer_ptr)1736*795d594fSAndroid Build Coastguard Worker void TraceWriter::FlushEntriesFormatV2(
1737*795d594fSAndroid Build Coastguard Worker uintptr_t* method_trace_entries,
1738*795d594fSAndroid Build Coastguard Worker size_t tid,
1739*795d594fSAndroid Build Coastguard Worker size_t num_records,
1740*795d594fSAndroid Build Coastguard Worker size_t* current_index,
1741*795d594fSAndroid Build Coastguard Worker uint8_t* init_buffer_ptr) {
1742*795d594fSAndroid Build Coastguard Worker uint8_t* current_buffer_ptr = init_buffer_ptr;
1743*795d594fSAndroid Build Coastguard Worker
1744*795d594fSAndroid Build Coastguard Worker EncodeEventBlockHeader(current_buffer_ptr, tid, num_records);
1745*795d594fSAndroid Build Coastguard Worker current_buffer_ptr += kEntryHeaderSizeV2;
1746*795d594fSAndroid Build Coastguard Worker
1747*795d594fSAndroid Build Coastguard Worker bool has_thread_cpu_clock = UseThreadCpuClock(clock_source_);
1748*795d594fSAndroid Build Coastguard Worker bool has_wall_clock = UseWallClock(clock_source_);
1749*795d594fSAndroid Build Coastguard Worker size_t num_entries = GetNumEntries(clock_source_);
1750*795d594fSAndroid Build Coastguard Worker uint32_t prev_wall_timestamp = 0;
1751*795d594fSAndroid Build Coastguard Worker uint32_t prev_thread_timestamp = 0;
1752*795d594fSAndroid Build Coastguard Worker uint64_t prev_method_action_encoding = 0;
1753*795d594fSAndroid Build Coastguard Worker size_t entry_index = kPerThreadBufSize;
1754*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < num_records; i++) {
1755*795d594fSAndroid Build Coastguard Worker entry_index -= num_entries;
1756*795d594fSAndroid Build Coastguard Worker
1757*795d594fSAndroid Build Coastguard Worker MethodTraceRecord record;
1758*795d594fSAndroid Build Coastguard Worker ReadValuesFromRecord(
1759*795d594fSAndroid Build Coastguard Worker method_trace_entries, entry_index, record, has_thread_cpu_clock, has_wall_clock);
1760*795d594fSAndroid Build Coastguard Worker
1761*795d594fSAndroid Build Coastguard Worker // TODO(mythria): Explore the possibility of using method pointer instead of having an encoding.
1762*795d594fSAndroid Build Coastguard Worker // On 64-bit this means method ids would use 8 bytes but that is okay since we only encode the
1763*795d594fSAndroid Build Coastguard Worker // full method id in the header and then encode the diff against the method id in the header.
1764*795d594fSAndroid Build Coastguard Worker // The diff is usually expected to be small.
1765*795d594fSAndroid Build Coastguard Worker uint64_t method_id = reinterpret_cast<uintptr_t>(record.method);
1766*795d594fSAndroid Build Coastguard Worker uint64_t method_action_encoding = method_id | record.action;
1767*795d594fSAndroid Build Coastguard Worker
1768*795d594fSAndroid Build Coastguard Worker int64_t method_diff = method_action_encoding - prev_method_action_encoding;
1769*795d594fSAndroid Build Coastguard Worker current_buffer_ptr = EncodeSignedLeb128(current_buffer_ptr, method_diff);
1770*795d594fSAndroid Build Coastguard Worker prev_method_action_encoding = method_action_encoding;
1771*795d594fSAndroid Build Coastguard Worker
1772*795d594fSAndroid Build Coastguard Worker if (has_wall_clock) {
1773*795d594fSAndroid Build Coastguard Worker current_buffer_ptr =
1774*795d594fSAndroid Build Coastguard Worker EncodeUnsignedLeb128(current_buffer_ptr, (record.wall_clock_time - prev_wall_timestamp));
1775*795d594fSAndroid Build Coastguard Worker prev_wall_timestamp = record.wall_clock_time;
1776*795d594fSAndroid Build Coastguard Worker }
1777*795d594fSAndroid Build Coastguard Worker
1778*795d594fSAndroid Build Coastguard Worker if (has_thread_cpu_clock) {
1779*795d594fSAndroid Build Coastguard Worker current_buffer_ptr = EncodeUnsignedLeb128(current_buffer_ptr,
1780*795d594fSAndroid Build Coastguard Worker (record.thread_cpu_time - prev_thread_timestamp));
1781*795d594fSAndroid Build Coastguard Worker prev_thread_timestamp = record.thread_cpu_time;
1782*795d594fSAndroid Build Coastguard Worker }
1783*795d594fSAndroid Build Coastguard Worker }
1784*795d594fSAndroid Build Coastguard Worker
1785*795d594fSAndroid Build Coastguard Worker // Update the total size of the block excluding header size.
1786*795d594fSAndroid Build Coastguard Worker uint8_t* total_size_loc = init_buffer_ptr + kEntryHeaderSizeV2 - 4;
1787*795d594fSAndroid Build Coastguard Worker Append4LE(total_size_loc, current_buffer_ptr - (init_buffer_ptr + kEntryHeaderSizeV2));
1788*795d594fSAndroid Build Coastguard Worker *current_index += current_buffer_ptr - init_buffer_ptr;
1789*795d594fSAndroid Build Coastguard Worker }
1790*795d594fSAndroid Build Coastguard Worker
FlushBuffer(uintptr_t * method_trace_entries,size_t current_offset,size_t tid,const std::unordered_map<ArtMethod *,std::string> & method_infos)1791*795d594fSAndroid Build Coastguard Worker void TraceWriter::FlushBuffer(uintptr_t* method_trace_entries,
1792*795d594fSAndroid Build Coastguard Worker size_t current_offset,
1793*795d594fSAndroid Build Coastguard Worker size_t tid,
1794*795d594fSAndroid Build Coastguard Worker const std::unordered_map<ArtMethod*, std::string>& method_infos) {
1795*795d594fSAndroid Build Coastguard Worker // Take a trace_writer_lock_ to serialize writes across threads. We also need to allocate a unique
1796*795d594fSAndroid Build Coastguard Worker // method id for each method. We do that by maintaining a map from id to method for each newly
1797*795d594fSAndroid Build Coastguard Worker // seen method. trace_writer_lock_ is required to serialize these.
1798*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
1799*795d594fSAndroid Build Coastguard Worker size_t current_index = 0;
1800*795d594fSAndroid Build Coastguard Worker uint8_t* buffer_ptr = buf_.get();
1801*795d594fSAndroid Build Coastguard Worker size_t buffer_size = buffer_size_;
1802*795d594fSAndroid Build Coastguard Worker
1803*795d594fSAndroid Build Coastguard Worker size_t num_entries = GetNumEntries(clock_source_);
1804*795d594fSAndroid Build Coastguard Worker size_t num_records = (kPerThreadBufSize - current_offset) / num_entries;
1805*795d594fSAndroid Build Coastguard Worker DCHECK_EQ((kPerThreadBufSize - current_offset) % num_entries, 0u);
1806*795d594fSAndroid Build Coastguard Worker const size_t record_size = GetRecordSize(clock_source_, trace_format_version_);
1807*795d594fSAndroid Build Coastguard Worker DCHECK_LT(record_size, kPerThreadBufSize);
1808*795d594fSAndroid Build Coastguard Worker
1809*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ != TraceOutputMode::kStreaming) {
1810*795d594fSAndroid Build Coastguard Worker // In non-streaming mode we only flush to file at the end, so retain the earlier data. If the
1811*795d594fSAndroid Build Coastguard Worker // buffer is full we don't process any more entries.
1812*795d594fSAndroid Build Coastguard Worker current_index = cur_offset_;
1813*795d594fSAndroid Build Coastguard Worker
1814*795d594fSAndroid Build Coastguard Worker // Check if there is sufficient place in the buffer for non-streaming case. If not return early.
1815*795d594fSAndroid Build Coastguard Worker if (cur_offset_ + record_size * num_records >= buffer_size) {
1816*795d594fSAndroid Build Coastguard Worker overflow_ = true;
1817*795d594fSAndroid Build Coastguard Worker return;
1818*795d594fSAndroid Build Coastguard Worker }
1819*795d594fSAndroid Build Coastguard Worker }
1820*795d594fSAndroid Build Coastguard Worker num_records_ += num_records;
1821*795d594fSAndroid Build Coastguard Worker
1822*795d594fSAndroid Build Coastguard Worker DCHECK_GT(buffer_size_, record_size * num_entries);
1823*795d594fSAndroid Build Coastguard Worker if (trace_format_version_ == Trace::kFormatV1) {
1824*795d594fSAndroid Build Coastguard Worker FlushEntriesFormatV1(
1825*795d594fSAndroid Build Coastguard Worker method_trace_entries, tid, method_infos, current_offset, ¤t_index, buffer_ptr);
1826*795d594fSAndroid Build Coastguard Worker } else {
1827*795d594fSAndroid Build Coastguard Worker FlushEntriesFormatV2(
1828*795d594fSAndroid Build Coastguard Worker method_trace_entries, tid, num_records, ¤t_index, buffer_ptr + current_index);
1829*795d594fSAndroid Build Coastguard Worker }
1830*795d594fSAndroid Build Coastguard Worker
1831*795d594fSAndroid Build Coastguard Worker if (trace_output_mode_ == TraceOutputMode::kStreaming) {
1832*795d594fSAndroid Build Coastguard Worker // Flush the contents of buffer to file.
1833*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buffer_ptr, current_index)) {
1834*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1835*795d594fSAndroid Build Coastguard Worker }
1836*795d594fSAndroid Build Coastguard Worker } else {
1837*795d594fSAndroid Build Coastguard Worker // In non-streaming mode, we keep the data in the buffer and write to the
1838*795d594fSAndroid Build Coastguard Worker // file when tracing has stopped. Just updated the offset of the buffer.
1839*795d594fSAndroid Build Coastguard Worker cur_offset_ = current_index;
1840*795d594fSAndroid Build Coastguard Worker }
1841*795d594fSAndroid Build Coastguard Worker return;
1842*795d594fSAndroid Build Coastguard Worker }
1843*795d594fSAndroid Build Coastguard Worker
LogMethodTraceEvent(Thread * thread,ArtMethod * method,TraceAction action,uint32_t thread_clock_diff,uint64_t timestamp_counter)1844*795d594fSAndroid Build Coastguard Worker void Trace::LogMethodTraceEvent(Thread* thread,
1845*795d594fSAndroid Build Coastguard Worker ArtMethod* method,
1846*795d594fSAndroid Build Coastguard Worker TraceAction action,
1847*795d594fSAndroid Build Coastguard Worker uint32_t thread_clock_diff,
1848*795d594fSAndroid Build Coastguard Worker uint64_t timestamp_counter) {
1849*795d594fSAndroid Build Coastguard Worker // This method is called in both tracing modes (method and sampling). In sampling mode, this
1850*795d594fSAndroid Build Coastguard Worker // method is only called by the sampling thread. In method tracing mode, it can be called
1851*795d594fSAndroid Build Coastguard Worker // concurrently.
1852*795d594fSAndroid Build Coastguard Worker
1853*795d594fSAndroid Build Coastguard Worker uintptr_t* method_trace_buffer = thread->GetMethodTraceBuffer();
1854*795d594fSAndroid Build Coastguard Worker uintptr_t** current_entry_ptr = thread->GetTraceBufferCurrEntryPtr();
1855*795d594fSAndroid Build Coastguard Worker // Initialize the buffer lazily. It's just simpler to keep the creation at one place.
1856*795d594fSAndroid Build Coastguard Worker if (method_trace_buffer == nullptr) {
1857*795d594fSAndroid Build Coastguard Worker method_trace_buffer = trace_writer_->AcquireTraceBuffer(thread->GetTid());
1858*795d594fSAndroid Build Coastguard Worker DCHECK(method_trace_buffer != nullptr);
1859*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBuffer(method_trace_buffer, kPerThreadBufSize);
1860*795d594fSAndroid Build Coastguard Worker trace_writer_->RecordThreadInfo(thread);
1861*795d594fSAndroid Build Coastguard Worker }
1862*795d594fSAndroid Build Coastguard Worker
1863*795d594fSAndroid Build Coastguard Worker if (trace_writer_->HasOverflow()) {
1864*795d594fSAndroid Build Coastguard Worker // In non-streaming modes, we stop recoding events once the buffer is full. Just reset the
1865*795d594fSAndroid Build Coastguard Worker // index, so we don't go to runtime for each method.
1866*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBufferCurrentEntry(kPerThreadBufSize);
1867*795d594fSAndroid Build Coastguard Worker return;
1868*795d594fSAndroid Build Coastguard Worker }
1869*795d594fSAndroid Build Coastguard Worker
1870*795d594fSAndroid Build Coastguard Worker size_t required_entries = GetNumEntries(clock_source_);
1871*795d594fSAndroid Build Coastguard Worker if (*current_entry_ptr - required_entries < method_trace_buffer) {
1872*795d594fSAndroid Build Coastguard Worker // This returns nullptr in non-streaming mode if there's an overflow and we cannot record any
1873*795d594fSAndroid Build Coastguard Worker // more entries. In streaming mode, it returns nullptr if it fails to allocate a new buffer.
1874*795d594fSAndroid Build Coastguard Worker method_trace_buffer = trace_writer_->PrepareBufferForNewEntries(thread);
1875*795d594fSAndroid Build Coastguard Worker if (method_trace_buffer == nullptr) {
1876*795d594fSAndroid Build Coastguard Worker thread->SetMethodTraceBufferCurrentEntry(kPerThreadBufSize);
1877*795d594fSAndroid Build Coastguard Worker return;
1878*795d594fSAndroid Build Coastguard Worker }
1879*795d594fSAndroid Build Coastguard Worker }
1880*795d594fSAndroid Build Coastguard Worker *current_entry_ptr = *current_entry_ptr - required_entries;
1881*795d594fSAndroid Build Coastguard Worker
1882*795d594fSAndroid Build Coastguard Worker // Record entry in per-thread trace buffer.
1883*795d594fSAndroid Build Coastguard Worker int entry_index = 0;
1884*795d594fSAndroid Build Coastguard Worker uintptr_t* current_entry = *current_entry_ptr;
1885*795d594fSAndroid Build Coastguard Worker // Ensure we always use the non-obsolete version of the method so that entry/exit events have the
1886*795d594fSAndroid Build Coastguard Worker // same pointer value.
1887*795d594fSAndroid Build Coastguard Worker method = method->GetNonObsoleteMethod();
1888*795d594fSAndroid Build Coastguard Worker current_entry[entry_index++] = reinterpret_cast<uintptr_t>(method) | action;
1889*795d594fSAndroid Build Coastguard Worker if (UseThreadCpuClock(clock_source_)) {
1890*795d594fSAndroid Build Coastguard Worker current_entry[entry_index++] = thread_clock_diff;
1891*795d594fSAndroid Build Coastguard Worker }
1892*795d594fSAndroid Build Coastguard Worker if (UseWallClock(clock_source_)) {
1893*795d594fSAndroid Build Coastguard Worker if (art::kRuntimePointerSize == PointerSize::k32) {
1894*795d594fSAndroid Build Coastguard Worker // On 32-bit architectures store timestamp counter as two 32-bit values.
1895*795d594fSAndroid Build Coastguard Worker current_entry[entry_index++] = static_cast<uint32_t>(timestamp_counter);
1896*795d594fSAndroid Build Coastguard Worker current_entry[entry_index++] = timestamp_counter >> 32;
1897*795d594fSAndroid Build Coastguard Worker } else {
1898*795d594fSAndroid Build Coastguard Worker current_entry[entry_index++] = timestamp_counter;
1899*795d594fSAndroid Build Coastguard Worker }
1900*795d594fSAndroid Build Coastguard Worker }
1901*795d594fSAndroid Build Coastguard Worker }
1902*795d594fSAndroid Build Coastguard Worker
EncodeEventEntry(uint8_t * ptr,uint16_t thread_id,uint32_t method_index,TraceAction action,uint32_t thread_clock_diff,uint32_t wall_clock_diff)1903*795d594fSAndroid Build Coastguard Worker void TraceWriter::EncodeEventEntry(uint8_t* ptr,
1904*795d594fSAndroid Build Coastguard Worker uint16_t thread_id,
1905*795d594fSAndroid Build Coastguard Worker uint32_t method_index,
1906*795d594fSAndroid Build Coastguard Worker TraceAction action,
1907*795d594fSAndroid Build Coastguard Worker uint32_t thread_clock_diff,
1908*795d594fSAndroid Build Coastguard Worker uint32_t wall_clock_diff) {
1909*795d594fSAndroid Build Coastguard Worker static constexpr size_t kPacketSize = 14U; // The maximum size of data in a packet.
1910*795d594fSAndroid Build Coastguard Worker DCHECK(method_index < (1 << (32 - TraceActionBits)));
1911*795d594fSAndroid Build Coastguard Worker uint32_t method_value = (method_index << TraceActionBits) | action;
1912*795d594fSAndroid Build Coastguard Worker Append2LE(ptr, thread_id);
1913*795d594fSAndroid Build Coastguard Worker Append4LE(ptr + 2, method_value);
1914*795d594fSAndroid Build Coastguard Worker ptr += 6;
1915*795d594fSAndroid Build Coastguard Worker
1916*795d594fSAndroid Build Coastguard Worker if (UseThreadCpuClock(clock_source_)) {
1917*795d594fSAndroid Build Coastguard Worker Append4LE(ptr, thread_clock_diff);
1918*795d594fSAndroid Build Coastguard Worker ptr += 4;
1919*795d594fSAndroid Build Coastguard Worker }
1920*795d594fSAndroid Build Coastguard Worker if (UseWallClock(clock_source_)) {
1921*795d594fSAndroid Build Coastguard Worker Append4LE(ptr, wall_clock_diff);
1922*795d594fSAndroid Build Coastguard Worker }
1923*795d594fSAndroid Build Coastguard Worker static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect.");
1924*795d594fSAndroid Build Coastguard Worker }
1925*795d594fSAndroid Build Coastguard Worker
EncodeEventBlockHeader(uint8_t * ptr,uint32_t thread_id,uint32_t num_records)1926*795d594fSAndroid Build Coastguard Worker void TraceWriter::EncodeEventBlockHeader(uint8_t* ptr, uint32_t thread_id, uint32_t num_records) {
1927*795d594fSAndroid Build Coastguard Worker ptr[0] = kEntryHeaderV2;
1928*795d594fSAndroid Build Coastguard Worker Append4LE(ptr + 1, thread_id);
1929*795d594fSAndroid Build Coastguard Worker // This specifies the total number of records encoded in the block using lebs.
1930*795d594fSAndroid Build Coastguard Worker DCHECK_LT(num_records, 1u << 24);
1931*795d594fSAndroid Build Coastguard Worker Append3LE(ptr + 5, num_records);
1932*795d594fSAndroid Build Coastguard Worker }
1933*795d594fSAndroid Build Coastguard Worker
EnsureSpace(uint8_t * buffer,size_t * current_index,size_t buffer_size,size_t required_size)1934*795d594fSAndroid Build Coastguard Worker void TraceWriter::EnsureSpace(uint8_t* buffer,
1935*795d594fSAndroid Build Coastguard Worker size_t* current_index,
1936*795d594fSAndroid Build Coastguard Worker size_t buffer_size,
1937*795d594fSAndroid Build Coastguard Worker size_t required_size) {
1938*795d594fSAndroid Build Coastguard Worker if (*current_index + required_size < buffer_size) {
1939*795d594fSAndroid Build Coastguard Worker return;
1940*795d594fSAndroid Build Coastguard Worker }
1941*795d594fSAndroid Build Coastguard Worker
1942*795d594fSAndroid Build Coastguard Worker if (!trace_file_->WriteFully(buffer, *current_index)) {
1943*795d594fSAndroid Build Coastguard Worker PLOG(WARNING) << "Failed streaming a tracing event.";
1944*795d594fSAndroid Build Coastguard Worker }
1945*795d594fSAndroid Build Coastguard Worker *current_index = 0;
1946*795d594fSAndroid Build Coastguard Worker }
1947*795d594fSAndroid Build Coastguard Worker
DumpMethodList(std::ostream & os)1948*795d594fSAndroid Build Coastguard Worker void TraceWriter::DumpMethodList(std::ostream& os) {
1949*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
1950*795d594fSAndroid Build Coastguard Worker for (auto const& entry : art_method_id_map_) {
1951*795d594fSAndroid Build Coastguard Worker os << GetMethodLine(GetMethodInfoLine(entry.first), entry.second);
1952*795d594fSAndroid Build Coastguard Worker }
1953*795d594fSAndroid Build Coastguard Worker }
1954*795d594fSAndroid Build Coastguard Worker
DumpThreadList(std::ostream & os)1955*795d594fSAndroid Build Coastguard Worker void TraceWriter::DumpThreadList(std::ostream& os) {
1956*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), trace_writer_lock_);
1957*795d594fSAndroid Build Coastguard Worker for (const auto& it : threads_list_) {
1958*795d594fSAndroid Build Coastguard Worker os << it.first << "\t" << it.second << "\n";
1959*795d594fSAndroid Build Coastguard Worker }
1960*795d594fSAndroid Build Coastguard Worker }
1961*795d594fSAndroid Build Coastguard Worker
GetOutputMode()1962*795d594fSAndroid Build Coastguard Worker TraceOutputMode Trace::GetOutputMode() {
1963*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1964*795d594fSAndroid Build Coastguard Worker CHECK(the_trace_ != nullptr) << "Trace output mode requested, but no trace currently running";
1965*795d594fSAndroid Build Coastguard Worker return the_trace_->trace_writer_->GetOutputMode();
1966*795d594fSAndroid Build Coastguard Worker }
1967*795d594fSAndroid Build Coastguard Worker
GetMode()1968*795d594fSAndroid Build Coastguard Worker Trace::TraceMode Trace::GetMode() {
1969*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1970*795d594fSAndroid Build Coastguard Worker CHECK(the_trace_ != nullptr) << "Trace mode requested, but no trace currently running";
1971*795d594fSAndroid Build Coastguard Worker return the_trace_->trace_mode_;
1972*795d594fSAndroid Build Coastguard Worker }
1973*795d594fSAndroid Build Coastguard Worker
GetFlags()1974*795d594fSAndroid Build Coastguard Worker int Trace::GetFlags() {
1975*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1976*795d594fSAndroid Build Coastguard Worker CHECK(the_trace_ != nullptr) << "Trace flags requested, but no trace currently running";
1977*795d594fSAndroid Build Coastguard Worker return the_trace_->flags_;
1978*795d594fSAndroid Build Coastguard Worker }
1979*795d594fSAndroid Build Coastguard Worker
GetIntervalInMillis()1980*795d594fSAndroid Build Coastguard Worker int Trace::GetIntervalInMillis() {
1981*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1982*795d594fSAndroid Build Coastguard Worker CHECK(the_trace_ != nullptr) << "Trace interval requested, but no trace currently running";
1983*795d594fSAndroid Build Coastguard Worker return the_trace_->interval_us_;
1984*795d594fSAndroid Build Coastguard Worker }
1985*795d594fSAndroid Build Coastguard Worker
GetBufferSize()1986*795d594fSAndroid Build Coastguard Worker size_t Trace::GetBufferSize() {
1987*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1988*795d594fSAndroid Build Coastguard Worker CHECK(the_trace_ != nullptr) << "Trace buffer size requested, but no trace currently running";
1989*795d594fSAndroid Build Coastguard Worker return the_trace_->trace_writer_->GetBufferSize();
1990*795d594fSAndroid Build Coastguard Worker }
1991*795d594fSAndroid Build Coastguard Worker
IsTracingEnabled()1992*795d594fSAndroid Build Coastguard Worker bool Trace::IsTracingEnabled() {
1993*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::trace_lock_);
1994*795d594fSAndroid Build Coastguard Worker return the_trace_ != nullptr;
1995*795d594fSAndroid Build Coastguard Worker }
1996*795d594fSAndroid Build Coastguard Worker
IsTracingEnabledLocked()1997*795d594fSAndroid Build Coastguard Worker bool Trace::IsTracingEnabledLocked() {
1998*795d594fSAndroid Build Coastguard Worker return the_trace_ != nullptr;
1999*795d594fSAndroid Build Coastguard Worker }
2000*795d594fSAndroid Build Coastguard Worker
2001*795d594fSAndroid Build Coastguard Worker } // namespace art
2002