xref: /aosp_15_r20/system/extras/simpleperf/event_selection_set.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #include "event_selection_set.h"
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <algorithm>
20*288bf522SAndroid Build Coastguard Worker #include <atomic>
21*288bf522SAndroid Build Coastguard Worker #include <thread>
22*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
23*288bf522SAndroid Build Coastguard Worker 
24*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
25*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
27*288bf522SAndroid Build Coastguard Worker 
28*288bf522SAndroid Build Coastguard Worker #include "ETMRecorder.h"
29*288bf522SAndroid Build Coastguard Worker #include "IOEventLoop.h"
30*288bf522SAndroid Build Coastguard Worker #include "RecordReadThread.h"
31*288bf522SAndroid Build Coastguard Worker #include "environment.h"
32*288bf522SAndroid Build Coastguard Worker #include "event_attr.h"
33*288bf522SAndroid Build Coastguard Worker #include "event_type.h"
34*288bf522SAndroid Build Coastguard Worker #include "perf_regs.h"
35*288bf522SAndroid Build Coastguard Worker #include "tracing.h"
36*288bf522SAndroid Build Coastguard Worker #include "utils.h"
37*288bf522SAndroid Build Coastguard Worker 
38*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
39*288bf522SAndroid Build Coastguard Worker 
40*288bf522SAndroid Build Coastguard Worker using android::base::StringPrintf;
41*288bf522SAndroid Build Coastguard Worker 
IsBranchSamplingSupported()42*288bf522SAndroid Build Coastguard Worker bool IsBranchSamplingSupported() {
43*288bf522SAndroid Build Coastguard Worker   const EventType* type = FindEventTypeByName("BR_INST_RETIRED.NEAR_TAKEN");
44*288bf522SAndroid Build Coastguard Worker   if (type == nullptr) {
45*288bf522SAndroid Build Coastguard Worker     return false;
46*288bf522SAndroid Build Coastguard Worker   }
47*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
48*288bf522SAndroid Build Coastguard Worker   attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
49*288bf522SAndroid Build Coastguard Worker   attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
50*288bf522SAndroid Build Coastguard Worker   return IsEventAttrSupported(attr, type->name);
51*288bf522SAndroid Build Coastguard Worker }
52*288bf522SAndroid Build Coastguard Worker 
IsDwarfCallChainSamplingSupported()53*288bf522SAndroid Build Coastguard Worker bool IsDwarfCallChainSamplingSupported() {
54*288bf522SAndroid Build Coastguard Worker   if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(3, 18)) {
55*288bf522SAndroid Build Coastguard Worker     // Skip test on kernel >= 3.18, which has all patches needed to support dwarf callchain.
56*288bf522SAndroid Build Coastguard Worker     return true;
57*288bf522SAndroid Build Coastguard Worker   }
58*288bf522SAndroid Build Coastguard Worker   const EventType* type = FindEventTypeByName("cpu-clock");
59*288bf522SAndroid Build Coastguard Worker   if (type == nullptr) {
60*288bf522SAndroid Build Coastguard Worker     return false;
61*288bf522SAndroid Build Coastguard Worker   }
62*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
63*288bf522SAndroid Build Coastguard Worker   attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
64*288bf522SAndroid Build Coastguard Worker   attr.exclude_callchain_user = 1;
65*288bf522SAndroid Build Coastguard Worker   attr.sample_regs_user = GetSupportedRegMask(GetTargetArch());
66*288bf522SAndroid Build Coastguard Worker   attr.sample_stack_user = 8192;
67*288bf522SAndroid Build Coastguard Worker   return IsEventAttrSupported(attr, type->name);
68*288bf522SAndroid Build Coastguard Worker }
69*288bf522SAndroid Build Coastguard Worker 
IsDumpingRegsForTracepointEventsSupported()70*288bf522SAndroid Build Coastguard Worker bool IsDumpingRegsForTracepointEventsSupported() {
71*288bf522SAndroid Build Coastguard Worker   if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(4, 2)) {
72*288bf522SAndroid Build Coastguard Worker     // Kernel >= 4.2 has patch "5b09a094f2 arm64: perf: Fix callchain parse error with kernel
73*288bf522SAndroid Build Coastguard Worker     // tracepoint events". So no need to test.
74*288bf522SAndroid Build Coastguard Worker     return true;
75*288bf522SAndroid Build Coastguard Worker   }
76*288bf522SAndroid Build Coastguard Worker   const EventType* event_type = FindEventTypeByName("sched:sched_switch", false);
77*288bf522SAndroid Build Coastguard Worker   if (event_type == nullptr) {
78*288bf522SAndroid Build Coastguard Worker     return false;
79*288bf522SAndroid Build Coastguard Worker   }
80*288bf522SAndroid Build Coastguard Worker   std::atomic<bool> done(false);
81*288bf522SAndroid Build Coastguard Worker   std::atomic<pid_t> thread_id(0);
82*288bf522SAndroid Build Coastguard Worker   std::thread thread([&]() {
83*288bf522SAndroid Build Coastguard Worker     thread_id = gettid();
84*288bf522SAndroid Build Coastguard Worker     while (!done) {
85*288bf522SAndroid Build Coastguard Worker       usleep(1);
86*288bf522SAndroid Build Coastguard Worker     }
87*288bf522SAndroid Build Coastguard Worker     usleep(1);  // Make a sched out to generate one sample.
88*288bf522SAndroid Build Coastguard Worker   });
89*288bf522SAndroid Build Coastguard Worker   while (thread_id == 0) {
90*288bf522SAndroid Build Coastguard Worker     usleep(1);
91*288bf522SAndroid Build Coastguard Worker   }
92*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(*event_type);
93*288bf522SAndroid Build Coastguard Worker   attr.freq = 0;
94*288bf522SAndroid Build Coastguard Worker   attr.sample_period = 1;
95*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<EventFd> event_fd =
96*288bf522SAndroid Build Coastguard Worker       EventFd::OpenEventFile(attr, thread_id, -1, nullptr, event_type->name);
97*288bf522SAndroid Build Coastguard Worker   if (event_fd == nullptr || !event_fd->CreateMappedBuffer(4, true)) {
98*288bf522SAndroid Build Coastguard Worker     done = true;
99*288bf522SAndroid Build Coastguard Worker     thread.join();
100*288bf522SAndroid Build Coastguard Worker     return false;
101*288bf522SAndroid Build Coastguard Worker   }
102*288bf522SAndroid Build Coastguard Worker   done = true;
103*288bf522SAndroid Build Coastguard Worker   thread.join();
104*288bf522SAndroid Build Coastguard Worker 
105*288bf522SAndroid Build Coastguard Worker   // There are small chances that we don't see samples immediately after joining the thread on
106*288bf522SAndroid Build Coastguard Worker   // cuttlefish, probably due to data synchronization between cpus. To avoid flaky tests, use a
107*288bf522SAndroid Build Coastguard Worker   // loop to wait for samples.
108*288bf522SAndroid Build Coastguard Worker   for (int timeout = 0; timeout < 1000; timeout++) {
109*288bf522SAndroid Build Coastguard Worker     std::vector<char> buffer = event_fd->GetAvailableMmapData();
110*288bf522SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<Record>> records =
111*288bf522SAndroid Build Coastguard Worker         ReadRecordsFromBuffer(attr, buffer.data(), buffer.size());
112*288bf522SAndroid Build Coastguard Worker     for (auto& r : records) {
113*288bf522SAndroid Build Coastguard Worker       if (r->type() == PERF_RECORD_SAMPLE) {
114*288bf522SAndroid Build Coastguard Worker         auto& record = *static_cast<SampleRecord*>(r.get());
115*288bf522SAndroid Build Coastguard Worker         return record.ip_data.ip != 0;
116*288bf522SAndroid Build Coastguard Worker       }
117*288bf522SAndroid Build Coastguard Worker     }
118*288bf522SAndroid Build Coastguard Worker     usleep(1);
119*288bf522SAndroid Build Coastguard Worker   }
120*288bf522SAndroid Build Coastguard Worker   return false;
121*288bf522SAndroid Build Coastguard Worker }
122*288bf522SAndroid Build Coastguard Worker 
IsSettingClockIdSupported()123*288bf522SAndroid Build Coastguard Worker bool IsSettingClockIdSupported() {
124*288bf522SAndroid Build Coastguard Worker   // Do the real check only once and keep the result in a static variable.
125*288bf522SAndroid Build Coastguard Worker   static int is_supported = -1;
126*288bf522SAndroid Build Coastguard Worker   if (is_supported == -1) {
127*288bf522SAndroid Build Coastguard Worker     is_supported = 0;
128*288bf522SAndroid Build Coastguard Worker     if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(4, 1)) {
129*288bf522SAndroid Build Coastguard Worker       // Kernel >= 4.1 has patch "34f43927 perf: Add per event clockid support". So no need to test.
130*288bf522SAndroid Build Coastguard Worker       is_supported = 1;
131*288bf522SAndroid Build Coastguard Worker     } else if (const EventType* type = FindEventTypeByName("cpu-clock"); type != nullptr) {
132*288bf522SAndroid Build Coastguard Worker       // Check if the kernel supports setting clockid, which was added in kernel 4.0. Just check
133*288bf522SAndroid Build Coastguard Worker       // with one clockid is enough. Because all needed clockids were supported before kernel 4.0.
134*288bf522SAndroid Build Coastguard Worker       perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
135*288bf522SAndroid Build Coastguard Worker       attr.use_clockid = 1;
136*288bf522SAndroid Build Coastguard Worker       attr.clockid = CLOCK_MONOTONIC;
137*288bf522SAndroid Build Coastguard Worker       is_supported = IsEventAttrSupported(attr, type->name) ? 1 : 0;
138*288bf522SAndroid Build Coastguard Worker     }
139*288bf522SAndroid Build Coastguard Worker   }
140*288bf522SAndroid Build Coastguard Worker   return is_supported;
141*288bf522SAndroid Build Coastguard Worker }
142*288bf522SAndroid Build Coastguard Worker 
IsMmap2Supported()143*288bf522SAndroid Build Coastguard Worker bool IsMmap2Supported() {
144*288bf522SAndroid Build Coastguard Worker   if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(3, 12)) {
145*288bf522SAndroid Build Coastguard Worker     // Kernel >= 3.12 has patch "13d7a2410 perf: Add attr->mmap2 attribute to an event". So no need
146*288bf522SAndroid Build Coastguard Worker     // to test.
147*288bf522SAndroid Build Coastguard Worker     return true;
148*288bf522SAndroid Build Coastguard Worker   }
149*288bf522SAndroid Build Coastguard Worker   const EventType* type = FindEventTypeByName("cpu-clock");
150*288bf522SAndroid Build Coastguard Worker   if (type == nullptr) {
151*288bf522SAndroid Build Coastguard Worker     return false;
152*288bf522SAndroid Build Coastguard Worker   }
153*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
154*288bf522SAndroid Build Coastguard Worker   attr.mmap2 = 1;
155*288bf522SAndroid Build Coastguard Worker   return IsEventAttrSupported(attr, type->name);
156*288bf522SAndroid Build Coastguard Worker }
157*288bf522SAndroid Build Coastguard Worker 
IsHardwareEventSupported()158*288bf522SAndroid Build Coastguard Worker bool IsHardwareEventSupported() {
159*288bf522SAndroid Build Coastguard Worker   const EventType* type = FindEventTypeByName("cpu-cycles");
160*288bf522SAndroid Build Coastguard Worker   if (type == nullptr) {
161*288bf522SAndroid Build Coastguard Worker     return false;
162*288bf522SAndroid Build Coastguard Worker   }
163*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
164*288bf522SAndroid Build Coastguard Worker   return IsEventAttrSupported(attr, type->name);
165*288bf522SAndroid Build Coastguard Worker }
166*288bf522SAndroid Build Coastguard Worker 
IsSwitchRecordSupported()167*288bf522SAndroid Build Coastguard Worker bool IsSwitchRecordSupported() {
168*288bf522SAndroid Build Coastguard Worker   // Kernel >= 4.3 has patch "45ac1403f perf: Add PERF_RECORD_SWITCH to indicate context switches".
169*288bf522SAndroid Build Coastguard Worker   auto version = GetKernelVersion();
170*288bf522SAndroid Build Coastguard Worker   return version && version.value() >= std::make_pair(4, 3);
171*288bf522SAndroid Build Coastguard Worker }
172*288bf522SAndroid Build Coastguard Worker 
ToString() const173*288bf522SAndroid Build Coastguard Worker std::string AddrFilter::ToString() const {
174*288bf522SAndroid Build Coastguard Worker   switch (type) {
175*288bf522SAndroid Build Coastguard Worker     case FILE_RANGE:
176*288bf522SAndroid Build Coastguard Worker       return StringPrintf("filter 0x%" PRIx64 "/0x%" PRIx64 "@%s", addr, size, file_path.c_str());
177*288bf522SAndroid Build Coastguard Worker     case AddrFilter::FILE_START:
178*288bf522SAndroid Build Coastguard Worker       return StringPrintf("start 0x%" PRIx64 "@%s", addr, file_path.c_str());
179*288bf522SAndroid Build Coastguard Worker     case AddrFilter::FILE_STOP:
180*288bf522SAndroid Build Coastguard Worker       return StringPrintf("stop 0x%" PRIx64 "@%s", addr, file_path.c_str());
181*288bf522SAndroid Build Coastguard Worker     case AddrFilter::KERNEL_RANGE:
182*288bf522SAndroid Build Coastguard Worker       return StringPrintf("filter 0x%" PRIx64 "/0x%" PRIx64, addr, size);
183*288bf522SAndroid Build Coastguard Worker     case AddrFilter::KERNEL_START:
184*288bf522SAndroid Build Coastguard Worker       return StringPrintf("start 0x%" PRIx64, addr);
185*288bf522SAndroid Build Coastguard Worker     case AddrFilter::KERNEL_STOP:
186*288bf522SAndroid Build Coastguard Worker       return StringPrintf("stop 0x%" PRIx64, addr);
187*288bf522SAndroid Build Coastguard Worker   }
188*288bf522SAndroid Build Coastguard Worker }
189*288bf522SAndroid Build Coastguard Worker 
EventSelectionSet(bool for_stat_cmd)190*288bf522SAndroid Build Coastguard Worker EventSelectionSet::EventSelectionSet(bool for_stat_cmd)
191*288bf522SAndroid Build Coastguard Worker     : for_stat_cmd_(for_stat_cmd), loop_(new IOEventLoop) {}
192*288bf522SAndroid Build Coastguard Worker 
~EventSelectionSet()193*288bf522SAndroid Build Coastguard Worker EventSelectionSet::~EventSelectionSet() {}
194*288bf522SAndroid Build Coastguard Worker 
BuildAndCheckEventSelection(const std::string & event_name,bool first_event,EventSelection * selection)195*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::BuildAndCheckEventSelection(const std::string& event_name, bool first_event,
196*288bf522SAndroid Build Coastguard Worker                                                     EventSelection* selection) {
197*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<EventTypeAndModifier> event_type = ParseEventType(event_name);
198*288bf522SAndroid Build Coastguard Worker   if (event_type == nullptr) {
199*288bf522SAndroid Build Coastguard Worker     return false;
200*288bf522SAndroid Build Coastguard Worker   }
201*288bf522SAndroid Build Coastguard Worker   if (for_stat_cmd_) {
202*288bf522SAndroid Build Coastguard Worker     if (event_type->event_type.name == "cpu-clock" || event_type->event_type.name == "task-clock") {
203*288bf522SAndroid Build Coastguard Worker       if (event_type->exclude_user || event_type->exclude_kernel) {
204*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Modifier u and modifier k used in event type " << event_type->event_type.name
205*288bf522SAndroid Build Coastguard Worker                    << " are not supported by the kernel.";
206*288bf522SAndroid Build Coastguard Worker         return false;
207*288bf522SAndroid Build Coastguard Worker       }
208*288bf522SAndroid Build Coastguard Worker     }
209*288bf522SAndroid Build Coastguard Worker   }
210*288bf522SAndroid Build Coastguard Worker   selection->event_type_modifier = *event_type;
211*288bf522SAndroid Build Coastguard Worker   selection->event_attr = CreateDefaultPerfEventAttr(event_type->event_type);
212*288bf522SAndroid Build Coastguard Worker   selection->event_attr.exclude_user = event_type->exclude_user;
213*288bf522SAndroid Build Coastguard Worker   selection->event_attr.exclude_kernel = event_type->exclude_kernel;
214*288bf522SAndroid Build Coastguard Worker   selection->event_attr.exclude_hv = event_type->exclude_hv;
215*288bf522SAndroid Build Coastguard Worker   selection->event_attr.exclude_host = event_type->exclude_host;
216*288bf522SAndroid Build Coastguard Worker   selection->event_attr.exclude_guest = event_type->exclude_guest;
217*288bf522SAndroid Build Coastguard Worker   selection->event_attr.precise_ip = event_type->precise_ip;
218*288bf522SAndroid Build Coastguard Worker   if (IsEtmEventType(event_type->event_type.type)) {
219*288bf522SAndroid Build Coastguard Worker     auto& etm_recorder = ETMRecorder::GetInstance();
220*288bf522SAndroid Build Coastguard Worker     if (auto result = etm_recorder.CheckEtmSupport(); !result.ok()) {
221*288bf522SAndroid Build Coastguard Worker       LOG(ERROR) << result.error();
222*288bf522SAndroid Build Coastguard Worker       return false;
223*288bf522SAndroid Build Coastguard Worker     }
224*288bf522SAndroid Build Coastguard Worker     ETMRecorder::GetInstance().SetEtmPerfEventAttr(&selection->event_attr);
225*288bf522SAndroid Build Coastguard Worker     // The kernel (rb_allocate_aux) allocates high order of pages based on aux_watermark.
226*288bf522SAndroid Build Coastguard Worker     // To avoid that, use aux_watermark <= 1 page size.
227*288bf522SAndroid Build Coastguard Worker     selection->event_attr.aux_watermark = 4096;
228*288bf522SAndroid Build Coastguard Worker   }
229*288bf522SAndroid Build Coastguard Worker   bool set_default_sample_freq = false;
230*288bf522SAndroid Build Coastguard Worker   if (!for_stat_cmd_) {
231*288bf522SAndroid Build Coastguard Worker     if (event_type->event_type.type == PERF_TYPE_TRACEPOINT) {
232*288bf522SAndroid Build Coastguard Worker       selection->event_attr.freq = 0;
233*288bf522SAndroid Build Coastguard Worker       selection->event_attr.sample_period = DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT;
234*288bf522SAndroid Build Coastguard Worker     } else if (IsEtmEventType(event_type->event_type.type)) {
235*288bf522SAndroid Build Coastguard Worker       // ETM recording has no sample frequency to adjust. Using sample frequency only wastes time
236*288bf522SAndroid Build Coastguard Worker       // enabling/disabling etm devices. So don't adjust frequency by default.
237*288bf522SAndroid Build Coastguard Worker       selection->event_attr.freq = 0;
238*288bf522SAndroid Build Coastguard Worker       selection->event_attr.sample_period = 1;
239*288bf522SAndroid Build Coastguard Worker       // An ETM event can't be enabled without mmap aux buffer. So disable it by default.
240*288bf522SAndroid Build Coastguard Worker       selection->event_attr.disabled = 1;
241*288bf522SAndroid Build Coastguard Worker     } else {
242*288bf522SAndroid Build Coastguard Worker       selection->event_attr.freq = 1;
243*288bf522SAndroid Build Coastguard Worker       // Set default sample freq here may print msg "Adjust sample freq to max allowed sample
244*288bf522SAndroid Build Coastguard Worker       // freq". But this is misleading. Because default sample freq may not be the final sample
245*288bf522SAndroid Build Coastguard Worker       // freq we use. So use minimum sample freq (1) here.
246*288bf522SAndroid Build Coastguard Worker       selection->event_attr.sample_freq = 1;
247*288bf522SAndroid Build Coastguard Worker       set_default_sample_freq = true;
248*288bf522SAndroid Build Coastguard Worker     }
249*288bf522SAndroid Build Coastguard Worker     // We only need to dump mmap and comm records for the first event type. Because all event types
250*288bf522SAndroid Build Coastguard Worker     // are monitoring the same processes.
251*288bf522SAndroid Build Coastguard Worker     if (first_event) {
252*288bf522SAndroid Build Coastguard Worker       selection->event_attr.mmap = 1;
253*288bf522SAndroid Build Coastguard Worker       selection->event_attr.comm = 1;
254*288bf522SAndroid Build Coastguard Worker       if (IsMmap2Supported()) {
255*288bf522SAndroid Build Coastguard Worker         selection->event_attr.mmap2 = 1;
256*288bf522SAndroid Build Coastguard Worker       }
257*288bf522SAndroid Build Coastguard Worker     }
258*288bf522SAndroid Build Coastguard Worker   }
259*288bf522SAndroid Build Coastguard Worker   // PMU events are provided by kernel, so they should be supported
260*288bf522SAndroid Build Coastguard Worker   if (!event_type->event_type.IsPmuEvent() &&
261*288bf522SAndroid Build Coastguard Worker       !IsEventAttrSupported(selection->event_attr, selection->event_type_modifier.name)) {
262*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "Event type '" << event_type->name << "' is not supported on the device";
263*288bf522SAndroid Build Coastguard Worker     return false;
264*288bf522SAndroid Build Coastguard Worker   }
265*288bf522SAndroid Build Coastguard Worker   if (set_default_sample_freq) {
266*288bf522SAndroid Build Coastguard Worker     selection->event_attr.sample_freq = DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT;
267*288bf522SAndroid Build Coastguard Worker   }
268*288bf522SAndroid Build Coastguard Worker 
269*288bf522SAndroid Build Coastguard Worker   selection->event_fds.clear();
270*288bf522SAndroid Build Coastguard Worker 
271*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
272*288bf522SAndroid Build Coastguard Worker     for (const auto& sel : group.selections) {
273*288bf522SAndroid Build Coastguard Worker       if (sel.event_type_modifier.name == selection->event_type_modifier.name) {
274*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Event type '" << sel.event_type_modifier.name << "' appears more than once";
275*288bf522SAndroid Build Coastguard Worker         return false;
276*288bf522SAndroid Build Coastguard Worker       }
277*288bf522SAndroid Build Coastguard Worker     }
278*288bf522SAndroid Build Coastguard Worker   }
279*288bf522SAndroid Build Coastguard Worker   return true;
280*288bf522SAndroid Build Coastguard Worker }
281*288bf522SAndroid Build Coastguard Worker 
AddEventType(const std::string & event_name)282*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::AddEventType(const std::string& event_name) {
283*288bf522SAndroid Build Coastguard Worker   return AddEventGroup(std::vector<std::string>(1, event_name));
284*288bf522SAndroid Build Coastguard Worker }
285*288bf522SAndroid Build Coastguard Worker 
AddEventType(const std::string & event_name,const SampleRate & sample_rate)286*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::AddEventType(const std::string& event_name, const SampleRate& sample_rate) {
287*288bf522SAndroid Build Coastguard Worker   if (!AddEventGroup(std::vector<std::string>(1, event_name))) {
288*288bf522SAndroid Build Coastguard Worker     return false;
289*288bf522SAndroid Build Coastguard Worker   }
290*288bf522SAndroid Build Coastguard Worker   SetSampleRateForGroup(groups_.back(), sample_rate);
291*288bf522SAndroid Build Coastguard Worker   return true;
292*288bf522SAndroid Build Coastguard Worker }
293*288bf522SAndroid Build Coastguard Worker 
AddEventGroup(const std::vector<std::string> & event_names)294*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::AddEventGroup(const std::vector<std::string>& event_names) {
295*288bf522SAndroid Build Coastguard Worker   EventSelectionGroup group;
296*288bf522SAndroid Build Coastguard Worker   bool first_event = groups_.empty();
297*288bf522SAndroid Build Coastguard Worker   bool first_in_group = true;
298*288bf522SAndroid Build Coastguard Worker   for (const auto& event_name : event_names) {
299*288bf522SAndroid Build Coastguard Worker     EventSelection selection;
300*288bf522SAndroid Build Coastguard Worker     if (!BuildAndCheckEventSelection(event_name, first_event, &selection)) {
301*288bf522SAndroid Build Coastguard Worker       return false;
302*288bf522SAndroid Build Coastguard Worker     }
303*288bf522SAndroid Build Coastguard Worker     if (IsEtmEventType(selection.event_attr.type)) {
304*288bf522SAndroid Build Coastguard Worker       has_aux_trace_ = true;
305*288bf522SAndroid Build Coastguard Worker     }
306*288bf522SAndroid Build Coastguard Worker     if (first_in_group) {
307*288bf522SAndroid Build Coastguard Worker       auto& event_type = selection.event_type_modifier.event_type;
308*288bf522SAndroid Build Coastguard Worker       if (event_type.IsPmuEvent()) {
309*288bf522SAndroid Build Coastguard Worker         selection.allowed_cpus = event_type.GetPmuCpumask();
310*288bf522SAndroid Build Coastguard Worker       }
311*288bf522SAndroid Build Coastguard Worker     }
312*288bf522SAndroid Build Coastguard Worker     first_event = false;
313*288bf522SAndroid Build Coastguard Worker     first_in_group = false;
314*288bf522SAndroid Build Coastguard Worker     group.selections.emplace_back(std::move(selection));
315*288bf522SAndroid Build Coastguard Worker   }
316*288bf522SAndroid Build Coastguard Worker   if (sample_rate_) {
317*288bf522SAndroid Build Coastguard Worker     SetSampleRateForGroup(group, sample_rate_.value());
318*288bf522SAndroid Build Coastguard Worker   }
319*288bf522SAndroid Build Coastguard Worker   if (cpus_) {
320*288bf522SAndroid Build Coastguard Worker     group.cpus = cpus_.value();
321*288bf522SAndroid Build Coastguard Worker   }
322*288bf522SAndroid Build Coastguard Worker   groups_.emplace_back(std::move(group));
323*288bf522SAndroid Build Coastguard Worker   UnionSampleType();
324*288bf522SAndroid Build Coastguard Worker   return true;
325*288bf522SAndroid Build Coastguard Worker }
326*288bf522SAndroid Build Coastguard Worker 
AddCounters(const std::vector<std::string> & event_names)327*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::AddCounters(const std::vector<std::string>& event_names) {
328*288bf522SAndroid Build Coastguard Worker   CHECK(!groups_.empty());
329*288bf522SAndroid Build Coastguard Worker   if (groups_.size() > 1) {
330*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to add counters. Only one event group is allowed.";
331*288bf522SAndroid Build Coastguard Worker     return false;
332*288bf522SAndroid Build Coastguard Worker   }
333*288bf522SAndroid Build Coastguard Worker   for (const auto& event_name : event_names) {
334*288bf522SAndroid Build Coastguard Worker     EventSelection selection;
335*288bf522SAndroid Build Coastguard Worker     if (!BuildAndCheckEventSelection(event_name, false, &selection)) {
336*288bf522SAndroid Build Coastguard Worker       return false;
337*288bf522SAndroid Build Coastguard Worker     }
338*288bf522SAndroid Build Coastguard Worker     // Use a big sample_period to avoid getting samples for added counters.
339*288bf522SAndroid Build Coastguard Worker     selection.event_attr.freq = 0;
340*288bf522SAndroid Build Coastguard Worker     selection.event_attr.sample_period = INFINITE_SAMPLE_PERIOD;
341*288bf522SAndroid Build Coastguard Worker     selection.event_attr.inherit = 0;
342*288bf522SAndroid Build Coastguard Worker     groups_[0].selections.emplace_back(std::move(selection));
343*288bf522SAndroid Build Coastguard Worker   }
344*288bf522SAndroid Build Coastguard Worker   // Add counters in each sample.
345*288bf522SAndroid Build Coastguard Worker   for (auto& selection : groups_[0].selections) {
346*288bf522SAndroid Build Coastguard Worker     selection.event_attr.sample_type |= PERF_SAMPLE_READ;
347*288bf522SAndroid Build Coastguard Worker     selection.event_attr.read_format |= PERF_FORMAT_GROUP;
348*288bf522SAndroid Build Coastguard Worker   }
349*288bf522SAndroid Build Coastguard Worker   return true;
350*288bf522SAndroid Build Coastguard Worker }
351*288bf522SAndroid Build Coastguard Worker 
GetEvents() const352*288bf522SAndroid Build Coastguard Worker std::vector<const EventType*> EventSelectionSet::GetEvents() const {
353*288bf522SAndroid Build Coastguard Worker   std::vector<const EventType*> result;
354*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
355*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
356*288bf522SAndroid Build Coastguard Worker       result.push_back(&selection.event_type_modifier.event_type);
357*288bf522SAndroid Build Coastguard Worker     }
358*288bf522SAndroid Build Coastguard Worker   }
359*288bf522SAndroid Build Coastguard Worker   return result;
360*288bf522SAndroid Build Coastguard Worker }
361*288bf522SAndroid Build Coastguard Worker 
GetTracepointEvents() const362*288bf522SAndroid Build Coastguard Worker std::vector<const EventType*> EventSelectionSet::GetTracepointEvents() const {
363*288bf522SAndroid Build Coastguard Worker   std::vector<const EventType*> result;
364*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
365*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
366*288bf522SAndroid Build Coastguard Worker       if (selection.event_type_modifier.event_type.type == PERF_TYPE_TRACEPOINT) {
367*288bf522SAndroid Build Coastguard Worker         result.push_back(&selection.event_type_modifier.event_type);
368*288bf522SAndroid Build Coastguard Worker       }
369*288bf522SAndroid Build Coastguard Worker     }
370*288bf522SAndroid Build Coastguard Worker   }
371*288bf522SAndroid Build Coastguard Worker   return result;
372*288bf522SAndroid Build Coastguard Worker }
373*288bf522SAndroid Build Coastguard Worker 
ExcludeKernel() const374*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::ExcludeKernel() const {
375*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
376*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
377*288bf522SAndroid Build Coastguard Worker       if (!selection.event_type_modifier.exclude_kernel) {
378*288bf522SAndroid Build Coastguard Worker         return false;
379*288bf522SAndroid Build Coastguard Worker       }
380*288bf522SAndroid Build Coastguard Worker     }
381*288bf522SAndroid Build Coastguard Worker   }
382*288bf522SAndroid Build Coastguard Worker   return true;
383*288bf522SAndroid Build Coastguard Worker }
384*288bf522SAndroid Build Coastguard Worker 
GetEventAttrWithId() const385*288bf522SAndroid Build Coastguard Worker EventAttrIds EventSelectionSet::GetEventAttrWithId() const {
386*288bf522SAndroid Build Coastguard Worker   EventAttrIds result;
387*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
388*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
389*288bf522SAndroid Build Coastguard Worker       std::vector<uint64_t> ids;
390*288bf522SAndroid Build Coastguard Worker       for (const auto& fd : selection.event_fds) {
391*288bf522SAndroid Build Coastguard Worker         ids.push_back(fd->Id());
392*288bf522SAndroid Build Coastguard Worker       }
393*288bf522SAndroid Build Coastguard Worker       result.resize(result.size() + 1);
394*288bf522SAndroid Build Coastguard Worker       result.back().attr = selection.event_attr;
395*288bf522SAndroid Build Coastguard Worker       result.back().ids = std::move(ids);
396*288bf522SAndroid Build Coastguard Worker     }
397*288bf522SAndroid Build Coastguard Worker   }
398*288bf522SAndroid Build Coastguard Worker   return result;
399*288bf522SAndroid Build Coastguard Worker }
400*288bf522SAndroid Build Coastguard Worker 
GetEventNamesById() const401*288bf522SAndroid Build Coastguard Worker std::unordered_map<uint64_t, std::string> EventSelectionSet::GetEventNamesById() const {
402*288bf522SAndroid Build Coastguard Worker   std::unordered_map<uint64_t, std::string> result;
403*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
404*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
405*288bf522SAndroid Build Coastguard Worker       for (const auto& fd : selection.event_fds) {
406*288bf522SAndroid Build Coastguard Worker         result[fd->Id()] = selection.event_type_modifier.name;
407*288bf522SAndroid Build Coastguard Worker       }
408*288bf522SAndroid Build Coastguard Worker     }
409*288bf522SAndroid Build Coastguard Worker   }
410*288bf522SAndroid Build Coastguard Worker   return result;
411*288bf522SAndroid Build Coastguard Worker }
412*288bf522SAndroid Build Coastguard Worker 
GetCpusById() const413*288bf522SAndroid Build Coastguard Worker std::unordered_map<uint64_t, int> EventSelectionSet::GetCpusById() const {
414*288bf522SAndroid Build Coastguard Worker   std::unordered_map<uint64_t, int> result;
415*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
416*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
417*288bf522SAndroid Build Coastguard Worker       for (const auto& fd : selection.event_fds) {
418*288bf522SAndroid Build Coastguard Worker         result[fd->Id()] = fd->Cpu();
419*288bf522SAndroid Build Coastguard Worker       }
420*288bf522SAndroid Build Coastguard Worker     }
421*288bf522SAndroid Build Coastguard Worker   }
422*288bf522SAndroid Build Coastguard Worker   return result;
423*288bf522SAndroid Build Coastguard Worker }
424*288bf522SAndroid Build Coastguard Worker 
GetHardwareCountersForCpus() const425*288bf522SAndroid Build Coastguard Worker std::map<int, size_t> EventSelectionSet::GetHardwareCountersForCpus() const {
426*288bf522SAndroid Build Coastguard Worker   std::map<int, size_t> cpu_map;
427*288bf522SAndroid Build Coastguard Worker   std::vector<int> online_cpus = GetOnlineCpus();
428*288bf522SAndroid Build Coastguard Worker 
429*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
430*288bf522SAndroid Build Coastguard Worker     size_t hardware_events = 0;
431*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
432*288bf522SAndroid Build Coastguard Worker       if (selection.event_type_modifier.event_type.IsHardwareEvent()) {
433*288bf522SAndroid Build Coastguard Worker         hardware_events++;
434*288bf522SAndroid Build Coastguard Worker       }
435*288bf522SAndroid Build Coastguard Worker     }
436*288bf522SAndroid Build Coastguard Worker     const std::vector<int>* pcpus = group.cpus.empty() ? &online_cpus : &group.cpus;
437*288bf522SAndroid Build Coastguard Worker     for (int cpu : *pcpus) {
438*288bf522SAndroid Build Coastguard Worker       cpu_map[cpu] += hardware_events;
439*288bf522SAndroid Build Coastguard Worker     }
440*288bf522SAndroid Build Coastguard Worker   }
441*288bf522SAndroid Build Coastguard Worker   return cpu_map;
442*288bf522SAndroid Build Coastguard Worker }
443*288bf522SAndroid Build Coastguard Worker 
444*288bf522SAndroid Build Coastguard Worker // Union the sample type of different event attrs can make reading sample
445*288bf522SAndroid Build Coastguard Worker // records in perf.data easier.
UnionSampleType()446*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::UnionSampleType() {
447*288bf522SAndroid Build Coastguard Worker   uint64_t sample_type = 0;
448*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
449*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
450*288bf522SAndroid Build Coastguard Worker       sample_type |= selection.event_attr.sample_type;
451*288bf522SAndroid Build Coastguard Worker     }
452*288bf522SAndroid Build Coastguard Worker   }
453*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
454*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
455*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_type = sample_type;
456*288bf522SAndroid Build Coastguard Worker     }
457*288bf522SAndroid Build Coastguard Worker   }
458*288bf522SAndroid Build Coastguard Worker }
459*288bf522SAndroid Build Coastguard Worker 
SetEnableCondition(bool enable_on_open,bool enable_on_exec)460*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetEnableCondition(bool enable_on_open, bool enable_on_exec) {
461*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
462*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
463*288bf522SAndroid Build Coastguard Worker       selection.event_attr.disabled = !enable_on_open;
464*288bf522SAndroid Build Coastguard Worker       selection.event_attr.enable_on_exec = enable_on_exec;
465*288bf522SAndroid Build Coastguard Worker     }
466*288bf522SAndroid Build Coastguard Worker   }
467*288bf522SAndroid Build Coastguard Worker }
468*288bf522SAndroid Build Coastguard Worker 
IsEnabledOnExec() const469*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::IsEnabledOnExec() const {
470*288bf522SAndroid Build Coastguard Worker   for (const auto& group : groups_) {
471*288bf522SAndroid Build Coastguard Worker     for (const auto& selection : group.selections) {
472*288bf522SAndroid Build Coastguard Worker       if (!selection.event_attr.enable_on_exec) {
473*288bf522SAndroid Build Coastguard Worker         return false;
474*288bf522SAndroid Build Coastguard Worker       }
475*288bf522SAndroid Build Coastguard Worker     }
476*288bf522SAndroid Build Coastguard Worker   }
477*288bf522SAndroid Build Coastguard Worker   return true;
478*288bf522SAndroid Build Coastguard Worker }
479*288bf522SAndroid Build Coastguard Worker 
SampleIdAll()480*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SampleIdAll() {
481*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
482*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
483*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_id_all = 1;
484*288bf522SAndroid Build Coastguard Worker     }
485*288bf522SAndroid Build Coastguard Worker   }
486*288bf522SAndroid Build Coastguard Worker }
487*288bf522SAndroid Build Coastguard Worker 
SetSampleRateForNewEvents(const SampleRate & rate)488*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetSampleRateForNewEvents(const SampleRate& rate) {
489*288bf522SAndroid Build Coastguard Worker   sample_rate_ = rate;
490*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
491*288bf522SAndroid Build Coastguard Worker     if (!group.set_sample_rate) {
492*288bf522SAndroid Build Coastguard Worker       SetSampleRateForGroup(group, rate);
493*288bf522SAndroid Build Coastguard Worker     }
494*288bf522SAndroid Build Coastguard Worker   }
495*288bf522SAndroid Build Coastguard Worker }
496*288bf522SAndroid Build Coastguard Worker 
SetCpusForNewEvents(const std::vector<int> & cpus)497*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetCpusForNewEvents(const std::vector<int>& cpus) {
498*288bf522SAndroid Build Coastguard Worker   cpus_ = cpus;
499*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
500*288bf522SAndroid Build Coastguard Worker     if (group.cpus.empty()) {
501*288bf522SAndroid Build Coastguard Worker       group.cpus = cpus_.value();
502*288bf522SAndroid Build Coastguard Worker     }
503*288bf522SAndroid Build Coastguard Worker   }
504*288bf522SAndroid Build Coastguard Worker }
505*288bf522SAndroid Build Coastguard Worker 
SetSampleRateForGroup(EventSelectionSet::EventSelectionGroup & group,const SampleRate & rate)506*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetSampleRateForGroup(EventSelectionSet::EventSelectionGroup& group,
507*288bf522SAndroid Build Coastguard Worker                                               const SampleRate& rate) {
508*288bf522SAndroid Build Coastguard Worker   group.set_sample_rate = true;
509*288bf522SAndroid Build Coastguard Worker   for (auto& selection : group.selections) {
510*288bf522SAndroid Build Coastguard Worker     if (rate.UseFreq()) {
511*288bf522SAndroid Build Coastguard Worker       selection.event_attr.freq = 1;
512*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_freq = rate.sample_freq;
513*288bf522SAndroid Build Coastguard Worker     } else {
514*288bf522SAndroid Build Coastguard Worker       selection.event_attr.freq = 0;
515*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_period = rate.sample_period;
516*288bf522SAndroid Build Coastguard Worker     }
517*288bf522SAndroid Build Coastguard Worker   }
518*288bf522SAndroid Build Coastguard Worker }
519*288bf522SAndroid Build Coastguard Worker 
SetBranchSampling(uint64_t branch_sample_type)520*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::SetBranchSampling(uint64_t branch_sample_type) {
521*288bf522SAndroid Build Coastguard Worker   if (branch_sample_type != 0 &&
522*288bf522SAndroid Build Coastguard Worker       (branch_sample_type & (PERF_SAMPLE_BRANCH_ANY | PERF_SAMPLE_BRANCH_ANY_CALL |
523*288bf522SAndroid Build Coastguard Worker                              PERF_SAMPLE_BRANCH_ANY_RETURN | PERF_SAMPLE_BRANCH_IND_CALL)) == 0) {
524*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid branch_sample_type: 0x" << std::hex << branch_sample_type;
525*288bf522SAndroid Build Coastguard Worker     return false;
526*288bf522SAndroid Build Coastguard Worker   }
527*288bf522SAndroid Build Coastguard Worker   if (branch_sample_type != 0 && !IsBranchSamplingSupported()) {
528*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "branch stack sampling is not supported on this device.";
529*288bf522SAndroid Build Coastguard Worker     return false;
530*288bf522SAndroid Build Coastguard Worker   }
531*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
532*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
533*288bf522SAndroid Build Coastguard Worker       perf_event_attr& attr = selection.event_attr;
534*288bf522SAndroid Build Coastguard Worker       if (branch_sample_type != 0) {
535*288bf522SAndroid Build Coastguard Worker         attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
536*288bf522SAndroid Build Coastguard Worker       } else {
537*288bf522SAndroid Build Coastguard Worker         attr.sample_type &= ~PERF_SAMPLE_BRANCH_STACK;
538*288bf522SAndroid Build Coastguard Worker       }
539*288bf522SAndroid Build Coastguard Worker       attr.branch_sample_type = branch_sample_type;
540*288bf522SAndroid Build Coastguard Worker     }
541*288bf522SAndroid Build Coastguard Worker   }
542*288bf522SAndroid Build Coastguard Worker   return true;
543*288bf522SAndroid Build Coastguard Worker }
544*288bf522SAndroid Build Coastguard Worker 
EnableFpCallChainSampling()545*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::EnableFpCallChainSampling() {
546*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
547*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
548*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
549*288bf522SAndroid Build Coastguard Worker     }
550*288bf522SAndroid Build Coastguard Worker   }
551*288bf522SAndroid Build Coastguard Worker }
552*288bf522SAndroid Build Coastguard Worker 
EnableDwarfCallChainSampling(uint32_t dump_stack_size)553*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::EnableDwarfCallChainSampling(uint32_t dump_stack_size) {
554*288bf522SAndroid Build Coastguard Worker   if (!IsDwarfCallChainSamplingSupported()) {
555*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "dwarf callchain sampling is not supported on this device.";
556*288bf522SAndroid Build Coastguard Worker     return false;
557*288bf522SAndroid Build Coastguard Worker   }
558*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
559*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
560*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_type |=
561*288bf522SAndroid Build Coastguard Worker           PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
562*288bf522SAndroid Build Coastguard Worker       selection.event_attr.exclude_callchain_user = 1;
563*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_regs_user = GetSupportedRegMask(GetMachineArch());
564*288bf522SAndroid Build Coastguard Worker       selection.event_attr.sample_stack_user = dump_stack_size;
565*288bf522SAndroid Build Coastguard Worker     }
566*288bf522SAndroid Build Coastguard Worker   }
567*288bf522SAndroid Build Coastguard Worker   return true;
568*288bf522SAndroid Build Coastguard Worker }
569*288bf522SAndroid Build Coastguard Worker 
SetInherit(bool enable)570*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetInherit(bool enable) {
571*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
572*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
573*288bf522SAndroid Build Coastguard Worker       selection.event_attr.inherit = (enable ? 1 : 0);
574*288bf522SAndroid Build Coastguard Worker     }
575*288bf522SAndroid Build Coastguard Worker   }
576*288bf522SAndroid Build Coastguard Worker }
577*288bf522SAndroid Build Coastguard Worker 
SetClockId(int clock_id)578*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetClockId(int clock_id) {
579*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
580*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
581*288bf522SAndroid Build Coastguard Worker       selection.event_attr.use_clockid = 1;
582*288bf522SAndroid Build Coastguard Worker       selection.event_attr.clockid = clock_id;
583*288bf522SAndroid Build Coastguard Worker     }
584*288bf522SAndroid Build Coastguard Worker   }
585*288bf522SAndroid Build Coastguard Worker }
586*288bf522SAndroid Build Coastguard Worker 
NeedKernelSymbol() const587*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::NeedKernelSymbol() const {
588*288bf522SAndroid Build Coastguard Worker   return !ExcludeKernel();
589*288bf522SAndroid Build Coastguard Worker }
590*288bf522SAndroid Build Coastguard Worker 
SetRecordNotExecutableMaps(bool record)591*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::SetRecordNotExecutableMaps(bool record) {
592*288bf522SAndroid Build Coastguard Worker   // We only need to dump non-executable mmap records for the first event type.
593*288bf522SAndroid Build Coastguard Worker   groups_[0].selections[0].event_attr.mmap_data = record ? 1 : 0;
594*288bf522SAndroid Build Coastguard Worker }
595*288bf522SAndroid Build Coastguard Worker 
RecordNotExecutableMaps() const596*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::RecordNotExecutableMaps() const {
597*288bf522SAndroid Build Coastguard Worker   return groups_[0].selections[0].event_attr.mmap_data == 1;
598*288bf522SAndroid Build Coastguard Worker }
599*288bf522SAndroid Build Coastguard Worker 
EnableSwitchRecord()600*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::EnableSwitchRecord() {
601*288bf522SAndroid Build Coastguard Worker   groups_[0].selections[0].event_attr.context_switch = 1;
602*288bf522SAndroid Build Coastguard Worker }
603*288bf522SAndroid Build Coastguard Worker 
WakeupPerSample()604*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::WakeupPerSample() {
605*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
606*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
607*288bf522SAndroid Build Coastguard Worker       selection.event_attr.watermark = 0;
608*288bf522SAndroid Build Coastguard Worker       selection.event_attr.wakeup_events = 1;
609*288bf522SAndroid Build Coastguard Worker     }
610*288bf522SAndroid Build Coastguard Worker   }
611*288bf522SAndroid Build Coastguard Worker }
612*288bf522SAndroid Build Coastguard Worker 
SetTracepointFilter(const std::string & filter)613*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::SetTracepointFilter(const std::string& filter) {
614*288bf522SAndroid Build Coastguard Worker   // 1. Find the tracepoint event to set filter.
615*288bf522SAndroid Build Coastguard Worker   EventSelection* selection = nullptr;
616*288bf522SAndroid Build Coastguard Worker   if (!groups_.empty()) {
617*288bf522SAndroid Build Coastguard Worker     auto& group = groups_.back();
618*288bf522SAndroid Build Coastguard Worker     if (group.selections.size() == 1) {
619*288bf522SAndroid Build Coastguard Worker       if (group.selections[0].event_attr.type == PERF_TYPE_TRACEPOINT) {
620*288bf522SAndroid Build Coastguard Worker         selection = &group.selections[0];
621*288bf522SAndroid Build Coastguard Worker       }
622*288bf522SAndroid Build Coastguard Worker     }
623*288bf522SAndroid Build Coastguard Worker   }
624*288bf522SAndroid Build Coastguard Worker   if (selection == nullptr) {
625*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "No tracepoint event before filter: " << filter;
626*288bf522SAndroid Build Coastguard Worker     return false;
627*288bf522SAndroid Build Coastguard Worker   }
628*288bf522SAndroid Build Coastguard Worker 
629*288bf522SAndroid Build Coastguard Worker   // 2. Check the format of the filter.
630*288bf522SAndroid Build Coastguard Worker   bool use_quote = false;
631*288bf522SAndroid Build Coastguard Worker   // Quotes are needed for string operands in kernel >= 4.19, probably after patch "tracing: Rewrite
632*288bf522SAndroid Build Coastguard Worker   // filter logic to be simpler and faster".
633*288bf522SAndroid Build Coastguard Worker   if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(4, 19)) {
634*288bf522SAndroid Build Coastguard Worker     use_quote = true;
635*288bf522SAndroid Build Coastguard Worker   }
636*288bf522SAndroid Build Coastguard Worker 
637*288bf522SAndroid Build Coastguard Worker   FieldNameSet used_fields;
638*288bf522SAndroid Build Coastguard Worker   auto adjusted_filter = AdjustTracepointFilter(filter, use_quote, &used_fields);
639*288bf522SAndroid Build Coastguard Worker   if (!adjusted_filter) {
640*288bf522SAndroid Build Coastguard Worker     return false;
641*288bf522SAndroid Build Coastguard Worker   }
642*288bf522SAndroid Build Coastguard Worker 
643*288bf522SAndroid Build Coastguard Worker   // 3. Check if used fields are available in the tracepoint event.
644*288bf522SAndroid Build Coastguard Worker   auto& event_type = selection->event_type_modifier.event_type;
645*288bf522SAndroid Build Coastguard Worker   if (auto opt_fields = GetFieldNamesForTracepointEvent(event_type); opt_fields) {
646*288bf522SAndroid Build Coastguard Worker     FieldNameSet& fields = opt_fields.value();
647*288bf522SAndroid Build Coastguard Worker     for (const auto& field : used_fields) {
648*288bf522SAndroid Build Coastguard Worker       if (fields.find(field) == fields.end()) {
649*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "field name " << field << " used in \"" << filter << "\" doesn't exist in "
650*288bf522SAndroid Build Coastguard Worker                    << event_type.name << ". Available fields are "
651*288bf522SAndroid Build Coastguard Worker                    << android::base::Join(fields, ",");
652*288bf522SAndroid Build Coastguard Worker         return false;
653*288bf522SAndroid Build Coastguard Worker       }
654*288bf522SAndroid Build Coastguard Worker     }
655*288bf522SAndroid Build Coastguard Worker   }
656*288bf522SAndroid Build Coastguard Worker 
657*288bf522SAndroid Build Coastguard Worker   // 4. Connect the filter to the event.
658*288bf522SAndroid Build Coastguard Worker   selection->tracepoint_filter = adjusted_filter.value();
659*288bf522SAndroid Build Coastguard Worker   return true;
660*288bf522SAndroid Build Coastguard Worker }
661*288bf522SAndroid Build Coastguard Worker 
OpenEventFilesOnGroup(EventSelectionGroup & group,pid_t tid,int cpu,std::string * failed_event_type)662*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::OpenEventFilesOnGroup(EventSelectionGroup& group, pid_t tid, int cpu,
663*288bf522SAndroid Build Coastguard Worker                                               std::string* failed_event_type) {
664*288bf522SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<EventFd>> event_fds;
665*288bf522SAndroid Build Coastguard Worker   // Given a tid and cpu, events on the same group should be all opened
666*288bf522SAndroid Build Coastguard Worker   // successfully or all failed to open.
667*288bf522SAndroid Build Coastguard Worker   EventFd* group_fd = nullptr;
668*288bf522SAndroid Build Coastguard Worker   for (auto& selection : group.selections) {
669*288bf522SAndroid Build Coastguard Worker     std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(
670*288bf522SAndroid Build Coastguard Worker         selection.event_attr, tid, cpu, group_fd, selection.event_type_modifier.name, false);
671*288bf522SAndroid Build Coastguard Worker     if (!event_fd) {
672*288bf522SAndroid Build Coastguard Worker       *failed_event_type = selection.event_type_modifier.name;
673*288bf522SAndroid Build Coastguard Worker       return false;
674*288bf522SAndroid Build Coastguard Worker     }
675*288bf522SAndroid Build Coastguard Worker     LOG(VERBOSE) << "OpenEventFile for " << event_fd->Name();
676*288bf522SAndroid Build Coastguard Worker     event_fds.emplace_back(std::move(event_fd));
677*288bf522SAndroid Build Coastguard Worker     if (group_fd == nullptr) {
678*288bf522SAndroid Build Coastguard Worker       group_fd = event_fds.back().get();
679*288bf522SAndroid Build Coastguard Worker     }
680*288bf522SAndroid Build Coastguard Worker   }
681*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < group.selections.size(); ++i) {
682*288bf522SAndroid Build Coastguard Worker     group.selections[i].event_fds.emplace_back(std::move(event_fds[i]));
683*288bf522SAndroid Build Coastguard Worker   }
684*288bf522SAndroid Build Coastguard Worker   return true;
685*288bf522SAndroid Build Coastguard Worker }
686*288bf522SAndroid Build Coastguard Worker 
PrepareThreads(const std::set<pid_t> & processes,const std::set<pid_t> & threads)687*288bf522SAndroid Build Coastguard Worker static std::set<pid_t> PrepareThreads(const std::set<pid_t>& processes,
688*288bf522SAndroid Build Coastguard Worker                                       const std::set<pid_t>& threads) {
689*288bf522SAndroid Build Coastguard Worker   std::set<pid_t> result = threads;
690*288bf522SAndroid Build Coastguard Worker   for (auto& pid : processes) {
691*288bf522SAndroid Build Coastguard Worker     std::vector<pid_t> tids = GetThreadsInProcess(pid);
692*288bf522SAndroid Build Coastguard Worker     result.insert(tids.begin(), tids.end());
693*288bf522SAndroid Build Coastguard Worker   }
694*288bf522SAndroid Build Coastguard Worker   return result;
695*288bf522SAndroid Build Coastguard Worker }
696*288bf522SAndroid Build Coastguard Worker 
OpenEventFiles()697*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::OpenEventFiles() {
698*288bf522SAndroid Build Coastguard Worker   std::vector<int> online_cpus = GetOnlineCpus();
699*288bf522SAndroid Build Coastguard Worker 
700*288bf522SAndroid Build Coastguard Worker   auto check_if_cpus_online = [&](const std::vector<int>& cpus) {
701*288bf522SAndroid Build Coastguard Worker     if (cpus.size() == 1 && cpus[0] == -1) {
702*288bf522SAndroid Build Coastguard Worker       return true;
703*288bf522SAndroid Build Coastguard Worker     }
704*288bf522SAndroid Build Coastguard Worker     for (int cpu : cpus) {
705*288bf522SAndroid Build Coastguard Worker       if (std::find(online_cpus.begin(), online_cpus.end(), cpu) == online_cpus.end()) {
706*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "cpu " << cpu << " is not online.";
707*288bf522SAndroid Build Coastguard Worker         return false;
708*288bf522SAndroid Build Coastguard Worker       }
709*288bf522SAndroid Build Coastguard Worker     }
710*288bf522SAndroid Build Coastguard Worker     return true;
711*288bf522SAndroid Build Coastguard Worker   };
712*288bf522SAndroid Build Coastguard Worker 
713*288bf522SAndroid Build Coastguard Worker   std::set<pid_t> threads = PrepareThreads(processes_, threads_);
714*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
715*288bf522SAndroid Build Coastguard Worker     const std::vector<int>* pcpus = &group.cpus;
716*288bf522SAndroid Build Coastguard Worker     if (!group.selections[0].allowed_cpus.empty()) {
717*288bf522SAndroid Build Coastguard Worker       // override cpu list if event's PMU has a cpumask as those PMUs are
718*288bf522SAndroid Build Coastguard Worker       // agnostic to cpu and it's meaningless to specify cpus for them.
719*288bf522SAndroid Build Coastguard Worker       pcpus = &group.selections[0].allowed_cpus;
720*288bf522SAndroid Build Coastguard Worker     }
721*288bf522SAndroid Build Coastguard Worker     if (pcpus->empty()) {
722*288bf522SAndroid Build Coastguard Worker       pcpus = &online_cpus;
723*288bf522SAndroid Build Coastguard Worker     } else if (!check_if_cpus_online(*pcpus)) {
724*288bf522SAndroid Build Coastguard Worker       return false;
725*288bf522SAndroid Build Coastguard Worker     }
726*288bf522SAndroid Build Coastguard Worker 
727*288bf522SAndroid Build Coastguard Worker     size_t success_count = 0;
728*288bf522SAndroid Build Coastguard Worker     std::string failed_event_type;
729*288bf522SAndroid Build Coastguard Worker     for (const auto tid : threads) {
730*288bf522SAndroid Build Coastguard Worker       for (const auto& cpu : *pcpus) {
731*288bf522SAndroid Build Coastguard Worker         if (OpenEventFilesOnGroup(group, tid, cpu, &failed_event_type)) {
732*288bf522SAndroid Build Coastguard Worker           success_count++;
733*288bf522SAndroid Build Coastguard Worker         }
734*288bf522SAndroid Build Coastguard Worker       }
735*288bf522SAndroid Build Coastguard Worker     }
736*288bf522SAndroid Build Coastguard Worker     // We can't guarantee to open perf event file successfully for each thread on each cpu.
737*288bf522SAndroid Build Coastguard Worker     // Because threads may exit between PrepareThreads() and OpenEventFilesOnGroup(), and
738*288bf522SAndroid Build Coastguard Worker     // cpus may be offlined between GetOnlineCpus() and OpenEventFilesOnGroup().
739*288bf522SAndroid Build Coastguard Worker     // So we only check that we can at least monitor one thread for each event group.
740*288bf522SAndroid Build Coastguard Worker     if (success_count == 0) {
741*288bf522SAndroid Build Coastguard Worker       int error_number = errno;
742*288bf522SAndroid Build Coastguard Worker       PLOG(ERROR) << "failed to open perf event file for event_type " << failed_event_type;
743*288bf522SAndroid Build Coastguard Worker       if (error_number == EMFILE) {
744*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Please increase hard limit of open file numbers.";
745*288bf522SAndroid Build Coastguard Worker       }
746*288bf522SAndroid Build Coastguard Worker       return false;
747*288bf522SAndroid Build Coastguard Worker     }
748*288bf522SAndroid Build Coastguard Worker   }
749*288bf522SAndroid Build Coastguard Worker   return ApplyFilters();
750*288bf522SAndroid Build Coastguard Worker }
751*288bf522SAndroid Build Coastguard Worker 
ApplyFilters()752*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::ApplyFilters() {
753*288bf522SAndroid Build Coastguard Worker   return ApplyAddrFilters() && ApplyTracepointFilters();
754*288bf522SAndroid Build Coastguard Worker }
755*288bf522SAndroid Build Coastguard Worker 
ApplyAddrFilters()756*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::ApplyAddrFilters() {
757*288bf522SAndroid Build Coastguard Worker   if (addr_filters_.empty()) {
758*288bf522SAndroid Build Coastguard Worker     return true;
759*288bf522SAndroid Build Coastguard Worker   }
760*288bf522SAndroid Build Coastguard Worker   if (!has_aux_trace_) {
761*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "addr filters only take effect in cs-etm instruction tracing";
762*288bf522SAndroid Build Coastguard Worker     return false;
763*288bf522SAndroid Build Coastguard Worker   }
764*288bf522SAndroid Build Coastguard Worker 
765*288bf522SAndroid Build Coastguard Worker   // Check filter count limit.
766*288bf522SAndroid Build Coastguard Worker   size_t required_etm_filter_count = 0;
767*288bf522SAndroid Build Coastguard Worker   for (auto& filter : addr_filters_) {
768*288bf522SAndroid Build Coastguard Worker     // A range filter needs two etm filters.
769*288bf522SAndroid Build Coastguard Worker     required_etm_filter_count +=
770*288bf522SAndroid Build Coastguard Worker         (filter.type == AddrFilter::FILE_RANGE || filter.type == AddrFilter::KERNEL_RANGE) ? 2 : 1;
771*288bf522SAndroid Build Coastguard Worker   }
772*288bf522SAndroid Build Coastguard Worker   size_t etm_filter_count = ETMRecorder::GetInstance().GetAddrFilterPairs() * 2;
773*288bf522SAndroid Build Coastguard Worker   if (etm_filter_count < required_etm_filter_count) {
774*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "needed " << required_etm_filter_count << " etm filters, but only "
775*288bf522SAndroid Build Coastguard Worker                << etm_filter_count << " filters are available.";
776*288bf522SAndroid Build Coastguard Worker     return false;
777*288bf522SAndroid Build Coastguard Worker   }
778*288bf522SAndroid Build Coastguard Worker 
779*288bf522SAndroid Build Coastguard Worker   std::string filter_str;
780*288bf522SAndroid Build Coastguard Worker   for (auto& filter : addr_filters_) {
781*288bf522SAndroid Build Coastguard Worker     if (!filter_str.empty()) {
782*288bf522SAndroid Build Coastguard Worker       filter_str += ',';
783*288bf522SAndroid Build Coastguard Worker     }
784*288bf522SAndroid Build Coastguard Worker     filter_str += filter.ToString();
785*288bf522SAndroid Build Coastguard Worker   }
786*288bf522SAndroid Build Coastguard Worker 
787*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
788*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
789*288bf522SAndroid Build Coastguard Worker       if (IsEtmEventType(selection.event_type_modifier.event_type.type)) {
790*288bf522SAndroid Build Coastguard Worker         for (auto& event_fd : selection.event_fds) {
791*288bf522SAndroid Build Coastguard Worker           if (!event_fd->SetFilter(filter_str)) {
792*288bf522SAndroid Build Coastguard Worker             return false;
793*288bf522SAndroid Build Coastguard Worker           }
794*288bf522SAndroid Build Coastguard Worker         }
795*288bf522SAndroid Build Coastguard Worker       }
796*288bf522SAndroid Build Coastguard Worker     }
797*288bf522SAndroid Build Coastguard Worker   }
798*288bf522SAndroid Build Coastguard Worker   return true;
799*288bf522SAndroid Build Coastguard Worker }
800*288bf522SAndroid Build Coastguard Worker 
ApplyTracepointFilters()801*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::ApplyTracepointFilters() {
802*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
803*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
804*288bf522SAndroid Build Coastguard Worker       if (!selection.tracepoint_filter.empty()) {
805*288bf522SAndroid Build Coastguard Worker         for (auto& event_fd : selection.event_fds) {
806*288bf522SAndroid Build Coastguard Worker           if (!event_fd->SetFilter(selection.tracepoint_filter)) {
807*288bf522SAndroid Build Coastguard Worker             return false;
808*288bf522SAndroid Build Coastguard Worker           }
809*288bf522SAndroid Build Coastguard Worker         }
810*288bf522SAndroid Build Coastguard Worker       }
811*288bf522SAndroid Build Coastguard Worker     }
812*288bf522SAndroid Build Coastguard Worker   }
813*288bf522SAndroid Build Coastguard Worker   return true;
814*288bf522SAndroid Build Coastguard Worker }
815*288bf522SAndroid Build Coastguard Worker 
ReadCounter(EventFd * event_fd,CounterInfo * counter)816*288bf522SAndroid Build Coastguard Worker static bool ReadCounter(EventFd* event_fd, CounterInfo* counter) {
817*288bf522SAndroid Build Coastguard Worker   if (!event_fd->ReadCounter(&counter->counter)) {
818*288bf522SAndroid Build Coastguard Worker     return false;
819*288bf522SAndroid Build Coastguard Worker   }
820*288bf522SAndroid Build Coastguard Worker   counter->tid = event_fd->ThreadId();
821*288bf522SAndroid Build Coastguard Worker   counter->cpu = event_fd->Cpu();
822*288bf522SAndroid Build Coastguard Worker   return true;
823*288bf522SAndroid Build Coastguard Worker }
824*288bf522SAndroid Build Coastguard Worker 
ReadCounters(std::vector<CountersInfo> * counters)825*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) {
826*288bf522SAndroid Build Coastguard Worker   counters->clear();
827*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < groups_.size(); ++i) {
828*288bf522SAndroid Build Coastguard Worker     for (auto& selection : groups_[i].selections) {
829*288bf522SAndroid Build Coastguard Worker       CountersInfo counters_info;
830*288bf522SAndroid Build Coastguard Worker       counters_info.group_id = i;
831*288bf522SAndroid Build Coastguard Worker       counters_info.event_name = selection.event_type_modifier.event_type.name;
832*288bf522SAndroid Build Coastguard Worker       counters_info.event_modifier = selection.event_type_modifier.modifier;
833*288bf522SAndroid Build Coastguard Worker       counters_info.counters = selection.hotplugged_counters;
834*288bf522SAndroid Build Coastguard Worker       for (auto& event_fd : selection.event_fds) {
835*288bf522SAndroid Build Coastguard Worker         CounterInfo counter;
836*288bf522SAndroid Build Coastguard Worker         if (!ReadCounter(event_fd.get(), &counter)) {
837*288bf522SAndroid Build Coastguard Worker           return false;
838*288bf522SAndroid Build Coastguard Worker         }
839*288bf522SAndroid Build Coastguard Worker         counters_info.counters.push_back(counter);
840*288bf522SAndroid Build Coastguard Worker       }
841*288bf522SAndroid Build Coastguard Worker       counters->push_back(counters_info);
842*288bf522SAndroid Build Coastguard Worker     }
843*288bf522SAndroid Build Coastguard Worker   }
844*288bf522SAndroid Build Coastguard Worker   return true;
845*288bf522SAndroid Build Coastguard Worker }
846*288bf522SAndroid Build Coastguard Worker 
MmapEventFiles(size_t min_mmap_pages,size_t max_mmap_pages,size_t aux_buffer_size,size_t record_buffer_size,bool allow_truncating_samples,bool exclude_perf)847*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages,
848*288bf522SAndroid Build Coastguard Worker                                        size_t aux_buffer_size, size_t record_buffer_size,
849*288bf522SAndroid Build Coastguard Worker                                        bool allow_truncating_samples, bool exclude_perf) {
850*288bf522SAndroid Build Coastguard Worker   record_read_thread_.reset(new simpleperf::RecordReadThread(
851*288bf522SAndroid Build Coastguard Worker       record_buffer_size, groups_[0].selections[0].event_attr, min_mmap_pages, max_mmap_pages,
852*288bf522SAndroid Build Coastguard Worker       aux_buffer_size, allow_truncating_samples, exclude_perf));
853*288bf522SAndroid Build Coastguard Worker   return true;
854*288bf522SAndroid Build Coastguard Worker }
855*288bf522SAndroid Build Coastguard Worker 
PrepareToReadMmapEventData(const std::function<bool (Record *)> & callback)856*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback) {
857*288bf522SAndroid Build Coastguard Worker   // Prepare record callback function.
858*288bf522SAndroid Build Coastguard Worker   record_callback_ = callback;
859*288bf522SAndroid Build Coastguard Worker   if (!record_read_thread_->RegisterDataCallback(*loop_,
860*288bf522SAndroid Build Coastguard Worker                                                  [this]() { return ReadMmapEventData(true); })) {
861*288bf522SAndroid Build Coastguard Worker     return false;
862*288bf522SAndroid Build Coastguard Worker   }
863*288bf522SAndroid Build Coastguard Worker   std::vector<EventFd*> event_fds;
864*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
865*288bf522SAndroid Build Coastguard Worker     for (auto& selection : group.selections) {
866*288bf522SAndroid Build Coastguard Worker       for (auto& event_fd : selection.event_fds) {
867*288bf522SAndroid Build Coastguard Worker         event_fds.push_back(event_fd.get());
868*288bf522SAndroid Build Coastguard Worker       }
869*288bf522SAndroid Build Coastguard Worker     }
870*288bf522SAndroid Build Coastguard Worker   }
871*288bf522SAndroid Build Coastguard Worker   return record_read_thread_->AddEventFds(event_fds);
872*288bf522SAndroid Build Coastguard Worker }
873*288bf522SAndroid Build Coastguard Worker 
SyncKernelBuffer()874*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::SyncKernelBuffer() {
875*288bf522SAndroid Build Coastguard Worker   return record_read_thread_->SyncKernelBuffer();
876*288bf522SAndroid Build Coastguard Worker }
877*288bf522SAndroid Build Coastguard Worker 
878*288bf522SAndroid Build Coastguard Worker // Read records from the RecordBuffer. If with_time_limit is false, read until the RecordBuffer is
879*288bf522SAndroid Build Coastguard Worker // empty, otherwise stop after 100 ms or when the record buffer is empty.
ReadMmapEventData(bool with_time_limit)880*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::ReadMmapEventData(bool with_time_limit) {
881*288bf522SAndroid Build Coastguard Worker   uint64_t start_time_in_ns;
882*288bf522SAndroid Build Coastguard Worker   if (with_time_limit) {
883*288bf522SAndroid Build Coastguard Worker     start_time_in_ns = GetSystemClock();
884*288bf522SAndroid Build Coastguard Worker   }
885*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<Record> r;
886*288bf522SAndroid Build Coastguard Worker   while ((r = record_read_thread_->GetRecord()) != nullptr) {
887*288bf522SAndroid Build Coastguard Worker     if (!record_callback_(r.get())) {
888*288bf522SAndroid Build Coastguard Worker       return false;
889*288bf522SAndroid Build Coastguard Worker     }
890*288bf522SAndroid Build Coastguard Worker     if (with_time_limit && (GetSystemClock() - start_time_in_ns) >= 1e8) {
891*288bf522SAndroid Build Coastguard Worker       break;
892*288bf522SAndroid Build Coastguard Worker     }
893*288bf522SAndroid Build Coastguard Worker   }
894*288bf522SAndroid Build Coastguard Worker   return true;
895*288bf522SAndroid Build Coastguard Worker }
896*288bf522SAndroid Build Coastguard Worker 
FinishReadMmapEventData()897*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::FinishReadMmapEventData() {
898*288bf522SAndroid Build Coastguard Worker   return ReadMmapEventData(false);
899*288bf522SAndroid Build Coastguard Worker }
900*288bf522SAndroid Build Coastguard Worker 
CloseEventFiles()901*288bf522SAndroid Build Coastguard Worker void EventSelectionSet::CloseEventFiles() {
902*288bf522SAndroid Build Coastguard Worker   if (record_read_thread_) {
903*288bf522SAndroid Build Coastguard Worker     record_read_thread_->StopReadThread();
904*288bf522SAndroid Build Coastguard Worker   }
905*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
906*288bf522SAndroid Build Coastguard Worker     for (auto& event : group.selections) {
907*288bf522SAndroid Build Coastguard Worker       event.event_fds.clear();
908*288bf522SAndroid Build Coastguard Worker     }
909*288bf522SAndroid Build Coastguard Worker   }
910*288bf522SAndroid Build Coastguard Worker }
911*288bf522SAndroid Build Coastguard Worker 
StopWhenNoMoreTargets(double check_interval_in_sec)912*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::StopWhenNoMoreTargets(double check_interval_in_sec) {
913*288bf522SAndroid Build Coastguard Worker   return loop_->AddPeriodicEvent(SecondToTimeval(check_interval_in_sec),
914*288bf522SAndroid Build Coastguard Worker                                  [&]() { return CheckMonitoredTargets(); });
915*288bf522SAndroid Build Coastguard Worker }
916*288bf522SAndroid Build Coastguard Worker 
CheckMonitoredTargets()917*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::CheckMonitoredTargets() {
918*288bf522SAndroid Build Coastguard Worker   if (!HasSampler()) {
919*288bf522SAndroid Build Coastguard Worker     return loop_->ExitLoop();
920*288bf522SAndroid Build Coastguard Worker   }
921*288bf522SAndroid Build Coastguard Worker   for (const auto& tid : threads_) {
922*288bf522SAndroid Build Coastguard Worker     if (IsThreadAlive(tid)) {
923*288bf522SAndroid Build Coastguard Worker       return true;
924*288bf522SAndroid Build Coastguard Worker     }
925*288bf522SAndroid Build Coastguard Worker   }
926*288bf522SAndroid Build Coastguard Worker   for (const auto& pid : processes_) {
927*288bf522SAndroid Build Coastguard Worker     if (IsThreadAlive(pid)) {
928*288bf522SAndroid Build Coastguard Worker       return true;
929*288bf522SAndroid Build Coastguard Worker     }
930*288bf522SAndroid Build Coastguard Worker   }
931*288bf522SAndroid Build Coastguard Worker   return loop_->ExitLoop();
932*288bf522SAndroid Build Coastguard Worker }
933*288bf522SAndroid Build Coastguard Worker 
HasSampler()934*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::HasSampler() {
935*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
936*288bf522SAndroid Build Coastguard Worker     for (auto& sel : group.selections) {
937*288bf522SAndroid Build Coastguard Worker       if (!sel.event_fds.empty()) {
938*288bf522SAndroid Build Coastguard Worker         return true;
939*288bf522SAndroid Build Coastguard Worker       }
940*288bf522SAndroid Build Coastguard Worker     }
941*288bf522SAndroid Build Coastguard Worker   }
942*288bf522SAndroid Build Coastguard Worker   return false;
943*288bf522SAndroid Build Coastguard Worker }
944*288bf522SAndroid Build Coastguard Worker 
SetEnableEvents(bool enable)945*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::SetEnableEvents(bool enable) {
946*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
947*288bf522SAndroid Build Coastguard Worker     for (auto& sel : group.selections) {
948*288bf522SAndroid Build Coastguard Worker       for (auto& fd : sel.event_fds) {
949*288bf522SAndroid Build Coastguard Worker         if (!fd->SetEnableEvent(enable)) {
950*288bf522SAndroid Build Coastguard Worker           return false;
951*288bf522SAndroid Build Coastguard Worker         }
952*288bf522SAndroid Build Coastguard Worker       }
953*288bf522SAndroid Build Coastguard Worker     }
954*288bf522SAndroid Build Coastguard Worker   }
955*288bf522SAndroid Build Coastguard Worker   return true;
956*288bf522SAndroid Build Coastguard Worker }
957*288bf522SAndroid Build Coastguard Worker 
EnableETMEvents()958*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::EnableETMEvents() {
959*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
960*288bf522SAndroid Build Coastguard Worker     for (auto& sel : group.selections) {
961*288bf522SAndroid Build Coastguard Worker       if (!sel.event_type_modifier.event_type.IsEtmEvent()) {
962*288bf522SAndroid Build Coastguard Worker         continue;
963*288bf522SAndroid Build Coastguard Worker       }
964*288bf522SAndroid Build Coastguard Worker       for (auto& fd : sel.event_fds) {
965*288bf522SAndroid Build Coastguard Worker         if (!fd->SetEnableEvent(true)) {
966*288bf522SAndroid Build Coastguard Worker           return false;
967*288bf522SAndroid Build Coastguard Worker         }
968*288bf522SAndroid Build Coastguard Worker       }
969*288bf522SAndroid Build Coastguard Worker     }
970*288bf522SAndroid Build Coastguard Worker   }
971*288bf522SAndroid Build Coastguard Worker   return true;
972*288bf522SAndroid Build Coastguard Worker }
973*288bf522SAndroid Build Coastguard Worker 
DisableETMEvents()974*288bf522SAndroid Build Coastguard Worker bool EventSelectionSet::DisableETMEvents() {
975*288bf522SAndroid Build Coastguard Worker   for (auto& group : groups_) {
976*288bf522SAndroid Build Coastguard Worker     for (auto& sel : group.selections) {
977*288bf522SAndroid Build Coastguard Worker       if (!sel.event_type_modifier.event_type.IsEtmEvent()) {
978*288bf522SAndroid Build Coastguard Worker         continue;
979*288bf522SAndroid Build Coastguard Worker       }
980*288bf522SAndroid Build Coastguard Worker       // When using ETR, ETM data is flushed to the aux buffer of the last cpu disabling ETM events.
981*288bf522SAndroid Build Coastguard Worker       // To avoid overflowing the aux buffer for one cpu, rotate the last cpu disabling ETM events.
982*288bf522SAndroid Build Coastguard Worker       if (etm_event_cpus_.empty()) {
983*288bf522SAndroid Build Coastguard Worker         for (const auto& fd : sel.event_fds) {
984*288bf522SAndroid Build Coastguard Worker           etm_event_cpus_.insert(fd->Cpu());
985*288bf522SAndroid Build Coastguard Worker         }
986*288bf522SAndroid Build Coastguard Worker         if (etm_event_cpus_.empty()) {
987*288bf522SAndroid Build Coastguard Worker           continue;
988*288bf522SAndroid Build Coastguard Worker         }
989*288bf522SAndroid Build Coastguard Worker         etm_event_cpus_it_ = etm_event_cpus_.begin();
990*288bf522SAndroid Build Coastguard Worker       }
991*288bf522SAndroid Build Coastguard Worker       int last_disabled_cpu = *etm_event_cpus_it_;
992*288bf522SAndroid Build Coastguard Worker       if (++etm_event_cpus_it_ == etm_event_cpus_.end()) {
993*288bf522SAndroid Build Coastguard Worker         etm_event_cpus_it_ = etm_event_cpus_.begin();
994*288bf522SAndroid Build Coastguard Worker       }
995*288bf522SAndroid Build Coastguard Worker 
996*288bf522SAndroid Build Coastguard Worker       for (auto& fd : sel.event_fds) {
997*288bf522SAndroid Build Coastguard Worker         if (fd->Cpu() != last_disabled_cpu) {
998*288bf522SAndroid Build Coastguard Worker           if (!fd->SetEnableEvent(false)) {
999*288bf522SAndroid Build Coastguard Worker             return false;
1000*288bf522SAndroid Build Coastguard Worker           }
1001*288bf522SAndroid Build Coastguard Worker         }
1002*288bf522SAndroid Build Coastguard Worker       }
1003*288bf522SAndroid Build Coastguard Worker       for (auto& fd : sel.event_fds) {
1004*288bf522SAndroid Build Coastguard Worker         if (fd->Cpu() == last_disabled_cpu) {
1005*288bf522SAndroid Build Coastguard Worker           if (!fd->SetEnableEvent(false)) {
1006*288bf522SAndroid Build Coastguard Worker             return false;
1007*288bf522SAndroid Build Coastguard Worker           }
1008*288bf522SAndroid Build Coastguard Worker         }
1009*288bf522SAndroid Build Coastguard Worker       }
1010*288bf522SAndroid Build Coastguard Worker     }
1011*288bf522SAndroid Build Coastguard Worker   }
1012*288bf522SAndroid Build Coastguard Worker   return true;
1013*288bf522SAndroid Build Coastguard Worker }
1014*288bf522SAndroid Build Coastguard Worker 
1015*288bf522SAndroid Build Coastguard Worker }  // namespace simpleperf
1016