1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "src/trace_processor/importers/proto/perf_sample_tracker.h"
17
18 #include <inttypes.h>
19 #include <stdio.h>
20
21 #include "src/trace_processor/importers/common/track_tracker.h"
22 #include "src/trace_processor/storage/trace_storage.h"
23 #include "src/trace_processor/types/trace_processor_context.h"
24
25 #include "protos/perfetto/common/perf_events.pbzero.h"
26 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
27 #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
28
29 namespace perfetto {
30 namespace trace_processor {
31
32 namespace {
33 // Follow perf tool naming convention.
StringifyCounter(int32_t counter)34 const char* StringifyCounter(int32_t counter) {
35 using protos::pbzero::PerfEvents;
36 switch (counter) {
37 case (PerfEvents::SW_CPU_CLOCK):
38 return "cpu-clock";
39 case (PerfEvents::SW_PAGE_FAULTS):
40 return "page-faults";
41 case (PerfEvents::HW_CPU_CYCLES):
42 return "cpu-cycles";
43 case (PerfEvents::HW_INSTRUCTIONS):
44 return "instructions";
45 default:
46 break;
47 }
48 return "unknown";
49 }
50
InternTimebaseCounterName(protos::pbzero::TracePacketDefaults::Decoder * defaults,TraceProcessorContext * context)51 StringId InternTimebaseCounterName(
52 protos::pbzero::TracePacketDefaults::Decoder* defaults,
53 TraceProcessorContext* context) {
54 using namespace protos::pbzero;
55 PerfSampleDefaults::Decoder perf_defaults(defaults->perf_sample_defaults());
56 PerfEvents::Timebase::Decoder timebase(perf_defaults.timebase());
57
58 if (timebase.counter() != PerfEvents::UNKNOWN_COUNTER) {
59 return context->storage->InternString(StringifyCounter(timebase.counter()));
60 }
61 PerfEvents::Tracepoint::Decoder tracepoint(timebase.tracepoint());
62 return context->storage->InternString(tracepoint.name());
63 }
64 } // namespace
65
GetSamplingStreamInfo(uint32_t seq_id,uint32_t cpu,protos::pbzero::TracePacketDefaults::Decoder * nullable_defaults)66 PerfSampleTracker::SamplingStreamInfo PerfSampleTracker::GetSamplingStreamInfo(
67 uint32_t seq_id,
68 uint32_t cpu,
69 protos::pbzero::TracePacketDefaults::Decoder* nullable_defaults) {
70 auto seq_it = seq_state_.find(seq_id);
71 if (seq_it == seq_state_.end()) {
72 seq_it = seq_state_.emplace(seq_id, next_perf_session_id_++).first;
73 }
74 SequenceState* seq_state = &seq_it->second;
75 uint32_t session_id = seq_state->perf_session_id;
76
77 auto cpu_it = seq_state->per_cpu.find(cpu);
78 if (cpu_it != seq_state->per_cpu.end())
79 return {seq_state->perf_session_id, cpu_it->second.timebase_track_id};
80
81 // No defaults means legacy producer implementation, assume default timebase
82 // of per-cpu timer. Always the case for Android R builds, and it isn't worth
83 // guaranteeing support for intermediate S builds in this aspect.
84 StringId name_id = kNullStringId;
85 if (!nullable_defaults || !nullable_defaults->has_perf_sample_defaults()) {
86 name_id = context_->storage->InternString(
87 StringifyCounter(protos::pbzero::PerfEvents::SW_CPU_CLOCK));
88 } else {
89 name_id = InternTimebaseCounterName(nullable_defaults, context_);
90 }
91
92 TrackId timebase_track_id = context_->track_tracker->CreatePerfCounterTrack(
93 name_id, session_id, cpu, /*is_timebase=*/true);
94
95 seq_state->per_cpu.emplace(cpu, timebase_track_id);
96
97 return {session_id, timebase_track_id};
98 }
99
100 } // namespace trace_processor
101 } // namespace perfetto
102