xref: /aosp_15_r20/external/perfetto/src/profiling/perf/event_config.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/profiling/perf/event_config.h"
18 
19 #include <linux/perf_event.h>
20 #include <time.h>
21 
22 #include <unwindstack/Regs.h>
23 #include <optional>
24 #include <vector>
25 
26 #include "perfetto/base/flat_set.h"
27 #include "perfetto/ext/base/utils.h"
28 #include "src/profiling/perf/regs_parsing.h"
29 
30 #include "protos/perfetto/common/perf_events.gen.h"
31 #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
32 
33 namespace perfetto {
34 namespace profiling {
35 
36 namespace {
37 constexpr uint64_t kDefaultSamplingFrequencyHz = 10;
38 constexpr uint32_t kDefaultDataPagesPerRingBuffer = 256;  // 1 MB: 256x 4k pages
39 constexpr uint32_t kDefaultReadTickPeriodMs = 100;
40 constexpr uint32_t kDefaultRemoteDescriptorTimeoutMs = 100;
41 
42 // Acceptable forms: "sched/sched_switch" or "sched:sched_switch".
SplitTracepointString(const std::string & input)43 std::pair<std::string, std::string> SplitTracepointString(
44     const std::string& input) {
45   auto slash_pos = input.find("/");
46   if (slash_pos != std::string::npos)
47     return std::make_pair(input.substr(0, slash_pos),
48                           input.substr(slash_pos + 1));
49 
50   auto colon_pos = input.find(":");
51   if (colon_pos != std::string::npos)
52     return std::make_pair(input.substr(0, colon_pos),
53                           input.substr(colon_pos + 1));
54 
55   return std::make_pair("", input);
56 }
57 
58 // If set, the returned id is guaranteed to be non-zero.
ParseTracepointAndResolveId(const protos::gen::PerfEvents::Tracepoint & tracepoint,EventConfig::tracepoint_id_fn_t tracepoint_id_lookup)59 std::optional<uint32_t> ParseTracepointAndResolveId(
60     const protos::gen::PerfEvents::Tracepoint& tracepoint,
61     EventConfig::tracepoint_id_fn_t tracepoint_id_lookup) {
62   std::string full_name = tracepoint.name();
63   std::string tp_group;
64   std::string tp_name;
65   std::tie(tp_group, tp_name) = SplitTracepointString(full_name);
66   if (tp_group.empty() || tp_name.empty()) {
67     PERFETTO_ELOG(
68         "Invalid tracepoint format: %s. Should be a full path like "
69         "sched:sched_switch or sched/sched_switch.",
70         full_name.c_str());
71     return std::nullopt;
72   }
73 
74   uint32_t tracepoint_id = tracepoint_id_lookup(tp_group, tp_name);
75   if (!tracepoint_id) {
76     PERFETTO_ELOG(
77         "Failed to resolve tracepoint %s to its id. Check that tracefs is "
78         "accessible and the event exists.",
79         full_name.c_str());
80     return std::nullopt;
81   }
82   return std::make_optional(tracepoint_id);
83 }
84 
85 // |T| is either gen::PerfEventConfig or gen::PerfEventConfig::Scope.
86 // Note: the semantics of target_cmdline and exclude_cmdline were changed since
87 // their original introduction. They used to be put through a canonicalization
88 // function that simplified them to the binary name alone. We no longer do this,
89 // regardless of whether we're parsing an old-style config. The overall outcome
90 // shouldn't change for almost all existing uses.
91 template <typename T>
ParseTargetFilter(const T & cfg,std::optional<ProcessSharding> process_sharding)92 TargetFilter ParseTargetFilter(
93     const T& cfg,
94     std::optional<ProcessSharding> process_sharding) {
95   TargetFilter filter;
96   for (const auto& str : cfg.target_cmdline()) {
97     filter.cmdlines.push_back(str);
98   }
99   for (const auto& str : cfg.exclude_cmdline()) {
100     filter.exclude_cmdlines.push_back(str);
101   }
102   for (const int32_t pid : cfg.target_pid()) {
103     filter.pids.insert(pid);
104   }
105   for (const int32_t pid : cfg.exclude_pid()) {
106     filter.exclude_pids.insert(pid);
107   }
108   filter.additional_cmdline_count = cfg.additional_cmdline_count();
109   filter.process_sharding = process_sharding;
110   return filter;
111 }
112 
IsPowerOfTwo(size_t v)113 constexpr bool IsPowerOfTwo(size_t v) {
114   return (v != 0 && ((v & (v - 1)) == 0));
115 }
116 
117 // returns |std::nullopt| if the input is invalid.
ChooseActualRingBufferPages(uint32_t config_value)118 std::optional<uint32_t> ChooseActualRingBufferPages(uint32_t config_value) {
119   if (!config_value) {
120     static_assert(IsPowerOfTwo(kDefaultDataPagesPerRingBuffer), "");
121     return std::make_optional(kDefaultDataPagesPerRingBuffer);
122   }
123 
124   if (!IsPowerOfTwo(config_value)) {
125     PERFETTO_ELOG("kernel buffer size must be a power of two pages");
126     return std::nullopt;
127   }
128 
129   return std::make_optional(config_value);
130 }
131 
ToPerfCounter(std::string name,protos::gen::PerfEvents::Counter pb_enum)132 std::optional<PerfCounter> ToPerfCounter(
133     std::string name,
134     protos::gen::PerfEvents::Counter pb_enum) {
135   using protos::gen::PerfEvents;
136   switch (static_cast<int>(pb_enum)) {  // cast to pacify -Wswitch-enum
137     case PerfEvents::SW_CPU_CLOCK:
138       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_CPU_CLOCK,
139                                          PERF_TYPE_SOFTWARE,
140                                          PERF_COUNT_SW_CPU_CLOCK);
141     case PerfEvents::SW_PAGE_FAULTS:
142       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_PAGE_FAULTS,
143                                          PERF_TYPE_SOFTWARE,
144                                          PERF_COUNT_SW_PAGE_FAULTS);
145     case PerfEvents::SW_TASK_CLOCK:
146       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_TASK_CLOCK,
147                                          PERF_TYPE_SOFTWARE,
148                                          PERF_COUNT_SW_TASK_CLOCK);
149     case PerfEvents::SW_CONTEXT_SWITCHES:
150       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_CONTEXT_SWITCHES,
151                                          PERF_TYPE_SOFTWARE,
152                                          PERF_COUNT_SW_CONTEXT_SWITCHES);
153     case PerfEvents::SW_CPU_MIGRATIONS:
154       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_CPU_MIGRATIONS,
155                                          PERF_TYPE_SOFTWARE,
156                                          PERF_COUNT_SW_CPU_MIGRATIONS);
157     case PerfEvents::SW_PAGE_FAULTS_MIN:
158       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_PAGE_FAULTS_MIN,
159                                          PERF_TYPE_SOFTWARE,
160                                          PERF_COUNT_SW_PAGE_FAULTS_MIN);
161     case PerfEvents::SW_PAGE_FAULTS_MAJ:
162       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_PAGE_FAULTS_MAJ,
163                                          PERF_TYPE_SOFTWARE,
164                                          PERF_COUNT_SW_PAGE_FAULTS_MAJ);
165     case PerfEvents::SW_ALIGNMENT_FAULTS:
166       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_ALIGNMENT_FAULTS,
167                                          PERF_TYPE_SOFTWARE,
168                                          PERF_COUNT_SW_ALIGNMENT_FAULTS);
169     case PerfEvents::SW_EMULATION_FAULTS:
170       return PerfCounter::BuiltinCounter(name, PerfEvents::SW_EMULATION_FAULTS,
171                                          PERF_TYPE_SOFTWARE,
172                                          PERF_COUNT_SW_EMULATION_FAULTS);
173     case PerfEvents::SW_DUMMY:
174       return PerfCounter::BuiltinCounter(
175           name, PerfEvents::SW_DUMMY, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY);
176 
177     case PerfEvents::HW_CPU_CYCLES:
178       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_CPU_CYCLES,
179                                          PERF_TYPE_HARDWARE,
180                                          PERF_COUNT_HW_CPU_CYCLES);
181     case PerfEvents::HW_INSTRUCTIONS:
182       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_INSTRUCTIONS,
183                                          PERF_TYPE_HARDWARE,
184                                          PERF_COUNT_HW_INSTRUCTIONS);
185     case PerfEvents::HW_CACHE_REFERENCES:
186       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_CACHE_REFERENCES,
187                                          PERF_TYPE_HARDWARE,
188                                          PERF_COUNT_HW_CACHE_REFERENCES);
189     case PerfEvents::HW_CACHE_MISSES:
190       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_CACHE_MISSES,
191                                          PERF_TYPE_HARDWARE,
192                                          PERF_COUNT_HW_CACHE_MISSES);
193     case PerfEvents::HW_BRANCH_INSTRUCTIONS:
194       return PerfCounter::BuiltinCounter(
195           name, PerfEvents::HW_BRANCH_INSTRUCTIONS, PERF_TYPE_HARDWARE,
196           PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
197     case PerfEvents::HW_BRANCH_MISSES:
198       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_BRANCH_MISSES,
199                                          PERF_TYPE_HARDWARE,
200                                          PERF_COUNT_HW_BRANCH_MISSES);
201     case PerfEvents::HW_BUS_CYCLES:
202       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_BUS_CYCLES,
203                                          PERF_TYPE_HARDWARE,
204                                          PERF_COUNT_HW_BUS_CYCLES);
205     case PerfEvents::HW_STALLED_CYCLES_FRONTEND:
206       return PerfCounter::BuiltinCounter(
207           name, PerfEvents::HW_STALLED_CYCLES_FRONTEND, PERF_TYPE_HARDWARE,
208           PERF_COUNT_HW_STALLED_CYCLES_FRONTEND);
209     case PerfEvents::HW_STALLED_CYCLES_BACKEND:
210       return PerfCounter::BuiltinCounter(
211           name, PerfEvents::HW_STALLED_CYCLES_BACKEND, PERF_TYPE_HARDWARE,
212           PERF_COUNT_HW_STALLED_CYCLES_BACKEND);
213     case PerfEvents::HW_REF_CPU_CYCLES:
214       return PerfCounter::BuiltinCounter(name, PerfEvents::HW_REF_CPU_CYCLES,
215                                          PERF_TYPE_HARDWARE,
216                                          PERF_COUNT_HW_REF_CPU_CYCLES);
217 
218     default:
219       PERFETTO_ELOG("Unrecognised PerfEvents::Counter enum value: %zu",
220                     static_cast<size_t>(pb_enum));
221       return std::nullopt;
222   }
223 }
224 
ToClockId(protos::gen::PerfEvents::PerfClock pb_enum)225 int32_t ToClockId(protos::gen::PerfEvents::PerfClock pb_enum) {
226   using protos::gen::PerfEvents;
227   switch (static_cast<int>(pb_enum)) {  // cast to pacify -Wswitch-enum
228     case PerfEvents::PERF_CLOCK_REALTIME:
229       return CLOCK_REALTIME;
230     case PerfEvents::PERF_CLOCK_MONOTONIC:
231       return CLOCK_MONOTONIC;
232     case PerfEvents::PERF_CLOCK_MONOTONIC_RAW:
233       return CLOCK_MONOTONIC_RAW;
234     case PerfEvents::PERF_CLOCK_BOOTTIME:
235       return CLOCK_BOOTTIME;
236     // Default to a monotonic clock since it should be compatible with all types
237     // of events. Whereas boottime cannot be used with hardware events due to
238     // potential access within non-maskable interrupts.
239     default:
240       return CLOCK_MONOTONIC_RAW;
241   }
242 }
243 
244 // Build a singular event from an event description provided by either
245 // a PerfEvents::Timebase or a FollowerEvent materialized by the
246 // polymorphic parameter event_desc.
247 template <typename T>
MakePerfCounter(EventConfig::tracepoint_id_fn_t & tracepoint_id_lookup,const std::string & name,const T & event_desc)248 std::optional<PerfCounter> MakePerfCounter(
249     EventConfig::tracepoint_id_fn_t& tracepoint_id_lookup,
250     const std::string& name,
251     const T& event_desc) {
252   if (event_desc.has_counter()) {
253     auto maybe_counter = ToPerfCounter(name, event_desc.counter());
254     if (!maybe_counter)
255       return std::nullopt;
256     return *maybe_counter;
257   } else if (event_desc.has_tracepoint()) {
258     const auto& tracepoint_pb = event_desc.tracepoint();
259     std::optional<uint32_t> maybe_id =
260         ParseTracepointAndResolveId(tracepoint_pb, tracepoint_id_lookup);
261     if (!maybe_id)
262       return std::nullopt;
263     return PerfCounter::Tracepoint(name, tracepoint_pb.name(),
264                                    tracepoint_pb.filter(), *maybe_id);
265   } else if (event_desc.has_raw_event()) {
266     const auto& raw = event_desc.raw_event();
267     return PerfCounter::RawEvent(name, raw.type(), raw.config(), raw.config1(),
268                                  raw.config2());
269   } else {
270     return PerfCounter::BuiltinCounter(
271         name, protos::gen::PerfEvents::PerfEvents::SW_CPU_CLOCK,
272         PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK);
273   }
274 }
275 
IsSupportedUnwindMode(protos::gen::PerfEventConfig::UnwindMode unwind_mode)276 bool IsSupportedUnwindMode(
277     protos::gen::PerfEventConfig::UnwindMode unwind_mode) {
278   using protos::gen::PerfEventConfig;
279   switch (static_cast<int>(unwind_mode)) {  // cast to pacify -Wswitch-enum
280     case PerfEventConfig::UNWIND_UNKNOWN:
281     case PerfEventConfig::UNWIND_SKIP:
282     case PerfEventConfig::UNWIND_DWARF:
283     case PerfEventConfig::UNWIND_FRAME_POINTER:
284       return true;
285     default:
286       return false;
287   }
288 }
289 
290 }  // namespace
291 
292 // static
BuiltinCounter(std::string name,protos::gen::PerfEvents::Counter counter,uint32_t type,uint64_t config)293 PerfCounter PerfCounter::BuiltinCounter(
294     std::string name,
295     protos::gen::PerfEvents::Counter counter,
296     uint32_t type,
297     uint64_t config) {
298   PerfCounter ret;
299   ret.type = PerfCounter::Type::kBuiltinCounter;
300   ret.counter = counter;
301   ret.name = std::move(name);
302 
303   ret.attr_type = type;
304   ret.attr_config = config;
305   // none of the builtin counters require config1 and config2 at the moment
306   return ret;
307 }
308 
309 // static
Tracepoint(std::string name,std::string tracepoint_name,std::string tracepoint_filter,uint64_t id)310 PerfCounter PerfCounter::Tracepoint(std::string name,
311                                     std::string tracepoint_name,
312                                     std::string tracepoint_filter,
313                                     uint64_t id) {
314   PerfCounter ret;
315   ret.type = PerfCounter::Type::kTracepoint;
316   ret.tracepoint_name = std::move(tracepoint_name);
317   ret.tracepoint_filter = std::move(tracepoint_filter);
318   ret.name = std::move(name);
319 
320   ret.attr_type = PERF_TYPE_TRACEPOINT;
321   ret.attr_config = id;
322   return ret;
323 }
324 
325 // static
RawEvent(std::string name,uint32_t type,uint64_t config,uint64_t config1,uint64_t config2)326 PerfCounter PerfCounter::RawEvent(std::string name,
327                                   uint32_t type,
328                                   uint64_t config,
329                                   uint64_t config1,
330                                   uint64_t config2) {
331   PerfCounter ret;
332   ret.type = PerfCounter::Type::kRawEvent;
333   ret.name = std::move(name);
334 
335   ret.attr_type = type;
336   ret.attr_config = config;
337   ret.attr_config1 = config1;
338   ret.attr_config2 = config2;
339   return ret;
340 }
341 
342 // static
Create(const protos::gen::PerfEventConfig & pb_config,const DataSourceConfig & raw_ds_config,std::optional<ProcessSharding> process_sharding,tracepoint_id_fn_t tracepoint_id_lookup)343 std::optional<EventConfig> EventConfig::Create(
344     const protos::gen::PerfEventConfig& pb_config,
345     const DataSourceConfig& raw_ds_config,
346     std::optional<ProcessSharding> process_sharding,
347     tracepoint_id_fn_t tracepoint_id_lookup) {
348   // Timebase: sampling interval.
349   uint64_t sampling_frequency = 0;
350   uint64_t sampling_period = 0;
351   if (pb_config.timebase().period()) {
352     sampling_period = pb_config.timebase().period();
353   } else if (pb_config.timebase().frequency()) {
354     sampling_frequency = pb_config.timebase().frequency();
355   } else if (pb_config.sampling_frequency()) {  // backwards compatibility
356     sampling_frequency = pb_config.sampling_frequency();
357   } else {
358     sampling_frequency = kDefaultSamplingFrequencyHz;
359   }
360   PERFETTO_DCHECK(sampling_period && !sampling_frequency ||
361                   !sampling_period && sampling_frequency);
362 
363   // Leader event. Default: CPU timer.
364   PerfCounter timebase_event;
365   std::string timebase_name = pb_config.timebase().name();
366 
367   // Build timebase.
368   auto maybe_perf_counter = MakePerfCounter(tracepoint_id_lookup, timebase_name,
369                                             pb_config.timebase());
370   if (!maybe_perf_counter) {
371     return std::nullopt;
372   }
373   timebase_event = std::move(*maybe_perf_counter);
374 
375   // Build the followers.
376   std::vector<PerfCounter> followers;
377   for (const auto& event : pb_config.followers()) {
378     const auto& name = event.name();
379     auto maybe_follower_counter =
380         MakePerfCounter(tracepoint_id_lookup, name, event);
381     if (!maybe_follower_counter) {
382       return std::nullopt;
383     }
384     followers.push_back(std::move(*maybe_follower_counter));
385   }
386 
387   // Callstack sampling.
388   bool kernel_frames = false;
389   // Disable user_frames by default.
390   auto unwind_mode = protos::gen::PerfEventConfig::UNWIND_SKIP;
391 
392   TargetFilter target_filter;
393   bool legacy_config = pb_config.all_cpus();  // all_cpus was mandatory before
394   if (pb_config.has_callstack_sampling() || legacy_config) {
395     // Userspace callstacks.
396     unwind_mode = pb_config.callstack_sampling().user_frames();
397     if (!IsSupportedUnwindMode(unwind_mode)) {
398       // enum value from the future that we don't yet know, refuse the config
399       return std::nullopt;
400     }
401 
402     // Process scoping. Sharding parameter is supplied from outside as it is
403     // shared by all data sources within a tracing session.
404     target_filter =
405         pb_config.callstack_sampling().has_scope()
406             ? ParseTargetFilter(pb_config.callstack_sampling().scope(),
407                                 process_sharding)
408             : ParseTargetFilter(pb_config,
409                                 process_sharding);  // backwards compatibility
410 
411     // Kernel callstacks.
412     kernel_frames = pb_config.callstack_sampling().kernel_frames() ||
413                     pb_config.kernel_frames();
414   }
415 
416   // Ring buffer options.
417   std::optional<uint32_t> ring_buffer_pages =
418       ChooseActualRingBufferPages(pb_config.ring_buffer_pages());
419   if (!ring_buffer_pages.has_value())
420     return std::nullopt;
421 
422   uint32_t read_tick_period_ms = pb_config.ring_buffer_read_period_ms()
423                                      ? pb_config.ring_buffer_read_period_ms()
424                                      : kDefaultReadTickPeriodMs;
425 
426   // Calculate a rough upper limit for the amount of samples the producer
427   // should read per read tick, as a safeguard against getting stuck chasing the
428   // ring buffer head indefinitely.
429   uint64_t samples_per_tick_limit = 0;
430   if (sampling_frequency) {
431     // expected = rate * period, with a conversion of period from ms to s:
432     uint64_t expected_samples_per_tick =
433         1 + (sampling_frequency * read_tick_period_ms) / 1000;
434     // Double the limit to account of actual sample rate uncertainties, as
435     // well as any other factors:
436     samples_per_tick_limit = 2 * expected_samples_per_tick;
437   } else {  // sampling_period
438     // We don't know the sample rate that a fixed period would cause, but we can
439     // still estimate how many samples will fit in one pass of the ring buffer
440     // (with the assumption that we don't want to read more than one buffer's
441     // capacity within a tick).
442     // TODO(rsavitski): for now, make an extremely conservative guess of an 8
443     // byte sample (stack sampling samples can be up to 64KB). This is most
444     // likely as good as no limit in practice.
445     samples_per_tick_limit = *ring_buffer_pages * (base::GetSysPageSize() / 8);
446   }
447   PERFETTO_DLOG("Capping samples (not records) per tick to [%" PRIu64 "]",
448                 samples_per_tick_limit);
449   if (samples_per_tick_limit == 0)
450     return std::nullopt;
451 
452   // Optional footprint controls.
453   uint64_t max_enqueued_footprint_bytes =
454       pb_config.max_enqueued_footprint_kb() * 1024;
455 
456   // Android-specific options.
457   uint32_t remote_descriptor_timeout_ms =
458       pb_config.remote_descriptor_timeout_ms()
459           ? pb_config.remote_descriptor_timeout_ms()
460           : kDefaultRemoteDescriptorTimeoutMs;
461 
462   // Build the underlying syscall config struct.
463   perf_event_attr pe = {};
464   pe.size = sizeof(perf_event_attr);
465   pe.disabled = 1;  // will be activated via ioctl
466 
467   // Sampling timebase.
468   pe.type = timebase_event.attr_type;
469   pe.config = timebase_event.attr_config;
470   pe.config1 = timebase_event.attr_config1;
471   pe.config2 = timebase_event.attr_config2;
472   if (sampling_frequency) {
473     pe.freq = true;
474     pe.sample_freq = sampling_frequency;
475   } else {
476     pe.sample_period = sampling_period;
477   }
478 
479   // What the samples will contain.
480   pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_READ;
481   // PERF_SAMPLE_TIME:
482   pe.clockid = ToClockId(pb_config.timebase().timestamp_clock());
483   pe.use_clockid = true;
484 
485   if (IsUserFramesEnabled(unwind_mode)) {
486     pe.sample_type |= PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER;
487     // PERF_SAMPLE_STACK_USER:
488     // Needs to be < ((u16)(~0u)), and have bottom 8 bits clear.
489     // Note that the kernel still needs to make space for the other parts of the
490     // sample (up to the max record size of 64k), so the effective maximum
491     // can be lower than this.
492     pe.sample_stack_user = (1u << 16) - 256;
493     // PERF_SAMPLE_REGS_USER:
494     pe.sample_regs_user =
495         PerfUserRegsMaskForArch(unwindstack::Regs::CurrentArch());
496   }
497   if (kernel_frames) {
498     pe.sample_type |= PERF_SAMPLE_CALLCHAIN;
499     pe.exclude_callchain_user = true;
500   }
501 
502   // Build the events associated with the timebase event (pe).
503   // The timebase event drives the capture with its frequency or period
504   // parameter. When linux captures the timebase event it also reads and report
505   // the values of associated events.
506   std::vector<perf_event_attr> pe_followers;
507   if (!followers.empty()) {
508     pe.read_format = PERF_FORMAT_GROUP;
509     pe_followers.reserve(followers.size());
510   }
511 
512   for (const auto& e : followers) {
513     perf_event_attr pe_follower = {};
514     pe_follower.size = sizeof(perf_event_attr);
515     pe_follower.disabled = 0;  // activated when the timebase is activated
516     pe_follower.type = e.attr_type;
517     pe_follower.config = e.attr_config;
518     pe_follower.config1 = e.attr_config1;
519     pe_follower.config2 = e.attr_config2;
520     pe_follower.sample_type =
521         PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_READ;
522     pe_follower.freq = 0;
523     pe_follower.sample_period = 0;
524     pe_follower.clockid = ToClockId(pb_config.timebase().timestamp_clock());
525     pe_follower.use_clockid = true;
526 
527     pe_followers.push_back(pe_follower);
528   }
529 
530   return EventConfig(
531       raw_ds_config, pe, std::move(pe_followers), timebase_event, followers,
532       kernel_frames, unwind_mode, std::move(target_filter),
533       ring_buffer_pages.value(), read_tick_period_ms, samples_per_tick_limit,
534       remote_descriptor_timeout_ms, pb_config.unwind_state_clear_period_ms(),
535       max_enqueued_footprint_bytes, pb_config.target_installed_by());
536 }
537 
538 // static
IsUserFramesEnabled(const protos::gen::PerfEventConfig::UnwindMode unwind_mode)539 bool EventConfig::IsUserFramesEnabled(
540     const protos::gen::PerfEventConfig::UnwindMode unwind_mode) {
541   using protos::gen::PerfEventConfig;
542   switch (unwind_mode) {
543     case PerfEventConfig::UNWIND_UNKNOWN:
544     // default to true, both for backwards compatibility and because it's
545     // almost always what the user wants.
546     case PerfEventConfig::UNWIND_DWARF:
547     case PerfEventConfig::UNWIND_FRAME_POINTER:
548       return true;
549     case PerfEventConfig::UNWIND_SKIP:
550       return false;
551   }
552 }
553 
EventConfig(const DataSourceConfig & raw_ds_config,const perf_event_attr & pe_timebase,std::vector<perf_event_attr> pe_followers,const PerfCounter & timebase_event,std::vector<PerfCounter> follower_events,bool kernel_frames,protos::gen::PerfEventConfig::UnwindMode unwind_mode,TargetFilter target_filter,uint32_t ring_buffer_pages,uint32_t read_tick_period_ms,uint64_t samples_per_tick_limit,uint32_t remote_descriptor_timeout_ms,uint32_t unwind_state_clear_period_ms,uint64_t max_enqueued_footprint_bytes,std::vector<std::string> target_installed_by)554 EventConfig::EventConfig(const DataSourceConfig& raw_ds_config,
555                          const perf_event_attr& pe_timebase,
556                          std::vector<perf_event_attr> pe_followers,
557                          const PerfCounter& timebase_event,
558                          std::vector<PerfCounter> follower_events,
559                          bool kernel_frames,
560                          protos::gen::PerfEventConfig::UnwindMode unwind_mode,
561                          TargetFilter target_filter,
562                          uint32_t ring_buffer_pages,
563                          uint32_t read_tick_period_ms,
564                          uint64_t samples_per_tick_limit,
565                          uint32_t remote_descriptor_timeout_ms,
566                          uint32_t unwind_state_clear_period_ms,
567                          uint64_t max_enqueued_footprint_bytes,
568                          std::vector<std::string> target_installed_by)
569     : perf_event_attr_(pe_timebase),
570       perf_event_followers_(std::move(pe_followers)),
571       timebase_event_(timebase_event),
572       follower_events_(std::move(follower_events)),
573       kernel_frames_(kernel_frames),
574       unwind_mode_(unwind_mode),
575       target_filter_(std::move(target_filter)),
576       ring_buffer_pages_(ring_buffer_pages),
577       read_tick_period_ms_(read_tick_period_ms),
578       samples_per_tick_limit_(samples_per_tick_limit),
579       remote_descriptor_timeout_ms_(remote_descriptor_timeout_ms),
580       unwind_state_clear_period_ms_(unwind_state_clear_period_ms),
581       max_enqueued_footprint_bytes_(max_enqueued_footprint_bytes),
582       target_installed_by_(std::move(target_installed_by)),
583       raw_ds_config_(raw_ds_config) /* full copy */ {}
584 
585 }  // namespace profiling
586 }  // namespace perfetto
587