• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 #include "perfetto/base/flat_set.h"
25 #include "perfetto/ext/base/optional.h"
26 #include "perfetto/profiling/normalize.h"
27 #include "src/profiling/perf/regs_parsing.h"
28 
29 #include "protos/perfetto/config/profiling/perf_event_config.pbzero.h"
30 
31 namespace perfetto {
32 namespace profiling {
33 
34 namespace {
35 constexpr uint64_t kDefaultSamplingFrequencyHz = 10;
36 constexpr uint32_t kDefaultDataPagesPerRingBuffer = 256;  // 1 MB: 256x 4k pages
37 constexpr uint32_t kDefaultReadTickPeriodMs = 100;
38 constexpr uint32_t kDefaultRemoteDescriptorTimeoutMs = 100;
39 
Normalize(const protozero::ConstChars & src)40 base::Optional<std::string> Normalize(const protozero::ConstChars& src) {
41   // Construct a null-terminated string that will be mutated by the normalizer.
42   std::vector<char> base(src.size + 1);
43   memcpy(base.data(), src.data, src.size);
44   base[src.size] = '\0';
45 
46   char* new_start = base.data();
47   ssize_t new_sz = NormalizeCmdLine(&new_start, base.size());
48   if (new_sz < 0) {
49     PERFETTO_ELOG("Failed to normalize config cmdline [%s], aborting",
50                   base.data());
51     return base::nullopt;
52   }
53   return base::make_optional<std::string>(new_start,
54                                           static_cast<size_t>(new_sz));
55 }
56 
57 // returns |base::nullopt| if any of the input cmdlines couldn't be normalized.
ParseTargetFilter(const protos::pbzero::PerfEventConfig::Decoder & cfg)58 base::Optional<TargetFilter> ParseTargetFilter(
59     const protos::pbzero::PerfEventConfig::Decoder& cfg) {
60   TargetFilter filter;
61   for (auto it = cfg.target_cmdline(); it; ++it) {
62     base::Optional<std::string> opt = Normalize(*it);
63     if (!opt.has_value())
64       return base::nullopt;
65     filter.cmdlines.insert(std::move(opt.value()));
66   }
67 
68   for (auto it = cfg.exclude_cmdline(); it; ++it) {
69     base::Optional<std::string> opt = Normalize(*it);
70     if (!opt.has_value())
71       return base::nullopt;
72     filter.exclude_cmdlines.insert(std::move(opt.value()));
73   }
74 
75   for (auto it = cfg.target_pid(); it; ++it) {
76     filter.pids.insert(*it);
77   }
78 
79   for (auto it = cfg.exclude_pid(); it; ++it) {
80     filter.exclude_pids.insert(*it);
81   }
82   return base::make_optional(std::move(filter));
83 }
84 
IsPowerOfTwo(size_t v)85 constexpr bool IsPowerOfTwo(size_t v) {
86   return (v != 0 && ((v & (v - 1)) == 0));
87 }
88 
89 // returns |base::nullopt| if the input is invalid.
ChooseActualRingBufferPages(uint32_t config_value)90 base::Optional<uint32_t> ChooseActualRingBufferPages(uint32_t config_value) {
91   if (!config_value) {
92     static_assert(IsPowerOfTwo(kDefaultDataPagesPerRingBuffer), "");
93     return base::make_optional(kDefaultDataPagesPerRingBuffer);
94   }
95 
96   if (!IsPowerOfTwo(config_value)) {
97     PERFETTO_ELOG("kernel buffer size must be a power of two pages");
98     return base::nullopt;
99   }
100 
101   return base::make_optional(config_value);
102 }
103 
104 }  // namespace
105 
106 // static
Create(const DataSourceConfig & ds_config)107 base::Optional<EventConfig> EventConfig::Create(
108     const DataSourceConfig& ds_config) {
109   protos::pbzero::PerfEventConfig::Decoder pb_config(
110       ds_config.perf_event_config_raw());
111 
112   base::Optional<TargetFilter> filter = ParseTargetFilter(pb_config);
113   if (!filter.has_value())
114     return base::nullopt;
115 
116   base::Optional<uint32_t> ring_buffer_pages =
117       ChooseActualRingBufferPages(pb_config.ring_buffer_pages());
118   if (!ring_buffer_pages.has_value())
119     return base::nullopt;
120 
121   uint32_t remote_descriptor_timeout_ms =
122       pb_config.remote_descriptor_timeout_ms()
123           ? pb_config.remote_descriptor_timeout_ms()
124           : kDefaultRemoteDescriptorTimeoutMs;
125 
126   uint32_t read_tick_period_ms = pb_config.ring_buffer_read_period_ms()
127                                      ? pb_config.ring_buffer_read_period_ms()
128                                      : kDefaultReadTickPeriodMs;
129 
130   uint32_t sampling_frequency = pb_config.sampling_frequency()
131                                     ? pb_config.sampling_frequency()
132                                     : kDefaultSamplingFrequencyHz;
133 
134   // Take the ratio of sampling and reading frequencies, which gives the
135   // upper bound on number of samples per tick (for a single per-cpu buffer).
136   // Overflow not a concern for sane inputs.
137   uint32_t expected_samples_per_tick =
138       1 + (sampling_frequency * read_tick_period_ms) / 1000;
139 
140   // Use double the expected value as the actual guardrail (don't assume that
141   // periodic read task is as exact as the kernel).
142   uint32_t samples_per_tick_limit = 2 * expected_samples_per_tick;
143   PERFETTO_DCHECK(samples_per_tick_limit > 0);
144   PERFETTO_DLOG("Capping samples (not records) per tick to [%" PRIu32 "]",
145                 samples_per_tick_limit);
146 
147   return EventConfig(pb_config, sampling_frequency, ring_buffer_pages.value(),
148                      read_tick_period_ms, samples_per_tick_limit,
149                      remote_descriptor_timeout_ms, std::move(filter.value()));
150 }
151 
EventConfig(const protos::pbzero::PerfEventConfig::Decoder & cfg,uint32_t sampling_frequency,uint32_t ring_buffer_pages,uint32_t read_tick_period_ms,uint32_t samples_per_tick_limit,uint32_t remote_descriptor_timeout_ms,TargetFilter target_filter)152 EventConfig::EventConfig(const protos::pbzero::PerfEventConfig::Decoder& cfg,
153                          uint32_t sampling_frequency,
154                          uint32_t ring_buffer_pages,
155                          uint32_t read_tick_period_ms,
156                          uint32_t samples_per_tick_limit,
157                          uint32_t remote_descriptor_timeout_ms,
158                          TargetFilter target_filter)
159     : target_all_cpus_(cfg.all_cpus()),
160       ring_buffer_pages_(ring_buffer_pages),
161       read_tick_period_ms_(read_tick_period_ms),
162       samples_per_tick_limit_(samples_per_tick_limit),
163       target_filter_(std::move(target_filter)),
164       remote_descriptor_timeout_ms_(remote_descriptor_timeout_ms),
165       unwind_state_clear_period_ms_(cfg.unwind_state_clear_period_ms()) {
166   auto& pe = perf_event_attr_;
167   pe.size = sizeof(perf_event_attr);
168 
169   pe.disabled = false;
170 
171   // Ask the kernel to sample at a given frequency.
172   pe.type = PERF_TYPE_SOFTWARE;
173   pe.config = PERF_COUNT_SW_CPU_CLOCK;
174   pe.freq = true;
175   pe.sample_freq = sampling_frequency;
176 
177   pe.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_STACK_USER |
178                    PERF_SAMPLE_REGS_USER;
179   // PERF_SAMPLE_TIME:
180   pe.clockid = CLOCK_BOOTTIME;
181   pe.use_clockid = true;
182   // PERF_SAMPLE_STACK_USER:
183   // Needs to be < ((u16)(~0u)), and have bottom 8 bits clear.
184   pe.sample_stack_user = (1u << 15);
185   // PERF_SAMPLE_REGS_USER:
186   pe.sample_regs_user =
187       PerfUserRegsMaskForArch(unwindstack::Regs::CurrentArch());
188 }
189 
190 }  // namespace profiling
191 }  // namespace perfetto
192