xref: /aosp_15_r20/external/perfetto/src/profiling/perf/perf_producer.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/perf_producer.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <optional>
20*6dbdd20aSAndroid Build Coastguard Worker #include <random>
21*6dbdd20aSAndroid Build Coastguard Worker #include <utility>
22*6dbdd20aSAndroid Build Coastguard Worker #include <vector>
23*6dbdd20aSAndroid Build Coastguard Worker 
24*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
25*6dbdd20aSAndroid Build Coastguard Worker 
26*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Error.h>
27*6dbdd20aSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
28*6dbdd20aSAndroid Build Coastguard Worker 
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/task_runner.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/metatrace.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
35*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/weak_ptr.h"
36*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/basic_types.h"
37*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/producer.h"
38*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/tracing_service.h"
39*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
40*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/core/data_source_config.h"
41*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing/core/data_source_descriptor.h"
42*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/callstack_trie.h"
43*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/proc_cmdline.h"
44*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/producer_support.h"
45*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/profiler_guardrails.h"
46*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/common/unwind_support.h"
47*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/common_types.h"
48*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/event_reader.h"
49*6dbdd20aSAndroid Build Coastguard Worker 
50*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/common/builtin_clock.pbzero.h"
51*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/common/perf_events.gen.h"
52*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/common/perf_events.pbzero.h"
53*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/config/profiling/perf_event_config.gen.h"
54*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
55*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/trace_packet.pbzero.h"
56*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
57*6dbdd20aSAndroid Build Coastguard Worker 
58*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
59*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
60*6dbdd20aSAndroid Build Coastguard Worker namespace {
61*6dbdd20aSAndroid Build Coastguard Worker 
62*6dbdd20aSAndroid Build Coastguard Worker // TODO(b/151835887): on Android, when using signals, there exists a vulnerable
63*6dbdd20aSAndroid Build Coastguard Worker // window between a process image being replaced by execve, and the new
64*6dbdd20aSAndroid Build Coastguard Worker // libc instance reinstalling the proper signal handlers. During this window,
65*6dbdd20aSAndroid Build Coastguard Worker // the signal disposition is defaulted to terminating the process.
66*6dbdd20aSAndroid Build Coastguard Worker // This is a best-effort mitigation from the daemon's side, using a heuristic
67*6dbdd20aSAndroid Build Coastguard Worker // that most execve calls follow a fork. So if we get a sample for a very fresh
68*6dbdd20aSAndroid Build Coastguard Worker // process, the grace period will give it a chance to get to
69*6dbdd20aSAndroid Build Coastguard Worker // a properly initialised state prior to getting signalled. This doesn't help
70*6dbdd20aSAndroid Build Coastguard Worker // cases when a mature process calls execve, or when the target gets descheduled
71*6dbdd20aSAndroid Build Coastguard Worker // (since this is a naive walltime wait).
72*6dbdd20aSAndroid Build Coastguard Worker // The proper fix is in the platform, see bug for progress.
73*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kProcDescriptorsAndroidDelayMs = 50;
74*6dbdd20aSAndroid Build Coastguard Worker 
75*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kMemoryLimitCheckPeriodMs = 1000;
76*6dbdd20aSAndroid Build Coastguard Worker 
77*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kInitialConnectionBackoffMs = 100;
78*6dbdd20aSAndroid Build Coastguard Worker constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
79*6dbdd20aSAndroid Build Coastguard Worker 
80*6dbdd20aSAndroid Build Coastguard Worker constexpr char kProducerName[] = "perfetto.traced_perf";
81*6dbdd20aSAndroid Build Coastguard Worker constexpr char kDataSourceName[] = "linux.perf";
82*6dbdd20aSAndroid Build Coastguard Worker 
NumberOfCpus()83*6dbdd20aSAndroid Build Coastguard Worker size_t NumberOfCpus() {
84*6dbdd20aSAndroid Build Coastguard Worker   return static_cast<size_t>(sysconf(_SC_NPROCESSORS_CONF));
85*6dbdd20aSAndroid Build Coastguard Worker }
86*6dbdd20aSAndroid Build Coastguard Worker 
GetOnlineCpus()87*6dbdd20aSAndroid Build Coastguard Worker std::vector<uint32_t> GetOnlineCpus() {
88*6dbdd20aSAndroid Build Coastguard Worker   size_t cpu_count = NumberOfCpus();
89*6dbdd20aSAndroid Build Coastguard Worker   if (cpu_count == 0) {
90*6dbdd20aSAndroid Build Coastguard Worker     return {};
91*6dbdd20aSAndroid Build Coastguard Worker   }
92*6dbdd20aSAndroid Build Coastguard Worker 
93*6dbdd20aSAndroid Build Coastguard Worker   static constexpr char kOnlineValue[] = "1\n";
94*6dbdd20aSAndroid Build Coastguard Worker   std::vector<uint32_t> online_cpus;
95*6dbdd20aSAndroid Build Coastguard Worker   online_cpus.reserve(cpu_count);
96*6dbdd20aSAndroid Build Coastguard Worker   for (uint32_t cpu = 0; cpu < cpu_count; ++cpu) {
97*6dbdd20aSAndroid Build Coastguard Worker     std::string res;
98*6dbdd20aSAndroid Build Coastguard Worker     base::StackString<1024> path("/sys/devices/system/cpu/cpu%u/online", cpu);
99*6dbdd20aSAndroid Build Coastguard Worker     if (!base::ReadFile(path.c_str(), &res)) {
100*6dbdd20aSAndroid Build Coastguard Worker       // Always consider CPU 0 to be online if the "online" file does not exist
101*6dbdd20aSAndroid Build Coastguard Worker       // for it. There seem to be several assumptions in the kernel which make
102*6dbdd20aSAndroid Build Coastguard Worker       // CPU 0 special so this is a pretty safe bet.
103*6dbdd20aSAndroid Build Coastguard Worker       if (cpu != 0) {
104*6dbdd20aSAndroid Build Coastguard Worker         return {};
105*6dbdd20aSAndroid Build Coastguard Worker       }
106*6dbdd20aSAndroid Build Coastguard Worker       res = kOnlineValue;
107*6dbdd20aSAndroid Build Coastguard Worker     }
108*6dbdd20aSAndroid Build Coastguard Worker     if (res != kOnlineValue) {
109*6dbdd20aSAndroid Build Coastguard Worker       continue;
110*6dbdd20aSAndroid Build Coastguard Worker     }
111*6dbdd20aSAndroid Build Coastguard Worker     online_cpus.push_back(cpu);
112*6dbdd20aSAndroid Build Coastguard Worker   }
113*6dbdd20aSAndroid Build Coastguard Worker   return online_cpus;
114*6dbdd20aSAndroid Build Coastguard Worker }
115*6dbdd20aSAndroid Build Coastguard Worker 
ToBuiltinClock(int32_t clockid)116*6dbdd20aSAndroid Build Coastguard Worker int32_t ToBuiltinClock(int32_t clockid) {
117*6dbdd20aSAndroid Build Coastguard Worker   switch (clockid) {
118*6dbdd20aSAndroid Build Coastguard Worker     case CLOCK_REALTIME:
119*6dbdd20aSAndroid Build Coastguard Worker       return protos::pbzero::BUILTIN_CLOCK_REALTIME;
120*6dbdd20aSAndroid Build Coastguard Worker     case CLOCK_MONOTONIC:
121*6dbdd20aSAndroid Build Coastguard Worker       return protos::pbzero::BUILTIN_CLOCK_MONOTONIC;
122*6dbdd20aSAndroid Build Coastguard Worker     case CLOCK_MONOTONIC_RAW:
123*6dbdd20aSAndroid Build Coastguard Worker       return protos::pbzero::BUILTIN_CLOCK_MONOTONIC_RAW;
124*6dbdd20aSAndroid Build Coastguard Worker     case CLOCK_BOOTTIME:
125*6dbdd20aSAndroid Build Coastguard Worker       return protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
126*6dbdd20aSAndroid Build Coastguard Worker     // Should never get invalid input here as otherwise the syscall itself
127*6dbdd20aSAndroid Build Coastguard Worker     // would've failed earlier.
128*6dbdd20aSAndroid Build Coastguard Worker     default:
129*6dbdd20aSAndroid Build Coastguard Worker       return protos::pbzero::BUILTIN_CLOCK_UNKNOWN;
130*6dbdd20aSAndroid Build Coastguard Worker   }
131*6dbdd20aSAndroid Build Coastguard Worker }
132*6dbdd20aSAndroid Build Coastguard Worker 
StartTracePacket(TraceWriter * trace_writer)133*6dbdd20aSAndroid Build Coastguard Worker TraceWriter::TracePacketHandle StartTracePacket(TraceWriter* trace_writer) {
134*6dbdd20aSAndroid Build Coastguard Worker   auto packet = trace_writer->NewTracePacket();
135*6dbdd20aSAndroid Build Coastguard Worker   packet->set_sequence_flags(
136*6dbdd20aSAndroid Build Coastguard Worker       protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
137*6dbdd20aSAndroid Build Coastguard Worker   return packet;
138*6dbdd20aSAndroid Build Coastguard Worker }
139*6dbdd20aSAndroid Build Coastguard Worker 
WritePerfEventDefaultsPacket(const EventConfig & event_config,TraceWriter * trace_writer)140*6dbdd20aSAndroid Build Coastguard Worker void WritePerfEventDefaultsPacket(const EventConfig& event_config,
141*6dbdd20aSAndroid Build Coastguard Worker                                   TraceWriter* trace_writer) {
142*6dbdd20aSAndroid Build Coastguard Worker   auto packet = trace_writer->NewTracePacket();
143*6dbdd20aSAndroid Build Coastguard Worker   packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
144*6dbdd20aSAndroid Build Coastguard Worker   packet->set_timestamp_clock_id(protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
145*6dbdd20aSAndroid Build Coastguard Worker 
146*6dbdd20aSAndroid Build Coastguard Worker   // start new incremental state generation:
147*6dbdd20aSAndroid Build Coastguard Worker   packet->set_sequence_flags(
148*6dbdd20aSAndroid Build Coastguard Worker       protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
149*6dbdd20aSAndroid Build Coastguard Worker 
150*6dbdd20aSAndroid Build Coastguard Worker   // default packet timestamp clock for the samples:
151*6dbdd20aSAndroid Build Coastguard Worker   perf_event_attr* perf_attr = event_config.perf_attr();
152*6dbdd20aSAndroid Build Coastguard Worker   auto* defaults = packet->set_trace_packet_defaults();
153*6dbdd20aSAndroid Build Coastguard Worker   int32_t builtin_clock = ToBuiltinClock(perf_attr->clockid);
154*6dbdd20aSAndroid Build Coastguard Worker   defaults->set_timestamp_clock_id(static_cast<uint32_t>(builtin_clock));
155*6dbdd20aSAndroid Build Coastguard Worker 
156*6dbdd20aSAndroid Build Coastguard Worker   auto* perf_defaults = defaults->set_perf_sample_defaults();
157*6dbdd20aSAndroid Build Coastguard Worker   auto* timebase_pb = perf_defaults->set_timebase();
158*6dbdd20aSAndroid Build Coastguard Worker 
159*6dbdd20aSAndroid Build Coastguard Worker   // frequency/period:
160*6dbdd20aSAndroid Build Coastguard Worker   if (perf_attr->freq) {
161*6dbdd20aSAndroid Build Coastguard Worker     timebase_pb->set_frequency(perf_attr->sample_freq);
162*6dbdd20aSAndroid Build Coastguard Worker   } else {
163*6dbdd20aSAndroid Build Coastguard Worker     timebase_pb->set_period(perf_attr->sample_period);
164*6dbdd20aSAndroid Build Coastguard Worker   }
165*6dbdd20aSAndroid Build Coastguard Worker 
166*6dbdd20aSAndroid Build Coastguard Worker   // timebase event:
167*6dbdd20aSAndroid Build Coastguard Worker   const PerfCounter& timebase = event_config.timebase_event();
168*6dbdd20aSAndroid Build Coastguard Worker   switch (timebase.event_type()) {
169*6dbdd20aSAndroid Build Coastguard Worker     case PerfCounter::Type::kBuiltinCounter: {
170*6dbdd20aSAndroid Build Coastguard Worker       timebase_pb->set_counter(
171*6dbdd20aSAndroid Build Coastguard Worker           static_cast<protos::pbzero::PerfEvents::Counter>(timebase.counter));
172*6dbdd20aSAndroid Build Coastguard Worker       break;
173*6dbdd20aSAndroid Build Coastguard Worker     }
174*6dbdd20aSAndroid Build Coastguard Worker     case PerfCounter::Type::kTracepoint: {
175*6dbdd20aSAndroid Build Coastguard Worker       auto* tracepoint_pb = timebase_pb->set_tracepoint();
176*6dbdd20aSAndroid Build Coastguard Worker       tracepoint_pb->set_name(timebase.tracepoint_name);
177*6dbdd20aSAndroid Build Coastguard Worker       tracepoint_pb->set_filter(timebase.tracepoint_filter);
178*6dbdd20aSAndroid Build Coastguard Worker       break;
179*6dbdd20aSAndroid Build Coastguard Worker     }
180*6dbdd20aSAndroid Build Coastguard Worker     case PerfCounter::Type::kRawEvent: {
181*6dbdd20aSAndroid Build Coastguard Worker       auto* raw_pb = timebase_pb->set_raw_event();
182*6dbdd20aSAndroid Build Coastguard Worker       raw_pb->set_type(timebase.attr_type);
183*6dbdd20aSAndroid Build Coastguard Worker       raw_pb->set_config(timebase.attr_config);
184*6dbdd20aSAndroid Build Coastguard Worker       raw_pb->set_config1(timebase.attr_config1);
185*6dbdd20aSAndroid Build Coastguard Worker       raw_pb->set_config2(timebase.attr_config2);
186*6dbdd20aSAndroid Build Coastguard Worker       break;
187*6dbdd20aSAndroid Build Coastguard Worker     }
188*6dbdd20aSAndroid Build Coastguard Worker   }
189*6dbdd20aSAndroid Build Coastguard Worker 
190*6dbdd20aSAndroid Build Coastguard Worker   // optional name to identify the counter during parsing:
191*6dbdd20aSAndroid Build Coastguard Worker   if (!timebase.name.empty()) {
192*6dbdd20aSAndroid Build Coastguard Worker     timebase_pb->set_name(timebase.name);
193*6dbdd20aSAndroid Build Coastguard Worker   }
194*6dbdd20aSAndroid Build Coastguard Worker 
195*6dbdd20aSAndroid Build Coastguard Worker   // follower events:
196*6dbdd20aSAndroid Build Coastguard Worker   for (const auto& e : event_config.follower_events()) {
197*6dbdd20aSAndroid Build Coastguard Worker     auto* followers_pb = perf_defaults->add_followers();
198*6dbdd20aSAndroid Build Coastguard Worker     followers_pb->set_name(e.name);
199*6dbdd20aSAndroid Build Coastguard Worker 
200*6dbdd20aSAndroid Build Coastguard Worker     switch (e.event_type()) {
201*6dbdd20aSAndroid Build Coastguard Worker       case PerfCounter::Type::kBuiltinCounter: {
202*6dbdd20aSAndroid Build Coastguard Worker         followers_pb->set_counter(
203*6dbdd20aSAndroid Build Coastguard Worker             static_cast<protos::pbzero::PerfEvents::Counter>(e.counter));
204*6dbdd20aSAndroid Build Coastguard Worker         break;
205*6dbdd20aSAndroid Build Coastguard Worker       }
206*6dbdd20aSAndroid Build Coastguard Worker       case PerfCounter::Type::kTracepoint: {
207*6dbdd20aSAndroid Build Coastguard Worker         auto* tracepoint_pb = followers_pb->set_tracepoint();
208*6dbdd20aSAndroid Build Coastguard Worker         tracepoint_pb->set_name(e.tracepoint_name);
209*6dbdd20aSAndroid Build Coastguard Worker         tracepoint_pb->set_filter(e.tracepoint_filter);
210*6dbdd20aSAndroid Build Coastguard Worker         break;
211*6dbdd20aSAndroid Build Coastguard Worker       }
212*6dbdd20aSAndroid Build Coastguard Worker       case PerfCounter::Type::kRawEvent: {
213*6dbdd20aSAndroid Build Coastguard Worker         auto* raw_pb = followers_pb->set_raw_event();
214*6dbdd20aSAndroid Build Coastguard Worker         raw_pb->set_type(e.attr_type);
215*6dbdd20aSAndroid Build Coastguard Worker         raw_pb->set_config(e.attr_config);
216*6dbdd20aSAndroid Build Coastguard Worker         raw_pb->set_config1(e.attr_config1);
217*6dbdd20aSAndroid Build Coastguard Worker         raw_pb->set_config2(e.attr_config2);
218*6dbdd20aSAndroid Build Coastguard Worker         break;
219*6dbdd20aSAndroid Build Coastguard Worker       }
220*6dbdd20aSAndroid Build Coastguard Worker     }
221*6dbdd20aSAndroid Build Coastguard Worker   }
222*6dbdd20aSAndroid Build Coastguard Worker 
223*6dbdd20aSAndroid Build Coastguard Worker   // Not setting timebase.timestamp_clock since the field that matters during
224*6dbdd20aSAndroid Build Coastguard Worker   // parsing is the root timestamp_clock_id set above.
225*6dbdd20aSAndroid Build Coastguard Worker 
226*6dbdd20aSAndroid Build Coastguard Worker   // Record the random shard we've chosen so that the post-processing can infer
227*6dbdd20aSAndroid Build Coastguard Worker   // which processes would've been unwound if sampled. In particular this lets
228*6dbdd20aSAndroid Build Coastguard Worker   // us distinguish between "running but not chosen" and "running and chosen,
229*6dbdd20aSAndroid Build Coastguard Worker   // but not sampled" cases.
230*6dbdd20aSAndroid Build Coastguard Worker   const auto& process_sharding = event_config.filter().process_sharding;
231*6dbdd20aSAndroid Build Coastguard Worker   if (process_sharding.has_value()) {
232*6dbdd20aSAndroid Build Coastguard Worker     perf_defaults->set_process_shard_count(process_sharding->shard_count);
233*6dbdd20aSAndroid Build Coastguard Worker     perf_defaults->set_chosen_process_shard(process_sharding->chosen_shard);
234*6dbdd20aSAndroid Build Coastguard Worker   }
235*6dbdd20aSAndroid Build Coastguard Worker }
236*6dbdd20aSAndroid Build Coastguard Worker 
TimeToNextReadTickMs(DataSourceInstanceID ds_id,uint32_t period_ms)237*6dbdd20aSAndroid Build Coastguard Worker uint32_t TimeToNextReadTickMs(DataSourceInstanceID ds_id, uint32_t period_ms) {
238*6dbdd20aSAndroid Build Coastguard Worker   // Normally, we'd schedule the next tick at the next |period_ms|
239*6dbdd20aSAndroid Build Coastguard Worker   // boundary of the boot clock. However, to avoid aligning the read tasks of
240*6dbdd20aSAndroid Build Coastguard Worker   // all concurrent data sources, we select a deterministic offset based on the
241*6dbdd20aSAndroid Build Coastguard Worker   // data source id.
242*6dbdd20aSAndroid Build Coastguard Worker   std::minstd_rand prng(static_cast<std::minstd_rand::result_type>(ds_id));
243*6dbdd20aSAndroid Build Coastguard Worker   std::uniform_int_distribution<uint32_t> dist(0, period_ms - 1);
244*6dbdd20aSAndroid Build Coastguard Worker   uint32_t ds_period_offset = dist(prng);
245*6dbdd20aSAndroid Build Coastguard Worker 
246*6dbdd20aSAndroid Build Coastguard Worker   uint64_t now_ms = static_cast<uint64_t>(base::GetWallTimeMs().count());
247*6dbdd20aSAndroid Build Coastguard Worker   return period_ms - ((now_ms - ds_period_offset) % period_ms);
248*6dbdd20aSAndroid Build Coastguard Worker }
249*6dbdd20aSAndroid Build Coastguard Worker 
ToCpuModeEnum(uint16_t perf_cpu_mode)250*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::Profiling::CpuMode ToCpuModeEnum(uint16_t perf_cpu_mode) {
251*6dbdd20aSAndroid Build Coastguard Worker   using Profiling = protos::pbzero::Profiling;
252*6dbdd20aSAndroid Build Coastguard Worker   switch (perf_cpu_mode) {
253*6dbdd20aSAndroid Build Coastguard Worker     case PERF_RECORD_MISC_KERNEL:
254*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::MODE_KERNEL;
255*6dbdd20aSAndroid Build Coastguard Worker     case PERF_RECORD_MISC_USER:
256*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::MODE_USER;
257*6dbdd20aSAndroid Build Coastguard Worker     case PERF_RECORD_MISC_HYPERVISOR:
258*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::MODE_HYPERVISOR;
259*6dbdd20aSAndroid Build Coastguard Worker     case PERF_RECORD_MISC_GUEST_KERNEL:
260*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::MODE_GUEST_KERNEL;
261*6dbdd20aSAndroid Build Coastguard Worker     case PERF_RECORD_MISC_GUEST_USER:
262*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::MODE_GUEST_USER;
263*6dbdd20aSAndroid Build Coastguard Worker     default:
264*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::MODE_UNKNOWN;
265*6dbdd20aSAndroid Build Coastguard Worker   }
266*6dbdd20aSAndroid Build Coastguard Worker }
267*6dbdd20aSAndroid Build Coastguard Worker 
ToProtoEnum(unwindstack::ErrorCode error_code)268*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::Profiling::StackUnwindError ToProtoEnum(
269*6dbdd20aSAndroid Build Coastguard Worker     unwindstack::ErrorCode error_code) {
270*6dbdd20aSAndroid Build Coastguard Worker   using Profiling = protos::pbzero::Profiling;
271*6dbdd20aSAndroid Build Coastguard Worker   switch (error_code) {
272*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_NONE:
273*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_NONE;
274*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_MEMORY_INVALID:
275*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_MEMORY_INVALID;
276*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_UNWIND_INFO:
277*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_UNWIND_INFO;
278*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_UNSUPPORTED:
279*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_UNSUPPORTED;
280*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_INVALID_MAP:
281*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_INVALID_MAP;
282*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
283*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_MAX_FRAMES_EXCEEDED;
284*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_REPEATED_FRAME:
285*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_REPEATED_FRAME;
286*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_INVALID_ELF:
287*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_INVALID_ELF;
288*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_SYSTEM_CALL:
289*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_SYSTEM_CALL;
290*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_THREAD_TIMEOUT:
291*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_THREAD_TIMEOUT;
292*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_THREAD_DOES_NOT_EXIST:
293*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_THREAD_DOES_NOT_EXIST;
294*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_BAD_ARCH:
295*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_BAD_ARCH;
296*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_MAPS_PARSE:
297*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_MAPS_PARSE;
298*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_INVALID_PARAMETER:
299*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_INVALID_PARAMETER;
300*6dbdd20aSAndroid Build Coastguard Worker     case unwindstack::ERROR_PTRACE_CALL:
301*6dbdd20aSAndroid Build Coastguard Worker       return Profiling::UNWIND_ERROR_PTRACE_CALL;
302*6dbdd20aSAndroid Build Coastguard Worker   }
303*6dbdd20aSAndroid Build Coastguard Worker   return Profiling::UNWIND_ERROR_UNKNOWN;
304*6dbdd20aSAndroid Build Coastguard Worker }
305*6dbdd20aSAndroid Build Coastguard Worker 
306*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
307*6dbdd20aSAndroid Build Coastguard Worker 
308*6dbdd20aSAndroid Build Coastguard Worker // static
ShouldRejectDueToFilter(pid_t pid,const TargetFilter & filter,bool skip_cmdline,base::FlatSet<std::string> * additional_cmdlines,std::function<bool (std::string *)> read_proc_pid_cmdline)309*6dbdd20aSAndroid Build Coastguard Worker bool PerfProducer::ShouldRejectDueToFilter(
310*6dbdd20aSAndroid Build Coastguard Worker     pid_t pid,
311*6dbdd20aSAndroid Build Coastguard Worker     const TargetFilter& filter,
312*6dbdd20aSAndroid Build Coastguard Worker     bool skip_cmdline,
313*6dbdd20aSAndroid Build Coastguard Worker     base::FlatSet<std::string>* additional_cmdlines,
314*6dbdd20aSAndroid Build Coastguard Worker     std::function<bool(std::string*)> read_proc_pid_cmdline) {
315*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(additional_cmdlines);
316*6dbdd20aSAndroid Build Coastguard Worker 
317*6dbdd20aSAndroid Build Coastguard Worker   std::string cmdline;
318*6dbdd20aSAndroid Build Coastguard Worker   bool have_cmdline = false;
319*6dbdd20aSAndroid Build Coastguard Worker   if (!skip_cmdline)
320*6dbdd20aSAndroid Build Coastguard Worker     have_cmdline = read_proc_pid_cmdline(&cmdline);
321*6dbdd20aSAndroid Build Coastguard Worker 
322*6dbdd20aSAndroid Build Coastguard Worker   const char* binname = "";
323*6dbdd20aSAndroid Build Coastguard Worker   if (have_cmdline) {
324*6dbdd20aSAndroid Build Coastguard Worker     binname = glob_aware::FindBinaryName(cmdline.c_str(), cmdline.size());
325*6dbdd20aSAndroid Build Coastguard Worker   }
326*6dbdd20aSAndroid Build Coastguard Worker 
327*6dbdd20aSAndroid Build Coastguard Worker   auto has_matching_pattern = [](const std::vector<std::string>& patterns,
328*6dbdd20aSAndroid Build Coastguard Worker                                  const char* cmd, const char* name) {
329*6dbdd20aSAndroid Build Coastguard Worker     for (const std::string& pattern : patterns) {
330*6dbdd20aSAndroid Build Coastguard Worker       if (glob_aware::MatchGlobPattern(pattern.c_str(), cmd, name)) {
331*6dbdd20aSAndroid Build Coastguard Worker         return true;
332*6dbdd20aSAndroid Build Coastguard Worker       }
333*6dbdd20aSAndroid Build Coastguard Worker     }
334*6dbdd20aSAndroid Build Coastguard Worker     return false;
335*6dbdd20aSAndroid Build Coastguard Worker   };
336*6dbdd20aSAndroid Build Coastguard Worker 
337*6dbdd20aSAndroid Build Coastguard Worker   if (have_cmdline &&
338*6dbdd20aSAndroid Build Coastguard Worker       has_matching_pattern(filter.exclude_cmdlines, cmdline.c_str(), binname)) {
339*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("Explicitly rejecting samples for pid [%d] due to cmdline",
340*6dbdd20aSAndroid Build Coastguard Worker                   static_cast<int>(pid));
341*6dbdd20aSAndroid Build Coastguard Worker     return true;
342*6dbdd20aSAndroid Build Coastguard Worker   }
343*6dbdd20aSAndroid Build Coastguard Worker   if (filter.exclude_pids.count(pid)) {
344*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("Explicitly rejecting samples for pid [%d] due to pid",
345*6dbdd20aSAndroid Build Coastguard Worker                   static_cast<int>(pid));
346*6dbdd20aSAndroid Build Coastguard Worker     return true;
347*6dbdd20aSAndroid Build Coastguard Worker   }
348*6dbdd20aSAndroid Build Coastguard Worker 
349*6dbdd20aSAndroid Build Coastguard Worker   if (have_cmdline &&
350*6dbdd20aSAndroid Build Coastguard Worker       has_matching_pattern(filter.cmdlines, cmdline.c_str(), binname)) {
351*6dbdd20aSAndroid Build Coastguard Worker     return false;
352*6dbdd20aSAndroid Build Coastguard Worker   }
353*6dbdd20aSAndroid Build Coastguard Worker   if (filter.pids.count(pid)) {
354*6dbdd20aSAndroid Build Coastguard Worker     return false;
355*6dbdd20aSAndroid Build Coastguard Worker   }
356*6dbdd20aSAndroid Build Coastguard Worker 
357*6dbdd20aSAndroid Build Coastguard Worker   // Empty allow filter means keep everything that isn't explicitly excluded.
358*6dbdd20aSAndroid Build Coastguard Worker   if (filter.cmdlines.empty() && filter.pids.empty() &&
359*6dbdd20aSAndroid Build Coastguard Worker       !filter.additional_cmdline_count &&
360*6dbdd20aSAndroid Build Coastguard Worker       !filter.process_sharding.has_value()) {
361*6dbdd20aSAndroid Build Coastguard Worker     return false;
362*6dbdd20aSAndroid Build Coastguard Worker   }
363*6dbdd20aSAndroid Build Coastguard Worker 
364*6dbdd20aSAndroid Build Coastguard Worker   // Niche option: process sharding to amortise systemwide unwinding costs.
365*6dbdd20aSAndroid Build Coastguard Worker   // Selects a subset of all processes by using the low order bits of their pid.
366*6dbdd20aSAndroid Build Coastguard Worker   if (filter.process_sharding.has_value()) {
367*6dbdd20aSAndroid Build Coastguard Worker     uint32_t upid = static_cast<uint32_t>(pid);
368*6dbdd20aSAndroid Build Coastguard Worker     if (upid % filter.process_sharding->shard_count ==
369*6dbdd20aSAndroid Build Coastguard Worker         filter.process_sharding->chosen_shard) {
370*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Process sharding: keeping pid [%d]",
371*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<int>(pid));
372*6dbdd20aSAndroid Build Coastguard Worker       return false;
373*6dbdd20aSAndroid Build Coastguard Worker     } else {
374*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Process sharding: rejecting pid [%d]",
375*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<int>(pid));
376*6dbdd20aSAndroid Build Coastguard Worker       return true;
377*6dbdd20aSAndroid Build Coastguard Worker     }
378*6dbdd20aSAndroid Build Coastguard Worker   }
379*6dbdd20aSAndroid Build Coastguard Worker 
380*6dbdd20aSAndroid Build Coastguard Worker   // Niche option: additionally remember the first seen N process cmdlines, and
381*6dbdd20aSAndroid Build Coastguard Worker   // keep all processes with those names.
382*6dbdd20aSAndroid Build Coastguard Worker   if (have_cmdline) {
383*6dbdd20aSAndroid Build Coastguard Worker     if (additional_cmdlines->count(cmdline)) {
384*6dbdd20aSAndroid Build Coastguard Worker       return false;
385*6dbdd20aSAndroid Build Coastguard Worker     }
386*6dbdd20aSAndroid Build Coastguard Worker     if (additional_cmdlines->size() < filter.additional_cmdline_count) {
387*6dbdd20aSAndroid Build Coastguard Worker       additional_cmdlines->insert(cmdline);
388*6dbdd20aSAndroid Build Coastguard Worker       return false;
389*6dbdd20aSAndroid Build Coastguard Worker     }
390*6dbdd20aSAndroid Build Coastguard Worker   }
391*6dbdd20aSAndroid Build Coastguard Worker 
392*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DLOG("Rejecting samples for pid [%d]", static_cast<int>(pid));
393*6dbdd20aSAndroid Build Coastguard Worker   return true;
394*6dbdd20aSAndroid Build Coastguard Worker }
395*6dbdd20aSAndroid Build Coastguard Worker 
PerfProducer(ProcDescriptorGetter * proc_fd_getter,base::TaskRunner * task_runner)396*6dbdd20aSAndroid Build Coastguard Worker PerfProducer::PerfProducer(ProcDescriptorGetter* proc_fd_getter,
397*6dbdd20aSAndroid Build Coastguard Worker                            base::TaskRunner* task_runner)
398*6dbdd20aSAndroid Build Coastguard Worker     : task_runner_(task_runner),
399*6dbdd20aSAndroid Build Coastguard Worker       proc_fd_getter_(proc_fd_getter),
400*6dbdd20aSAndroid Build Coastguard Worker       unwinding_worker_(this),
401*6dbdd20aSAndroid Build Coastguard Worker       weak_factory_(this) {
402*6dbdd20aSAndroid Build Coastguard Worker   proc_fd_getter->SetDelegate(this);
403*6dbdd20aSAndroid Build Coastguard Worker }
404*6dbdd20aSAndroid Build Coastguard Worker 
SetupDataSource(DataSourceInstanceID,const DataSourceConfig &)405*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::SetupDataSource(DataSourceInstanceID,
406*6dbdd20aSAndroid Build Coastguard Worker                                    const DataSourceConfig&) {}
407*6dbdd20aSAndroid Build Coastguard Worker 
StartDataSource(DataSourceInstanceID ds_id,const DataSourceConfig & config)408*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::StartDataSource(DataSourceInstanceID ds_id,
409*6dbdd20aSAndroid Build Coastguard Worker                                    const DataSourceConfig& config) {
410*6dbdd20aSAndroid Build Coastguard Worker   uint64_t tracing_session_id = config.tracing_session_id();
411*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_LOG("StartDataSource(ds %zu, session %" PRIu64 ", name %s)",
412*6dbdd20aSAndroid Build Coastguard Worker                static_cast<size_t>(ds_id), tracing_session_id,
413*6dbdd20aSAndroid Build Coastguard Worker                config.name().c_str());
414*6dbdd20aSAndroid Build Coastguard Worker 
415*6dbdd20aSAndroid Build Coastguard Worker   if (config.name() == MetatraceWriter::kDataSourceName) {
416*6dbdd20aSAndroid Build Coastguard Worker     StartMetatraceSource(ds_id, static_cast<BufferID>(config.target_buffer()));
417*6dbdd20aSAndroid Build Coastguard Worker     return;
418*6dbdd20aSAndroid Build Coastguard Worker   }
419*6dbdd20aSAndroid Build Coastguard Worker 
420*6dbdd20aSAndroid Build Coastguard Worker   // linux.perf data source
421*6dbdd20aSAndroid Build Coastguard Worker   if (config.name() != kDataSourceName)
422*6dbdd20aSAndroid Build Coastguard Worker     return;
423*6dbdd20aSAndroid Build Coastguard Worker 
424*6dbdd20aSAndroid Build Coastguard Worker   // Tracepoint name -> id lookup in case the config asks for tracepoints:
425*6dbdd20aSAndroid Build Coastguard Worker   auto tracepoint_id_lookup = [this](const std::string& group,
426*6dbdd20aSAndroid Build Coastguard Worker                                      const std::string& name) {
427*6dbdd20aSAndroid Build Coastguard Worker     if (!tracefs_)  // lazy init or retry
428*6dbdd20aSAndroid Build Coastguard Worker       tracefs_ = FtraceProcfs::CreateGuessingMountPoint();
429*6dbdd20aSAndroid Build Coastguard Worker     if (!tracefs_)  // still didn't find an accessible tracefs
430*6dbdd20aSAndroid Build Coastguard Worker       return 0u;
431*6dbdd20aSAndroid Build Coastguard Worker     return tracefs_->ReadEventId(group, name);
432*6dbdd20aSAndroid Build Coastguard Worker   };
433*6dbdd20aSAndroid Build Coastguard Worker 
434*6dbdd20aSAndroid Build Coastguard Worker   protos::gen::PerfEventConfig event_config_pb;
435*6dbdd20aSAndroid Build Coastguard Worker   if (!event_config_pb.ParseFromString(config.perf_event_config_raw())) {
436*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_ELOG("PerfEventConfig could not be parsed.");
437*6dbdd20aSAndroid Build Coastguard Worker     return;
438*6dbdd20aSAndroid Build Coastguard Worker   }
439*6dbdd20aSAndroid Build Coastguard Worker 
440*6dbdd20aSAndroid Build Coastguard Worker   // Unlikely: handle a callstack sampling option that shares a random decision
441*6dbdd20aSAndroid Build Coastguard Worker   // between all data sources within a tracing session. Instead of introducing
442*6dbdd20aSAndroid Build Coastguard Worker   // session-scoped data, we replicate the decision in each per-DS EventConfig.
443*6dbdd20aSAndroid Build Coastguard Worker   std::optional<ProcessSharding> process_sharding;
444*6dbdd20aSAndroid Build Coastguard Worker   uint32_t shard_count =
445*6dbdd20aSAndroid Build Coastguard Worker       event_config_pb.callstack_sampling().scope().process_shard_count();
446*6dbdd20aSAndroid Build Coastguard Worker   if (shard_count > 0) {
447*6dbdd20aSAndroid Build Coastguard Worker     process_sharding =
448*6dbdd20aSAndroid Build Coastguard Worker         GetOrChooseCallstackProcessShard(tracing_session_id, shard_count);
449*6dbdd20aSAndroid Build Coastguard Worker   }
450*6dbdd20aSAndroid Build Coastguard Worker 
451*6dbdd20aSAndroid Build Coastguard Worker   std::optional<EventConfig> event_config = EventConfig::Create(
452*6dbdd20aSAndroid Build Coastguard Worker       event_config_pb, config, process_sharding, tracepoint_id_lookup);
453*6dbdd20aSAndroid Build Coastguard Worker   if (!event_config.has_value()) {
454*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_ELOG("PerfEventConfig rejected.");
455*6dbdd20aSAndroid Build Coastguard Worker     return;
456*6dbdd20aSAndroid Build Coastguard Worker   }
457*6dbdd20aSAndroid Build Coastguard Worker 
458*6dbdd20aSAndroid Build Coastguard Worker   std::vector<uint32_t> online_cpus = GetOnlineCpus();
459*6dbdd20aSAndroid Build Coastguard Worker   if (online_cpus.empty()) {
460*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_ELOG("No online CPUs found.");
461*6dbdd20aSAndroid Build Coastguard Worker     return;
462*6dbdd20aSAndroid Build Coastguard Worker   }
463*6dbdd20aSAndroid Build Coastguard Worker 
464*6dbdd20aSAndroid Build Coastguard Worker   std::vector<EventReader> per_cpu_readers;
465*6dbdd20aSAndroid Build Coastguard Worker   for (uint32_t cpu : online_cpus) {
466*6dbdd20aSAndroid Build Coastguard Worker     std::optional<EventReader> event_reader =
467*6dbdd20aSAndroid Build Coastguard Worker         EventReader::ConfigureEvents(cpu, event_config.value());
468*6dbdd20aSAndroid Build Coastguard Worker     if (!event_reader.has_value()) {
469*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_ELOG("Failed to set up perf events for cpu%" PRIu32
470*6dbdd20aSAndroid Build Coastguard Worker                     ", discarding data source.",
471*6dbdd20aSAndroid Build Coastguard Worker                     cpu);
472*6dbdd20aSAndroid Build Coastguard Worker       return;
473*6dbdd20aSAndroid Build Coastguard Worker     }
474*6dbdd20aSAndroid Build Coastguard Worker     per_cpu_readers.emplace_back(std::move(event_reader.value()));
475*6dbdd20aSAndroid Build Coastguard Worker   }
476*6dbdd20aSAndroid Build Coastguard Worker 
477*6dbdd20aSAndroid Build Coastguard Worker   auto buffer_id = static_cast<BufferID>(config.target_buffer());
478*6dbdd20aSAndroid Build Coastguard Worker   auto writer = endpoint_->CreateTraceWriter(buffer_id);
479*6dbdd20aSAndroid Build Coastguard Worker 
480*6dbdd20aSAndroid Build Coastguard Worker   // Construct the data source instance.
481*6dbdd20aSAndroid Build Coastguard Worker   std::map<DataSourceInstanceID, DataSourceState>::iterator ds_it;
482*6dbdd20aSAndroid Build Coastguard Worker   bool inserted;
483*6dbdd20aSAndroid Build Coastguard Worker   std::tie(ds_it, inserted) = data_sources_.emplace(
484*6dbdd20aSAndroid Build Coastguard Worker       std::piecewise_construct, std::forward_as_tuple(ds_id),
485*6dbdd20aSAndroid Build Coastguard Worker       std::forward_as_tuple(event_config.value(), tracing_session_id,
486*6dbdd20aSAndroid Build Coastguard Worker                             std::move(writer), std::move(per_cpu_readers)));
487*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(inserted);
488*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
489*6dbdd20aSAndroid Build Coastguard Worker 
490*6dbdd20aSAndroid Build Coastguard Worker   // Start the configured events.
491*6dbdd20aSAndroid Build Coastguard Worker   for (auto& per_cpu_reader : ds.per_cpu_readers) {
492*6dbdd20aSAndroid Build Coastguard Worker     per_cpu_reader.EnableEvents();
493*6dbdd20aSAndroid Build Coastguard Worker   }
494*6dbdd20aSAndroid Build Coastguard Worker 
495*6dbdd20aSAndroid Build Coastguard Worker   WritePerfEventDefaultsPacket(ds.event_config, ds.trace_writer.get());
496*6dbdd20aSAndroid Build Coastguard Worker 
497*6dbdd20aSAndroid Build Coastguard Worker   InterningOutputTracker::WriteFixedInterningsPacket(
498*6dbdd20aSAndroid Build Coastguard Worker       ds_it->second.trace_writer.get(),
499*6dbdd20aSAndroid Build Coastguard Worker       protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
500*6dbdd20aSAndroid Build Coastguard Worker 
501*6dbdd20aSAndroid Build Coastguard Worker   // Inform unwinder of the new data source instance, and optionally start a
502*6dbdd20aSAndroid Build Coastguard Worker   // periodic task to clear its cached state.
503*6dbdd20aSAndroid Build Coastguard Worker   auto unwind_mode = (ds.event_config.unwind_mode() ==
504*6dbdd20aSAndroid Build Coastguard Worker                       protos::gen::PerfEventConfig::UNWIND_FRAME_POINTER)
505*6dbdd20aSAndroid Build Coastguard Worker                          ? Unwinder::UnwindMode::kFramePointer
506*6dbdd20aSAndroid Build Coastguard Worker                          : Unwinder::UnwindMode::kUnwindStack;
507*6dbdd20aSAndroid Build Coastguard Worker   unwinding_worker_->PostStartDataSource(ds_id, ds.event_config.kernel_frames(),
508*6dbdd20aSAndroid Build Coastguard Worker                                          unwind_mode);
509*6dbdd20aSAndroid Build Coastguard Worker   if (ds.event_config.unwind_state_clear_period_ms()) {
510*6dbdd20aSAndroid Build Coastguard Worker     unwinding_worker_->PostClearCachedStatePeriodic(
511*6dbdd20aSAndroid Build Coastguard Worker         ds_id, ds.event_config.unwind_state_clear_period_ms());
512*6dbdd20aSAndroid Build Coastguard Worker   }
513*6dbdd20aSAndroid Build Coastguard Worker 
514*6dbdd20aSAndroid Build Coastguard Worker   // Kick off periodic read task.
515*6dbdd20aSAndroid Build Coastguard Worker   auto tick_period_ms = ds.event_config.read_tick_period_ms();
516*6dbdd20aSAndroid Build Coastguard Worker   auto weak_this = weak_factory_.GetWeakPtr();
517*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostDelayedTask(
518*6dbdd20aSAndroid Build Coastguard Worker       [weak_this, ds_id] {
519*6dbdd20aSAndroid Build Coastguard Worker         if (weak_this)
520*6dbdd20aSAndroid Build Coastguard Worker           weak_this->TickDataSourceRead(ds_id);
521*6dbdd20aSAndroid Build Coastguard Worker       },
522*6dbdd20aSAndroid Build Coastguard Worker       TimeToNextReadTickMs(ds_id, tick_period_ms));
523*6dbdd20aSAndroid Build Coastguard Worker 
524*6dbdd20aSAndroid Build Coastguard Worker   // Optionally kick off periodic memory footprint limit check.
525*6dbdd20aSAndroid Build Coastguard Worker   uint32_t max_daemon_memory_kb = event_config_pb.max_daemon_memory_kb();
526*6dbdd20aSAndroid Build Coastguard Worker   if (max_daemon_memory_kb > 0) {
527*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->PostDelayedTask(
528*6dbdd20aSAndroid Build Coastguard Worker         [weak_this, ds_id, max_daemon_memory_kb] {
529*6dbdd20aSAndroid Build Coastguard Worker           if (weak_this)
530*6dbdd20aSAndroid Build Coastguard Worker             weak_this->CheckMemoryFootprintPeriodic(ds_id,
531*6dbdd20aSAndroid Build Coastguard Worker                                                     max_daemon_memory_kb);
532*6dbdd20aSAndroid Build Coastguard Worker         },
533*6dbdd20aSAndroid Build Coastguard Worker         kMemoryLimitCheckPeriodMs);
534*6dbdd20aSAndroid Build Coastguard Worker   }
535*6dbdd20aSAndroid Build Coastguard Worker }
536*6dbdd20aSAndroid Build Coastguard Worker 
CheckMemoryFootprintPeriodic(DataSourceInstanceID ds_id,uint32_t max_daemon_memory_kb)537*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::CheckMemoryFootprintPeriodic(DataSourceInstanceID ds_id,
538*6dbdd20aSAndroid Build Coastguard Worker                                                 uint32_t max_daemon_memory_kb) {
539*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
540*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end())
541*6dbdd20aSAndroid Build Coastguard Worker     return;  // stop recurring
542*6dbdd20aSAndroid Build Coastguard Worker 
543*6dbdd20aSAndroid Build Coastguard Worker   GuardrailConfig gconfig = {};
544*6dbdd20aSAndroid Build Coastguard Worker   gconfig.memory_guardrail_kb = max_daemon_memory_kb;
545*6dbdd20aSAndroid Build Coastguard Worker 
546*6dbdd20aSAndroid Build Coastguard Worker   ProfilerMemoryGuardrails footprint_snapshot;
547*6dbdd20aSAndroid Build Coastguard Worker   if (footprint_snapshot.IsOverMemoryThreshold(gconfig)) {
548*6dbdd20aSAndroid Build Coastguard Worker     PurgeDataSource(ds_id);
549*6dbdd20aSAndroid Build Coastguard Worker     return;  // stop recurring
550*6dbdd20aSAndroid Build Coastguard Worker   }
551*6dbdd20aSAndroid Build Coastguard Worker 
552*6dbdd20aSAndroid Build Coastguard Worker   // repost
553*6dbdd20aSAndroid Build Coastguard Worker   auto weak_this = weak_factory_.GetWeakPtr();
554*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostDelayedTask(
555*6dbdd20aSAndroid Build Coastguard Worker       [weak_this, ds_id, max_daemon_memory_kb] {
556*6dbdd20aSAndroid Build Coastguard Worker         if (weak_this)
557*6dbdd20aSAndroid Build Coastguard Worker           weak_this->CheckMemoryFootprintPeriodic(ds_id, max_daemon_memory_kb);
558*6dbdd20aSAndroid Build Coastguard Worker       },
559*6dbdd20aSAndroid Build Coastguard Worker       kMemoryLimitCheckPeriodMs);
560*6dbdd20aSAndroid Build Coastguard Worker }
561*6dbdd20aSAndroid Build Coastguard Worker 
StopDataSource(DataSourceInstanceID ds_id)562*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::StopDataSource(DataSourceInstanceID ds_id) {
563*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_LOG("StopDataSource(%zu)", static_cast<size_t>(ds_id));
564*6dbdd20aSAndroid Build Coastguard Worker 
565*6dbdd20aSAndroid Build Coastguard Worker   // Metatrace: stop immediately (will miss the events from the
566*6dbdd20aSAndroid Build Coastguard Worker   // asynchronous shutdown of the primary data source).
567*6dbdd20aSAndroid Build Coastguard Worker   auto meta_it = metatrace_writers_.find(ds_id);
568*6dbdd20aSAndroid Build Coastguard Worker   if (meta_it != metatrace_writers_.end()) {
569*6dbdd20aSAndroid Build Coastguard Worker     meta_it->second.WriteAllAndFlushTraceWriter([] {});
570*6dbdd20aSAndroid Build Coastguard Worker     metatrace_writers_.erase(meta_it);
571*6dbdd20aSAndroid Build Coastguard Worker     return;
572*6dbdd20aSAndroid Build Coastguard Worker   }
573*6dbdd20aSAndroid Build Coastguard Worker 
574*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
575*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end()) {
576*6dbdd20aSAndroid Build Coastguard Worker     // Most likely, the source is missing due to an abrupt stop (via
577*6dbdd20aSAndroid Build Coastguard Worker     // |PurgeDataSource|). Tell the service that we've stopped the source now,
578*6dbdd20aSAndroid Build Coastguard Worker     // so that it doesn't wait for the ack until the timeout.
579*6dbdd20aSAndroid Build Coastguard Worker     endpoint_->NotifyDataSourceStopped(ds_id);
580*6dbdd20aSAndroid Build Coastguard Worker     return;
581*6dbdd20aSAndroid Build Coastguard Worker   }
582*6dbdd20aSAndroid Build Coastguard Worker 
583*6dbdd20aSAndroid Build Coastguard Worker   // Start shutting down the reading frontend, which will propagate the stop
584*6dbdd20aSAndroid Build Coastguard Worker   // further as the intermediate buffers are cleared.
585*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
586*6dbdd20aSAndroid Build Coastguard Worker   InitiateReaderStop(&ds);
587*6dbdd20aSAndroid Build Coastguard Worker }
588*6dbdd20aSAndroid Build Coastguard Worker 
589*6dbdd20aSAndroid Build Coastguard Worker // The perf data sources ignore flush requests, as flushing would be
590*6dbdd20aSAndroid Build Coastguard Worker // unnecessarily complicated given out-of-order unwinding and proc-fd timeouts.
591*6dbdd20aSAndroid Build Coastguard Worker // Instead of responding to explicit flushes, we can ensure that we're otherwise
592*6dbdd20aSAndroid Build Coastguard Worker // well-behaved (do not reorder packets too much), and let the service scrape
593*6dbdd20aSAndroid Build Coastguard Worker // the SMB.
Flush(FlushRequestID flush_id,const DataSourceInstanceID * data_source_ids,size_t num_data_sources,FlushFlags)594*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::Flush(FlushRequestID flush_id,
595*6dbdd20aSAndroid Build Coastguard Worker                          const DataSourceInstanceID* data_source_ids,
596*6dbdd20aSAndroid Build Coastguard Worker                          size_t num_data_sources,
597*6dbdd20aSAndroid Build Coastguard Worker                          FlushFlags) {
598*6dbdd20aSAndroid Build Coastguard Worker   // Flush metatracing if requested.
599*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < num_data_sources; i++) {
600*6dbdd20aSAndroid Build Coastguard Worker     auto ds_id = data_source_ids[i];
601*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("Flush(%zu)", static_cast<size_t>(ds_id));
602*6dbdd20aSAndroid Build Coastguard Worker 
603*6dbdd20aSAndroid Build Coastguard Worker     auto meta_it = metatrace_writers_.find(ds_id);
604*6dbdd20aSAndroid Build Coastguard Worker     if (meta_it != metatrace_writers_.end()) {
605*6dbdd20aSAndroid Build Coastguard Worker       meta_it->second.WriteAllAndFlushTraceWriter([] {});
606*6dbdd20aSAndroid Build Coastguard Worker     }
607*6dbdd20aSAndroid Build Coastguard Worker   }
608*6dbdd20aSAndroid Build Coastguard Worker 
609*6dbdd20aSAndroid Build Coastguard Worker   endpoint_->NotifyFlushComplete(flush_id);
610*6dbdd20aSAndroid Build Coastguard Worker }
611*6dbdd20aSAndroid Build Coastguard Worker 
ClearIncrementalState(const DataSourceInstanceID * data_source_ids,size_t num_data_sources)612*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::ClearIncrementalState(
613*6dbdd20aSAndroid Build Coastguard Worker     const DataSourceInstanceID* data_source_ids,
614*6dbdd20aSAndroid Build Coastguard Worker     size_t num_data_sources) {
615*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < num_data_sources; i++) {
616*6dbdd20aSAndroid Build Coastguard Worker     auto ds_id = data_source_ids[i];
617*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("ClearIncrementalState(%zu)", static_cast<size_t>(ds_id));
618*6dbdd20aSAndroid Build Coastguard Worker 
619*6dbdd20aSAndroid Build Coastguard Worker     if (metatrace_writers_.find(ds_id) != metatrace_writers_.end())
620*6dbdd20aSAndroid Build Coastguard Worker       continue;
621*6dbdd20aSAndroid Build Coastguard Worker 
622*6dbdd20aSAndroid Build Coastguard Worker     auto ds_it = data_sources_.find(ds_id);
623*6dbdd20aSAndroid Build Coastguard Worker     if (ds_it == data_sources_.end()) {
624*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("ClearIncrementalState(%zu): did not find matching entry",
625*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<size_t>(ds_id));
626*6dbdd20aSAndroid Build Coastguard Worker       continue;
627*6dbdd20aSAndroid Build Coastguard Worker     }
628*6dbdd20aSAndroid Build Coastguard Worker     DataSourceState& ds = ds_it->second;
629*6dbdd20aSAndroid Build Coastguard Worker 
630*6dbdd20aSAndroid Build Coastguard Worker     WritePerfEventDefaultsPacket(ds.event_config, ds.trace_writer.get());
631*6dbdd20aSAndroid Build Coastguard Worker 
632*6dbdd20aSAndroid Build Coastguard Worker     // Forget which incremental state we've emitted before.
633*6dbdd20aSAndroid Build Coastguard Worker     ds.interning_output.ClearHistory();
634*6dbdd20aSAndroid Build Coastguard Worker     InterningOutputTracker::WriteFixedInterningsPacket(
635*6dbdd20aSAndroid Build Coastguard Worker         ds.trace_writer.get(),
636*6dbdd20aSAndroid Build Coastguard Worker         protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
637*6dbdd20aSAndroid Build Coastguard Worker 
638*6dbdd20aSAndroid Build Coastguard Worker     // Drop the cross-datasource callstack interning trie. This is not
639*6dbdd20aSAndroid Build Coastguard Worker     // necessary for correctness (the preceding step is sufficient). However,
640*6dbdd20aSAndroid Build Coastguard Worker     // incremental clearing is likely to be used in ring buffer traces, where
641*6dbdd20aSAndroid Build Coastguard Worker     // it makes sense to reset the trie's size periodically, and this is a
642*6dbdd20aSAndroid Build Coastguard Worker     // reasonable point to do so. The trie keeps the monotonic interning IDs,
643*6dbdd20aSAndroid Build Coastguard Worker     // so there is no confusion for other concurrent data sources. We do not
644*6dbdd20aSAndroid Build Coastguard Worker     // bother with clearing concurrent sources' interning output trackers as
645*6dbdd20aSAndroid Build Coastguard Worker     // their footprint should be trivial.
646*6dbdd20aSAndroid Build Coastguard Worker     callstack_trie_.ClearTrie();
647*6dbdd20aSAndroid Build Coastguard Worker   }
648*6dbdd20aSAndroid Build Coastguard Worker }
649*6dbdd20aSAndroid Build Coastguard Worker 
TickDataSourceRead(DataSourceInstanceID ds_id)650*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::TickDataSourceRead(DataSourceInstanceID ds_id) {
651*6dbdd20aSAndroid Build Coastguard Worker   auto it = data_sources_.find(ds_id);
652*6dbdd20aSAndroid Build Coastguard Worker   if (it == data_sources_.end()) {
653*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("TickDataSourceRead(%zu): source gone",
654*6dbdd20aSAndroid Build Coastguard Worker                   static_cast<size_t>(ds_id));
655*6dbdd20aSAndroid Build Coastguard Worker     return;
656*6dbdd20aSAndroid Build Coastguard Worker   }
657*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = it->second;
658*6dbdd20aSAndroid Build Coastguard Worker 
659*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, PROFILER_READ_TICK);
660*6dbdd20aSAndroid Build Coastguard Worker 
661*6dbdd20aSAndroid Build Coastguard Worker   // Make a pass over all per-cpu readers.
662*6dbdd20aSAndroid Build Coastguard Worker   uint64_t max_samples = ds.event_config.samples_per_tick_limit();
663*6dbdd20aSAndroid Build Coastguard Worker   bool more_records_available = false;
664*6dbdd20aSAndroid Build Coastguard Worker   for (EventReader& reader : ds.per_cpu_readers) {
665*6dbdd20aSAndroid Build Coastguard Worker     if (ReadAndParsePerCpuBuffer(&reader, max_samples, ds_id, &ds)) {
666*6dbdd20aSAndroid Build Coastguard Worker       more_records_available = true;
667*6dbdd20aSAndroid Build Coastguard Worker     }
668*6dbdd20aSAndroid Build Coastguard Worker   }
669*6dbdd20aSAndroid Build Coastguard Worker 
670*6dbdd20aSAndroid Build Coastguard Worker   // Wake up the unwinder as we've (likely) pushed samples into its queue.
671*6dbdd20aSAndroid Build Coastguard Worker   unwinding_worker_->PostProcessQueue();
672*6dbdd20aSAndroid Build Coastguard Worker 
673*6dbdd20aSAndroid Build Coastguard Worker   if (PERFETTO_UNLIKELY(ds.status == DataSourceState::Status::kShuttingDown) &&
674*6dbdd20aSAndroid Build Coastguard Worker       !more_records_available) {
675*6dbdd20aSAndroid Build Coastguard Worker     unwinding_worker_->PostInitiateDataSourceStop(ds_id);
676*6dbdd20aSAndroid Build Coastguard Worker   } else {
677*6dbdd20aSAndroid Build Coastguard Worker     // otherwise, keep reading
678*6dbdd20aSAndroid Build Coastguard Worker     auto tick_period_ms = it->second.event_config.read_tick_period_ms();
679*6dbdd20aSAndroid Build Coastguard Worker     auto weak_this = weak_factory_.GetWeakPtr();
680*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->PostDelayedTask(
681*6dbdd20aSAndroid Build Coastguard Worker         [weak_this, ds_id] {
682*6dbdd20aSAndroid Build Coastguard Worker           if (weak_this)
683*6dbdd20aSAndroid Build Coastguard Worker             weak_this->TickDataSourceRead(ds_id);
684*6dbdd20aSAndroid Build Coastguard Worker         },
685*6dbdd20aSAndroid Build Coastguard Worker         TimeToNextReadTickMs(ds_id, tick_period_ms));
686*6dbdd20aSAndroid Build Coastguard Worker   }
687*6dbdd20aSAndroid Build Coastguard Worker }
688*6dbdd20aSAndroid Build Coastguard Worker 
ReadAndParsePerCpuBuffer(EventReader * reader,uint64_t max_samples,DataSourceInstanceID ds_id,DataSourceState * ds)689*6dbdd20aSAndroid Build Coastguard Worker bool PerfProducer::ReadAndParsePerCpuBuffer(EventReader* reader,
690*6dbdd20aSAndroid Build Coastguard Worker                                             uint64_t max_samples,
691*6dbdd20aSAndroid Build Coastguard Worker                                             DataSourceInstanceID ds_id,
692*6dbdd20aSAndroid Build Coastguard Worker                                             DataSourceState* ds) {
693*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_METATRACE_SCOPED(TAG_PRODUCER, PROFILER_READ_CPU);
694*6dbdd20aSAndroid Build Coastguard Worker 
695*6dbdd20aSAndroid Build Coastguard Worker   // If the kernel ring buffer dropped data, record it in the trace.
696*6dbdd20aSAndroid Build Coastguard Worker   size_t cpu = reader->cpu();
697*6dbdd20aSAndroid Build Coastguard Worker   auto records_lost_callback = [this, ds_id, cpu](uint64_t records_lost) {
698*6dbdd20aSAndroid Build Coastguard Worker     auto weak_this = weak_factory_.GetWeakPtr();
699*6dbdd20aSAndroid Build Coastguard Worker     task_runner_->PostTask([weak_this, ds_id, cpu, records_lost] {
700*6dbdd20aSAndroid Build Coastguard Worker       if (weak_this)
701*6dbdd20aSAndroid Build Coastguard Worker         weak_this->EmitRingBufferLoss(ds_id, cpu, records_lost);
702*6dbdd20aSAndroid Build Coastguard Worker     });
703*6dbdd20aSAndroid Build Coastguard Worker   };
704*6dbdd20aSAndroid Build Coastguard Worker 
705*6dbdd20aSAndroid Build Coastguard Worker   for (uint64_t i = 0; i < max_samples; i++) {
706*6dbdd20aSAndroid Build Coastguard Worker     std::optional<ParsedSample> sample =
707*6dbdd20aSAndroid Build Coastguard Worker         reader->ReadUntilSample(records_lost_callback);
708*6dbdd20aSAndroid Build Coastguard Worker     if (!sample) {
709*6dbdd20aSAndroid Build Coastguard Worker       return false;  // caught up to the writer
710*6dbdd20aSAndroid Build Coastguard Worker     }
711*6dbdd20aSAndroid Build Coastguard Worker 
712*6dbdd20aSAndroid Build Coastguard Worker     // Counter-only mode: skip the unwinding stage, serialise the sample
713*6dbdd20aSAndroid Build Coastguard Worker     // immediately.
714*6dbdd20aSAndroid Build Coastguard Worker     const EventConfig& event_config = ds->event_config;
715*6dbdd20aSAndroid Build Coastguard Worker     if (!event_config.sample_callstacks()) {
716*6dbdd20aSAndroid Build Coastguard Worker       CompletedSample output;
717*6dbdd20aSAndroid Build Coastguard Worker       output.common = sample->common;
718*6dbdd20aSAndroid Build Coastguard Worker       EmitSample(ds_id, std::move(output));
719*6dbdd20aSAndroid Build Coastguard Worker       continue;
720*6dbdd20aSAndroid Build Coastguard Worker     }
721*6dbdd20aSAndroid Build Coastguard Worker 
722*6dbdd20aSAndroid Build Coastguard Worker     // Sampling either or both of userspace and kernel callstacks.
723*6dbdd20aSAndroid Build Coastguard Worker     pid_t pid = sample->common.pid;
724*6dbdd20aSAndroid Build Coastguard Worker     auto& process_state = ds->process_states[pid];  // insert if new
725*6dbdd20aSAndroid Build Coastguard Worker 
726*6dbdd20aSAndroid Build Coastguard Worker     // Asynchronous proc-fd lookup timed out.
727*6dbdd20aSAndroid Build Coastguard Worker     if (process_state == ProcessTrackingStatus::kFdsTimedOut) {
728*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Skipping sample for pid [%d]: kFdsTimedOut",
729*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<int>(pid));
730*6dbdd20aSAndroid Build Coastguard Worker       EmitSkippedSample(ds_id, std::move(sample.value()),
731*6dbdd20aSAndroid Build Coastguard Worker                         SampleSkipReason::kReadStage);
732*6dbdd20aSAndroid Build Coastguard Worker       continue;
733*6dbdd20aSAndroid Build Coastguard Worker     }
734*6dbdd20aSAndroid Build Coastguard Worker 
735*6dbdd20aSAndroid Build Coastguard Worker     // Previously excluded, e.g. due to failing the target filter check.
736*6dbdd20aSAndroid Build Coastguard Worker     if (process_state == ProcessTrackingStatus::kRejected) {
737*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Skipping sample for pid [%d]: kRejected",
738*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<int>(pid));
739*6dbdd20aSAndroid Build Coastguard Worker       continue;
740*6dbdd20aSAndroid Build Coastguard Worker     }
741*6dbdd20aSAndroid Build Coastguard Worker 
742*6dbdd20aSAndroid Build Coastguard Worker     // Seeing pid for the first time. We need to consider whether the process
743*6dbdd20aSAndroid Build Coastguard Worker     // is a kernel thread, and which callstacks we're recording.
744*6dbdd20aSAndroid Build Coastguard Worker     //
745*6dbdd20aSAndroid Build Coastguard Worker     // {user} stacks -> user processes: signal for proc-fd lookup
746*6dbdd20aSAndroid Build Coastguard Worker     //               -> kthreads: reject
747*6dbdd20aSAndroid Build Coastguard Worker     //
748*6dbdd20aSAndroid Build Coastguard Worker     // {kernel} stacks -> user processes: accept without proc-fds
749*6dbdd20aSAndroid Build Coastguard Worker     //                 -> kthreads: accept without proc-fds
750*6dbdd20aSAndroid Build Coastguard Worker     //
751*6dbdd20aSAndroid Build Coastguard Worker     // {kernel+user} stacks -> user processes: signal for proc-fd lookup
752*6dbdd20aSAndroid Build Coastguard Worker     //                      -> kthreads: accept without proc-fds
753*6dbdd20aSAndroid Build Coastguard Worker     //
754*6dbdd20aSAndroid Build Coastguard Worker     if (process_state == ProcessTrackingStatus::kInitial) {
755*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("New pid: [%d]", static_cast<int>(pid));
756*6dbdd20aSAndroid Build Coastguard Worker 
757*6dbdd20aSAndroid Build Coastguard Worker       // Kernel threads (which have no userspace state) are never relevant if
758*6dbdd20aSAndroid Build Coastguard Worker       // we're not recording kernel callchains.
759*6dbdd20aSAndroid Build Coastguard Worker       bool is_kthread = !sample->regs;  // no userspace regs
760*6dbdd20aSAndroid Build Coastguard Worker       if (is_kthread && !event_config.kernel_frames()) {
761*6dbdd20aSAndroid Build Coastguard Worker         process_state = ProcessTrackingStatus::kRejected;
762*6dbdd20aSAndroid Build Coastguard Worker         continue;
763*6dbdd20aSAndroid Build Coastguard Worker       }
764*6dbdd20aSAndroid Build Coastguard Worker 
765*6dbdd20aSAndroid Build Coastguard Worker       // Check whether samples for this new process should be dropped due to
766*6dbdd20aSAndroid Build Coastguard Worker       // the target filtering. Kernel threads don't have a cmdline, but we
767*6dbdd20aSAndroid Build Coastguard Worker       // still check against pid inclusion/exclusion.
768*6dbdd20aSAndroid Build Coastguard Worker       if (ShouldRejectDueToFilter(
769*6dbdd20aSAndroid Build Coastguard Worker               pid, event_config.filter(), is_kthread, &ds->additional_cmdlines,
770*6dbdd20aSAndroid Build Coastguard Worker               [pid](std::string* cmdline) {
771*6dbdd20aSAndroid Build Coastguard Worker                 return glob_aware::ReadProcCmdlineForPID(pid, cmdline);
772*6dbdd20aSAndroid Build Coastguard Worker               })) {
773*6dbdd20aSAndroid Build Coastguard Worker         process_state = ProcessTrackingStatus::kRejected;
774*6dbdd20aSAndroid Build Coastguard Worker         continue;
775*6dbdd20aSAndroid Build Coastguard Worker       }
776*6dbdd20aSAndroid Build Coastguard Worker 
777*6dbdd20aSAndroid Build Coastguard Worker       // At this point, sampled process is known to be of interest.
778*6dbdd20aSAndroid Build Coastguard Worker       if (!is_kthread && event_config.user_frames()) {
779*6dbdd20aSAndroid Build Coastguard Worker         // Start resolving the proc-fds. Response is async.
780*6dbdd20aSAndroid Build Coastguard Worker         process_state = ProcessTrackingStatus::kFdsResolving;
781*6dbdd20aSAndroid Build Coastguard Worker         InitiateDescriptorLookup(ds_id, pid,
782*6dbdd20aSAndroid Build Coastguard Worker                                  event_config.remote_descriptor_timeout_ms());
783*6dbdd20aSAndroid Build Coastguard Worker         // note: fallthrough
784*6dbdd20aSAndroid Build Coastguard Worker       } else {
785*6dbdd20aSAndroid Build Coastguard Worker         // Either a kernel thread (no need to obtain proc-fds), or a userspace
786*6dbdd20aSAndroid Build Coastguard Worker         // process but we're not recording userspace callstacks.
787*6dbdd20aSAndroid Build Coastguard Worker         process_state = ProcessTrackingStatus::kAccepted;
788*6dbdd20aSAndroid Build Coastguard Worker         unwinding_worker_->PostRecordNoUserspaceProcess(ds_id, pid);
789*6dbdd20aSAndroid Build Coastguard Worker         // note: fallthrough
790*6dbdd20aSAndroid Build Coastguard Worker       }
791*6dbdd20aSAndroid Build Coastguard Worker     }
792*6dbdd20aSAndroid Build Coastguard Worker 
793*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(process_state == ProcessTrackingStatus::kAccepted ||
794*6dbdd20aSAndroid Build Coastguard Worker                    process_state == ProcessTrackingStatus::kFdsResolving);
795*6dbdd20aSAndroid Build Coastguard Worker 
796*6dbdd20aSAndroid Build Coastguard Worker     // If we're only interested in the kernel callchains, then userspace
797*6dbdd20aSAndroid Build Coastguard Worker     // process samples are relevant only if they were sampled during kernel
798*6dbdd20aSAndroid Build Coastguard Worker     // context.
799*6dbdd20aSAndroid Build Coastguard Worker     if (!event_config.user_frames() &&
800*6dbdd20aSAndroid Build Coastguard Worker         sample->common.cpu_mode == PERF_RECORD_MISC_USER) {
801*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Skipping usermode sample for kernel-only config");
802*6dbdd20aSAndroid Build Coastguard Worker       continue;
803*6dbdd20aSAndroid Build Coastguard Worker     }
804*6dbdd20aSAndroid Build Coastguard Worker 
805*6dbdd20aSAndroid Build Coastguard Worker     // Optionally: drop sample if above a given threshold of sampled stacks
806*6dbdd20aSAndroid Build Coastguard Worker     // that are waiting in the unwinding queue.
807*6dbdd20aSAndroid Build Coastguard Worker     uint64_t max_footprint_bytes = event_config.max_enqueued_footprint_bytes();
808*6dbdd20aSAndroid Build Coastguard Worker     uint64_t sample_stack_size = sample->stack.size();
809*6dbdd20aSAndroid Build Coastguard Worker     if (max_footprint_bytes) {
810*6dbdd20aSAndroid Build Coastguard Worker       uint64_t footprint_bytes = unwinding_worker_->GetEnqueuedFootprint();
811*6dbdd20aSAndroid Build Coastguard Worker       if (footprint_bytes + sample_stack_size >= max_footprint_bytes) {
812*6dbdd20aSAndroid Build Coastguard Worker         PERFETTO_DLOG("Skipping sample enqueueing due to footprint limit.");
813*6dbdd20aSAndroid Build Coastguard Worker         EmitSkippedSample(ds_id, std::move(sample.value()),
814*6dbdd20aSAndroid Build Coastguard Worker                           SampleSkipReason::kUnwindEnqueue);
815*6dbdd20aSAndroid Build Coastguard Worker         continue;
816*6dbdd20aSAndroid Build Coastguard Worker       }
817*6dbdd20aSAndroid Build Coastguard Worker     }
818*6dbdd20aSAndroid Build Coastguard Worker 
819*6dbdd20aSAndroid Build Coastguard Worker     // Push the sample into the unwinding queue if there is room.
820*6dbdd20aSAndroid Build Coastguard Worker     auto& queue = unwinding_worker_->unwind_queue();
821*6dbdd20aSAndroid Build Coastguard Worker     WriteView write_view = queue.BeginWrite();
822*6dbdd20aSAndroid Build Coastguard Worker     if (write_view.valid) {
823*6dbdd20aSAndroid Build Coastguard Worker       queue.at(write_view.write_pos) =
824*6dbdd20aSAndroid Build Coastguard Worker           UnwindEntry{ds_id, std::move(sample.value())};
825*6dbdd20aSAndroid Build Coastguard Worker       queue.CommitWrite();
826*6dbdd20aSAndroid Build Coastguard Worker       unwinding_worker_->IncrementEnqueuedFootprint(sample_stack_size);
827*6dbdd20aSAndroid Build Coastguard Worker     } else {
828*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Unwinder queue full, skipping sample");
829*6dbdd20aSAndroid Build Coastguard Worker       EmitSkippedSample(ds_id, std::move(sample.value()),
830*6dbdd20aSAndroid Build Coastguard Worker                         SampleSkipReason::kUnwindEnqueue);
831*6dbdd20aSAndroid Build Coastguard Worker     }
832*6dbdd20aSAndroid Build Coastguard Worker   }  // for (i < max_samples)
833*6dbdd20aSAndroid Build Coastguard Worker 
834*6dbdd20aSAndroid Build Coastguard Worker   // Most likely more events in the kernel buffer. Though we might be exactly on
835*6dbdd20aSAndroid Build Coastguard Worker   // the boundary due to |max_samples|.
836*6dbdd20aSAndroid Build Coastguard Worker   return true;
837*6dbdd20aSAndroid Build Coastguard Worker }
838*6dbdd20aSAndroid Build Coastguard Worker 
839*6dbdd20aSAndroid Build Coastguard Worker // Note: first-fit makes descriptor request fulfillment not true FIFO. But the
840*6dbdd20aSAndroid Build Coastguard Worker // edge-cases where it matters are very unlikely.
OnProcDescriptors(pid_t pid,uid_t uid,base::ScopedFile maps_fd,base::ScopedFile mem_fd)841*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::OnProcDescriptors(pid_t pid,
842*6dbdd20aSAndroid Build Coastguard Worker                                      uid_t uid,
843*6dbdd20aSAndroid Build Coastguard Worker                                      base::ScopedFile maps_fd,
844*6dbdd20aSAndroid Build Coastguard Worker                                      base::ScopedFile mem_fd) {
845*6dbdd20aSAndroid Build Coastguard Worker   // Find first-fit data source that requested descriptors for the process.
846*6dbdd20aSAndroid Build Coastguard Worker   for (auto& it : data_sources_) {
847*6dbdd20aSAndroid Build Coastguard Worker     DataSourceState& ds = it.second;
848*6dbdd20aSAndroid Build Coastguard Worker     auto proc_status_it = ds.process_states.find(pid);
849*6dbdd20aSAndroid Build Coastguard Worker     if (proc_status_it == ds.process_states.end())
850*6dbdd20aSAndroid Build Coastguard Worker       continue;
851*6dbdd20aSAndroid Build Coastguard Worker 
852*6dbdd20aSAndroid Build Coastguard Worker     // TODO(rsavitski): consider checking ProcessTrackingStatus before
853*6dbdd20aSAndroid Build Coastguard Worker     // CanProfile.
854*6dbdd20aSAndroid Build Coastguard Worker     if (!CanProfile(ds.event_config.raw_ds_config(), uid,
855*6dbdd20aSAndroid Build Coastguard Worker                     ds.event_config.target_installed_by())) {
856*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Not profileable: pid [%d], uid [%d] for DS [%zu]",
857*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<int>(pid), static_cast<int>(uid),
858*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<size_t>(it.first));
859*6dbdd20aSAndroid Build Coastguard Worker       continue;
860*6dbdd20aSAndroid Build Coastguard Worker     }
861*6dbdd20aSAndroid Build Coastguard Worker 
862*6dbdd20aSAndroid Build Coastguard Worker     // Match against either resolving, or expired state. In the latter
863*6dbdd20aSAndroid Build Coastguard Worker     // case, it means that the async response was slow enough that we've marked
864*6dbdd20aSAndroid Build Coastguard Worker     // the lookup as expired (but can now recover for future samples).
865*6dbdd20aSAndroid Build Coastguard Worker     auto proc_status = proc_status_it->second;
866*6dbdd20aSAndroid Build Coastguard Worker     if (proc_status == ProcessTrackingStatus::kFdsResolving ||
867*6dbdd20aSAndroid Build Coastguard Worker         proc_status == ProcessTrackingStatus::kFdsTimedOut) {
868*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DLOG("Handing off proc-fds for pid [%d] to DS [%zu]",
869*6dbdd20aSAndroid Build Coastguard Worker                     static_cast<int>(pid), static_cast<size_t>(it.first));
870*6dbdd20aSAndroid Build Coastguard Worker 
871*6dbdd20aSAndroid Build Coastguard Worker       proc_status_it->second = ProcessTrackingStatus::kAccepted;
872*6dbdd20aSAndroid Build Coastguard Worker       unwinding_worker_->PostAdoptProcDescriptors(
873*6dbdd20aSAndroid Build Coastguard Worker           it.first, pid, std::move(maps_fd), std::move(mem_fd));
874*6dbdd20aSAndroid Build Coastguard Worker       return;  // done
875*6dbdd20aSAndroid Build Coastguard Worker     }
876*6dbdd20aSAndroid Build Coastguard Worker   }
877*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DLOG(
878*6dbdd20aSAndroid Build Coastguard Worker       "Discarding proc-fds for pid [%d] as found no outstanding requests.",
879*6dbdd20aSAndroid Build Coastguard Worker       static_cast<int>(pid));
880*6dbdd20aSAndroid Build Coastguard Worker }
881*6dbdd20aSAndroid Build Coastguard Worker 
InitiateDescriptorLookup(DataSourceInstanceID ds_id,pid_t pid,uint32_t timeout_ms)882*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::InitiateDescriptorLookup(DataSourceInstanceID ds_id,
883*6dbdd20aSAndroid Build Coastguard Worker                                             pid_t pid,
884*6dbdd20aSAndroid Build Coastguard Worker                                             uint32_t timeout_ms) {
885*6dbdd20aSAndroid Build Coastguard Worker   if (!proc_fd_getter_->RequiresDelayedRequest()) {
886*6dbdd20aSAndroid Build Coastguard Worker     StartDescriptorLookup(ds_id, pid, timeout_ms);
887*6dbdd20aSAndroid Build Coastguard Worker     return;
888*6dbdd20aSAndroid Build Coastguard Worker   }
889*6dbdd20aSAndroid Build Coastguard Worker 
890*6dbdd20aSAndroid Build Coastguard Worker   // Delay lookups on Android. See comment on |kProcDescriptorsAndroidDelayMs|.
891*6dbdd20aSAndroid Build Coastguard Worker   auto weak_this = weak_factory_.GetWeakPtr();
892*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostDelayedTask(
893*6dbdd20aSAndroid Build Coastguard Worker       [weak_this, ds_id, pid, timeout_ms] {
894*6dbdd20aSAndroid Build Coastguard Worker         if (weak_this)
895*6dbdd20aSAndroid Build Coastguard Worker           weak_this->StartDescriptorLookup(ds_id, pid, timeout_ms);
896*6dbdd20aSAndroid Build Coastguard Worker       },
897*6dbdd20aSAndroid Build Coastguard Worker       kProcDescriptorsAndroidDelayMs);
898*6dbdd20aSAndroid Build Coastguard Worker }
899*6dbdd20aSAndroid Build Coastguard Worker 
StartDescriptorLookup(DataSourceInstanceID ds_id,pid_t pid,uint32_t timeout_ms)900*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::StartDescriptorLookup(DataSourceInstanceID ds_id,
901*6dbdd20aSAndroid Build Coastguard Worker                                          pid_t pid,
902*6dbdd20aSAndroid Build Coastguard Worker                                          uint32_t timeout_ms) {
903*6dbdd20aSAndroid Build Coastguard Worker   proc_fd_getter_->GetDescriptorsForPid(pid);
904*6dbdd20aSAndroid Build Coastguard Worker 
905*6dbdd20aSAndroid Build Coastguard Worker   auto weak_this = weak_factory_.GetWeakPtr();
906*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostDelayedTask(
907*6dbdd20aSAndroid Build Coastguard Worker       [weak_this, ds_id, pid] {
908*6dbdd20aSAndroid Build Coastguard Worker         if (weak_this)
909*6dbdd20aSAndroid Build Coastguard Worker           weak_this->EvaluateDescriptorLookupTimeout(ds_id, pid);
910*6dbdd20aSAndroid Build Coastguard Worker       },
911*6dbdd20aSAndroid Build Coastguard Worker       timeout_ms);
912*6dbdd20aSAndroid Build Coastguard Worker }
913*6dbdd20aSAndroid Build Coastguard Worker 
EvaluateDescriptorLookupTimeout(DataSourceInstanceID ds_id,pid_t pid)914*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::EvaluateDescriptorLookupTimeout(DataSourceInstanceID ds_id,
915*6dbdd20aSAndroid Build Coastguard Worker                                                    pid_t pid) {
916*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
917*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end())
918*6dbdd20aSAndroid Build Coastguard Worker     return;
919*6dbdd20aSAndroid Build Coastguard Worker 
920*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
921*6dbdd20aSAndroid Build Coastguard Worker   auto proc_status_it = ds.process_states.find(pid);
922*6dbdd20aSAndroid Build Coastguard Worker   if (proc_status_it == ds.process_states.end())
923*6dbdd20aSAndroid Build Coastguard Worker     return;
924*6dbdd20aSAndroid Build Coastguard Worker 
925*6dbdd20aSAndroid Build Coastguard Worker   // If the request is still outstanding, mark the process as expired (causing
926*6dbdd20aSAndroid Build Coastguard Worker   // outstanding and future samples to be discarded).
927*6dbdd20aSAndroid Build Coastguard Worker   auto proc_status = proc_status_it->second;
928*6dbdd20aSAndroid Build Coastguard Worker   if (proc_status == ProcessTrackingStatus::kFdsResolving) {
929*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("Descriptor lookup timeout of pid [%d] for DS [%zu]",
930*6dbdd20aSAndroid Build Coastguard Worker                   static_cast<int>(pid), static_cast<size_t>(ds_it->first));
931*6dbdd20aSAndroid Build Coastguard Worker 
932*6dbdd20aSAndroid Build Coastguard Worker     proc_status_it->second = ProcessTrackingStatus::kFdsTimedOut;
933*6dbdd20aSAndroid Build Coastguard Worker     // Also inform the unwinder of the state change (so that it can discard any
934*6dbdd20aSAndroid Build Coastguard Worker     // of the already-enqueued samples).
935*6dbdd20aSAndroid Build Coastguard Worker     unwinding_worker_->PostRecordTimedOutProcDescriptors(ds_id, pid);
936*6dbdd20aSAndroid Build Coastguard Worker   }
937*6dbdd20aSAndroid Build Coastguard Worker }
938*6dbdd20aSAndroid Build Coastguard Worker 
PostEmitSample(DataSourceInstanceID ds_id,CompletedSample sample)939*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::PostEmitSample(DataSourceInstanceID ds_id,
940*6dbdd20aSAndroid Build Coastguard Worker                                   CompletedSample sample) {
941*6dbdd20aSAndroid Build Coastguard Worker   // hack: c++11 lambdas can't be moved into, so stash the sample on the heap.
942*6dbdd20aSAndroid Build Coastguard Worker   CompletedSample* raw_sample = new CompletedSample(std::move(sample));
943*6dbdd20aSAndroid Build Coastguard Worker   auto weak_this = weak_factory_.GetWeakPtr();
944*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostTask([weak_this, ds_id, raw_sample] {
945*6dbdd20aSAndroid Build Coastguard Worker     if (weak_this)
946*6dbdd20aSAndroid Build Coastguard Worker       weak_this->EmitSample(ds_id, std::move(*raw_sample));
947*6dbdd20aSAndroid Build Coastguard Worker     delete raw_sample;
948*6dbdd20aSAndroid Build Coastguard Worker   });
949*6dbdd20aSAndroid Build Coastguard Worker }
950*6dbdd20aSAndroid Build Coastguard Worker 
EmitSample(DataSourceInstanceID ds_id,CompletedSample sample)951*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::EmitSample(DataSourceInstanceID ds_id,
952*6dbdd20aSAndroid Build Coastguard Worker                               CompletedSample sample) {
953*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
954*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end()) {
955*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("EmitSample(ds: %zu): source gone",
956*6dbdd20aSAndroid Build Coastguard Worker                   static_cast<size_t>(ds_id));
957*6dbdd20aSAndroid Build Coastguard Worker     return;
958*6dbdd20aSAndroid Build Coastguard Worker   }
959*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
960*6dbdd20aSAndroid Build Coastguard Worker 
961*6dbdd20aSAndroid Build Coastguard Worker   // intern callsite
962*6dbdd20aSAndroid Build Coastguard Worker   GlobalCallstackTrie::Node* callstack_root =
963*6dbdd20aSAndroid Build Coastguard Worker       callstack_trie_.CreateCallsite(sample.frames, sample.build_ids);
964*6dbdd20aSAndroid Build Coastguard Worker   uint64_t callstack_iid = callstack_root->id();
965*6dbdd20aSAndroid Build Coastguard Worker 
966*6dbdd20aSAndroid Build Coastguard Worker   // start packet, timestamp domain defaults to monotonic_raw
967*6dbdd20aSAndroid Build Coastguard Worker   auto packet = StartTracePacket(ds.trace_writer.get());
968*6dbdd20aSAndroid Build Coastguard Worker   packet->set_timestamp(sample.common.timestamp);
969*6dbdd20aSAndroid Build Coastguard Worker 
970*6dbdd20aSAndroid Build Coastguard Worker   // write new interning data (if any)
971*6dbdd20aSAndroid Build Coastguard Worker   protos::pbzero::InternedData* interned_out = packet->set_interned_data();
972*6dbdd20aSAndroid Build Coastguard Worker   ds.interning_output.WriteCallstack(callstack_root, &callstack_trie_,
973*6dbdd20aSAndroid Build Coastguard Worker                                      interned_out);
974*6dbdd20aSAndroid Build Coastguard Worker 
975*6dbdd20aSAndroid Build Coastguard Worker   // write the sample itself
976*6dbdd20aSAndroid Build Coastguard Worker   auto* perf_sample = packet->set_perf_sample();
977*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_cpu(sample.common.cpu);
978*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_pid(static_cast<uint32_t>(sample.common.pid));
979*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_tid(static_cast<uint32_t>(sample.common.tid));
980*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_cpu_mode(ToCpuModeEnum(sample.common.cpu_mode));
981*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_timebase_count(sample.common.timebase_count);
982*6dbdd20aSAndroid Build Coastguard Worker 
983*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < sample.common.follower_counts.size(); ++i) {
984*6dbdd20aSAndroid Build Coastguard Worker     perf_sample->add_follower_counts(sample.common.follower_counts[i]);
985*6dbdd20aSAndroid Build Coastguard Worker   }
986*6dbdd20aSAndroid Build Coastguard Worker 
987*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_callstack_iid(callstack_iid);
988*6dbdd20aSAndroid Build Coastguard Worker   if (sample.unwind_error != unwindstack::ERROR_NONE) {
989*6dbdd20aSAndroid Build Coastguard Worker     perf_sample->set_unwind_error(ToProtoEnum(sample.unwind_error));
990*6dbdd20aSAndroid Build Coastguard Worker   }
991*6dbdd20aSAndroid Build Coastguard Worker }
992*6dbdd20aSAndroid Build Coastguard Worker 
EmitRingBufferLoss(DataSourceInstanceID ds_id,size_t cpu,uint64_t records_lost)993*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::EmitRingBufferLoss(DataSourceInstanceID ds_id,
994*6dbdd20aSAndroid Build Coastguard Worker                                       size_t cpu,
995*6dbdd20aSAndroid Build Coastguard Worker                                       uint64_t records_lost) {
996*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
997*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end())
998*6dbdd20aSAndroid Build Coastguard Worker     return;
999*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
1000*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DLOG("DataSource(%zu): cpu%zu lost [%" PRIu64 "] records",
1001*6dbdd20aSAndroid Build Coastguard Worker                 static_cast<size_t>(ds_id), cpu, records_lost);
1002*6dbdd20aSAndroid Build Coastguard Worker 
1003*6dbdd20aSAndroid Build Coastguard Worker   // The data loss record relates to a single ring buffer, and indicates loss
1004*6dbdd20aSAndroid Build Coastguard Worker   // since the last successfully-written record in that buffer. Therefore the
1005*6dbdd20aSAndroid Build Coastguard Worker   // data loss record itself has no timestamp.
1006*6dbdd20aSAndroid Build Coastguard Worker   // We timestamp the packet with the boot clock for packet ordering purposes,
1007*6dbdd20aSAndroid Build Coastguard Worker   // but it no longer has a (precise) interpretation relative to the sample
1008*6dbdd20aSAndroid Build Coastguard Worker   // stream from that per-cpu buffer. See the proto comments for more details.
1009*6dbdd20aSAndroid Build Coastguard Worker   auto packet = StartTracePacket(ds.trace_writer.get());
1010*6dbdd20aSAndroid Build Coastguard Worker   packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
1011*6dbdd20aSAndroid Build Coastguard Worker   packet->set_timestamp_clock_id(
1012*6dbdd20aSAndroid Build Coastguard Worker       protos::pbzero::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
1013*6dbdd20aSAndroid Build Coastguard Worker 
1014*6dbdd20aSAndroid Build Coastguard Worker   auto* perf_sample = packet->set_perf_sample();
1015*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_cpu(static_cast<uint32_t>(cpu));
1016*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_kernel_records_lost(records_lost);
1017*6dbdd20aSAndroid Build Coastguard Worker }
1018*6dbdd20aSAndroid Build Coastguard Worker 
PostEmitUnwinderSkippedSample(DataSourceInstanceID ds_id,ParsedSample sample)1019*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::PostEmitUnwinderSkippedSample(DataSourceInstanceID ds_id,
1020*6dbdd20aSAndroid Build Coastguard Worker                                                  ParsedSample sample) {
1021*6dbdd20aSAndroid Build Coastguard Worker   PostEmitSkippedSample(ds_id, std::move(sample),
1022*6dbdd20aSAndroid Build Coastguard Worker                         SampleSkipReason::kUnwindStage);
1023*6dbdd20aSAndroid Build Coastguard Worker }
1024*6dbdd20aSAndroid Build Coastguard Worker 
PostEmitSkippedSample(DataSourceInstanceID ds_id,ParsedSample sample,SampleSkipReason reason)1025*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::PostEmitSkippedSample(DataSourceInstanceID ds_id,
1026*6dbdd20aSAndroid Build Coastguard Worker                                          ParsedSample sample,
1027*6dbdd20aSAndroid Build Coastguard Worker                                          SampleSkipReason reason) {
1028*6dbdd20aSAndroid Build Coastguard Worker   // hack: c++11 lambdas can't be moved into, so stash the sample on the heap.
1029*6dbdd20aSAndroid Build Coastguard Worker   ParsedSample* raw_sample = new ParsedSample(std::move(sample));
1030*6dbdd20aSAndroid Build Coastguard Worker   auto weak_this = weak_factory_.GetWeakPtr();
1031*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostTask([weak_this, ds_id, raw_sample, reason] {
1032*6dbdd20aSAndroid Build Coastguard Worker     if (weak_this)
1033*6dbdd20aSAndroid Build Coastguard Worker       weak_this->EmitSkippedSample(ds_id, std::move(*raw_sample), reason);
1034*6dbdd20aSAndroid Build Coastguard Worker     delete raw_sample;
1035*6dbdd20aSAndroid Build Coastguard Worker   });
1036*6dbdd20aSAndroid Build Coastguard Worker }
1037*6dbdd20aSAndroid Build Coastguard Worker 
EmitSkippedSample(DataSourceInstanceID ds_id,ParsedSample sample,SampleSkipReason reason)1038*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::EmitSkippedSample(DataSourceInstanceID ds_id,
1039*6dbdd20aSAndroid Build Coastguard Worker                                      ParsedSample sample,
1040*6dbdd20aSAndroid Build Coastguard Worker                                      SampleSkipReason reason) {
1041*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
1042*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end())
1043*6dbdd20aSAndroid Build Coastguard Worker     return;
1044*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
1045*6dbdd20aSAndroid Build Coastguard Worker 
1046*6dbdd20aSAndroid Build Coastguard Worker   // Note: timestamp defaults to the monotonic_raw domain.
1047*6dbdd20aSAndroid Build Coastguard Worker   auto packet = StartTracePacket(ds.trace_writer.get());
1048*6dbdd20aSAndroid Build Coastguard Worker   packet->set_timestamp(sample.common.timestamp);
1049*6dbdd20aSAndroid Build Coastguard Worker   auto* perf_sample = packet->set_perf_sample();
1050*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_cpu(sample.common.cpu);
1051*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_pid(static_cast<uint32_t>(sample.common.pid));
1052*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_tid(static_cast<uint32_t>(sample.common.tid));
1053*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_cpu_mode(ToCpuModeEnum(sample.common.cpu_mode));
1054*6dbdd20aSAndroid Build Coastguard Worker   perf_sample->set_timebase_count(sample.common.timebase_count);
1055*6dbdd20aSAndroid Build Coastguard Worker 
1056*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < sample.common.follower_counts.size(); ++i) {
1057*6dbdd20aSAndroid Build Coastguard Worker     perf_sample->add_follower_counts(sample.common.follower_counts[i]);
1058*6dbdd20aSAndroid Build Coastguard Worker   }
1059*6dbdd20aSAndroid Build Coastguard Worker 
1060*6dbdd20aSAndroid Build Coastguard Worker   using PerfSample = protos::pbzero::PerfSample;
1061*6dbdd20aSAndroid Build Coastguard Worker   switch (reason) {
1062*6dbdd20aSAndroid Build Coastguard Worker     case SampleSkipReason::kReadStage:
1063*6dbdd20aSAndroid Build Coastguard Worker       perf_sample->set_sample_skipped_reason(
1064*6dbdd20aSAndroid Build Coastguard Worker           PerfSample::PROFILER_SKIP_READ_STAGE);
1065*6dbdd20aSAndroid Build Coastguard Worker       break;
1066*6dbdd20aSAndroid Build Coastguard Worker     case SampleSkipReason::kUnwindEnqueue:
1067*6dbdd20aSAndroid Build Coastguard Worker       perf_sample->set_sample_skipped_reason(
1068*6dbdd20aSAndroid Build Coastguard Worker           PerfSample::PROFILER_SKIP_UNWIND_ENQUEUE);
1069*6dbdd20aSAndroid Build Coastguard Worker       break;
1070*6dbdd20aSAndroid Build Coastguard Worker     case SampleSkipReason::kUnwindStage:
1071*6dbdd20aSAndroid Build Coastguard Worker       perf_sample->set_sample_skipped_reason(
1072*6dbdd20aSAndroid Build Coastguard Worker           PerfSample::PROFILER_SKIP_UNWIND_STAGE);
1073*6dbdd20aSAndroid Build Coastguard Worker       break;
1074*6dbdd20aSAndroid Build Coastguard Worker   }
1075*6dbdd20aSAndroid Build Coastguard Worker }
1076*6dbdd20aSAndroid Build Coastguard Worker 
InitiateReaderStop(DataSourceState * ds)1077*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::InitiateReaderStop(DataSourceState* ds) {
1078*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DLOG("InitiateReaderStop");
1079*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ds->status != DataSourceState::Status::kShuttingDown);
1080*6dbdd20aSAndroid Build Coastguard Worker 
1081*6dbdd20aSAndroid Build Coastguard Worker   ds->status = DataSourceState::Status::kShuttingDown;
1082*6dbdd20aSAndroid Build Coastguard Worker   for (auto& event_reader : ds->per_cpu_readers) {
1083*6dbdd20aSAndroid Build Coastguard Worker     event_reader.DisableEvents();
1084*6dbdd20aSAndroid Build Coastguard Worker   }
1085*6dbdd20aSAndroid Build Coastguard Worker }
1086*6dbdd20aSAndroid Build Coastguard Worker 
PostFinishDataSourceStop(DataSourceInstanceID ds_id)1087*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::PostFinishDataSourceStop(DataSourceInstanceID ds_id) {
1088*6dbdd20aSAndroid Build Coastguard Worker   auto weak_producer = weak_factory_.GetWeakPtr();
1089*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostTask([weak_producer, ds_id] {
1090*6dbdd20aSAndroid Build Coastguard Worker     if (weak_producer)
1091*6dbdd20aSAndroid Build Coastguard Worker       weak_producer->FinishDataSourceStop(ds_id);
1092*6dbdd20aSAndroid Build Coastguard Worker   });
1093*6dbdd20aSAndroid Build Coastguard Worker }
1094*6dbdd20aSAndroid Build Coastguard Worker 
FinishDataSourceStop(DataSourceInstanceID ds_id)1095*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::FinishDataSourceStop(DataSourceInstanceID ds_id) {
1096*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_LOG("FinishDataSourceStop(%zu)", static_cast<size_t>(ds_id));
1097*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
1098*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end()) {
1099*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("FinishDataSourceStop(%zu): source gone",
1100*6dbdd20aSAndroid Build Coastguard Worker                   static_cast<size_t>(ds_id));
1101*6dbdd20aSAndroid Build Coastguard Worker     return;
1102*6dbdd20aSAndroid Build Coastguard Worker   }
1103*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
1104*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ds.status == DataSourceState::Status::kShuttingDown);
1105*6dbdd20aSAndroid Build Coastguard Worker 
1106*6dbdd20aSAndroid Build Coastguard Worker   ds.trace_writer->Flush();
1107*6dbdd20aSAndroid Build Coastguard Worker   data_sources_.erase(ds_it);
1108*6dbdd20aSAndroid Build Coastguard Worker 
1109*6dbdd20aSAndroid Build Coastguard Worker   endpoint_->NotifyDataSourceStopped(ds_id);
1110*6dbdd20aSAndroid Build Coastguard Worker 
1111*6dbdd20aSAndroid Build Coastguard Worker   // Clean up resources if there are no more active sources.
1112*6dbdd20aSAndroid Build Coastguard Worker   if (data_sources_.empty()) {
1113*6dbdd20aSAndroid Build Coastguard Worker     callstack_trie_.ClearTrie();  // purge internings
1114*6dbdd20aSAndroid Build Coastguard Worker     base::MaybeReleaseAllocatorMemToOS();
1115*6dbdd20aSAndroid Build Coastguard Worker   }
1116*6dbdd20aSAndroid Build Coastguard Worker }
1117*6dbdd20aSAndroid Build Coastguard Worker 
1118*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): maybe make the tracing service respect premature
1119*6dbdd20aSAndroid Build Coastguard Worker // producer-driven stops, and then issue a NotifyDataSourceStopped here.
1120*6dbdd20aSAndroid Build Coastguard Worker // Alternatively (and at the expense of higher complexity) introduce a new data
1121*6dbdd20aSAndroid Build Coastguard Worker // source status of "tombstoned", and propagate it until the source is stopped
1122*6dbdd20aSAndroid Build Coastguard Worker // by the service (this would technically allow for stricter lifetime checking
1123*6dbdd20aSAndroid Build Coastguard Worker // of data sources, and help with discarding periodic flushes).
1124*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): Purging while stopping will currently leave the stop
1125*6dbdd20aSAndroid Build Coastguard Worker // unacknowledged. Consider checking whether the DS is stopping here, and if so,
1126*6dbdd20aSAndroid Build Coastguard Worker // notifying immediately after erasing.
PurgeDataSource(DataSourceInstanceID ds_id)1127*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::PurgeDataSource(DataSourceInstanceID ds_id) {
1128*6dbdd20aSAndroid Build Coastguard Worker   auto ds_it = data_sources_.find(ds_id);
1129*6dbdd20aSAndroid Build Coastguard Worker   if (ds_it == data_sources_.end())
1130*6dbdd20aSAndroid Build Coastguard Worker     return;
1131*6dbdd20aSAndroid Build Coastguard Worker   DataSourceState& ds = ds_it->second;
1132*6dbdd20aSAndroid Build Coastguard Worker 
1133*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_LOG("Stopping DataSource(%zu) prematurely",
1134*6dbdd20aSAndroid Build Coastguard Worker                static_cast<size_t>(ds_id));
1135*6dbdd20aSAndroid Build Coastguard Worker 
1136*6dbdd20aSAndroid Build Coastguard Worker   unwinding_worker_->PostPurgeDataSource(ds_id);
1137*6dbdd20aSAndroid Build Coastguard Worker 
1138*6dbdd20aSAndroid Build Coastguard Worker   // Write a packet indicating the abrupt stop.
1139*6dbdd20aSAndroid Build Coastguard Worker   {
1140*6dbdd20aSAndroid Build Coastguard Worker     auto packet = StartTracePacket(ds.trace_writer.get());
1141*6dbdd20aSAndroid Build Coastguard Worker     packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
1142*6dbdd20aSAndroid Build Coastguard Worker     packet->set_timestamp_clock_id(
1143*6dbdd20aSAndroid Build Coastguard Worker         protos::pbzero::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
1144*6dbdd20aSAndroid Build Coastguard Worker     auto* perf_sample = packet->set_perf_sample();
1145*6dbdd20aSAndroid Build Coastguard Worker     auto* producer_event = perf_sample->set_producer_event();
1146*6dbdd20aSAndroid Build Coastguard Worker     producer_event->set_source_stop_reason(
1147*6dbdd20aSAndroid Build Coastguard Worker         protos::pbzero::PerfSample::ProducerEvent::PROFILER_STOP_GUARDRAIL);
1148*6dbdd20aSAndroid Build Coastguard Worker   }
1149*6dbdd20aSAndroid Build Coastguard Worker 
1150*6dbdd20aSAndroid Build Coastguard Worker   ds.trace_writer->Flush();
1151*6dbdd20aSAndroid Build Coastguard Worker   data_sources_.erase(ds_it);
1152*6dbdd20aSAndroid Build Coastguard Worker 
1153*6dbdd20aSAndroid Build Coastguard Worker   // Clean up resources if there are no more active sources.
1154*6dbdd20aSAndroid Build Coastguard Worker   if (data_sources_.empty()) {
1155*6dbdd20aSAndroid Build Coastguard Worker     callstack_trie_.ClearTrie();  // purge internings
1156*6dbdd20aSAndroid Build Coastguard Worker     base::MaybeReleaseAllocatorMemToOS();
1157*6dbdd20aSAndroid Build Coastguard Worker   }
1158*6dbdd20aSAndroid Build Coastguard Worker }
1159*6dbdd20aSAndroid Build Coastguard Worker 
1160*6dbdd20aSAndroid Build Coastguard Worker // Either:
1161*6dbdd20aSAndroid Build Coastguard Worker // * choose a random number up to |shard_count|.
1162*6dbdd20aSAndroid Build Coastguard Worker // * reuse a choice made previously by a data source within this tracing
1163*6dbdd20aSAndroid Build Coastguard Worker //   session. The config option requires that all data sources within one config
1164*6dbdd20aSAndroid Build Coastguard Worker //   have the same shard count.
GetOrChooseCallstackProcessShard(uint64_t tracing_session_id,uint32_t shard_count)1165*6dbdd20aSAndroid Build Coastguard Worker std::optional<ProcessSharding> PerfProducer::GetOrChooseCallstackProcessShard(
1166*6dbdd20aSAndroid Build Coastguard Worker     uint64_t tracing_session_id,
1167*6dbdd20aSAndroid Build Coastguard Worker     uint32_t shard_count) {
1168*6dbdd20aSAndroid Build Coastguard Worker   for (auto& it : data_sources_) {
1169*6dbdd20aSAndroid Build Coastguard Worker     const DataSourceState& ds = it.second;
1170*6dbdd20aSAndroid Build Coastguard Worker     const auto& sharding = ds.event_config.filter().process_sharding;
1171*6dbdd20aSAndroid Build Coastguard Worker     if ((ds.tracing_session_id != tracing_session_id) || !sharding.has_value())
1172*6dbdd20aSAndroid Build Coastguard Worker       continue;
1173*6dbdd20aSAndroid Build Coastguard Worker 
1174*6dbdd20aSAndroid Build Coastguard Worker     // Found existing data source, reuse its decision while doing best-effort
1175*6dbdd20aSAndroid Build Coastguard Worker     // error reporting (logging) if the shard count is not the same.
1176*6dbdd20aSAndroid Build Coastguard Worker     if (sharding->shard_count != shard_count) {
1177*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_ELOG(
1178*6dbdd20aSAndroid Build Coastguard Worker           "Mismatch of process_shard_count between data sources in tracing "
1179*6dbdd20aSAndroid Build Coastguard Worker           "session %" PRIu64 ". Overriding shard count to match.",
1180*6dbdd20aSAndroid Build Coastguard Worker           tracing_session_id);
1181*6dbdd20aSAndroid Build Coastguard Worker     }
1182*6dbdd20aSAndroid Build Coastguard Worker     return sharding;
1183*6dbdd20aSAndroid Build Coastguard Worker   }
1184*6dbdd20aSAndroid Build Coastguard Worker 
1185*6dbdd20aSAndroid Build Coastguard Worker   // First data source in this session, choose random shard.
1186*6dbdd20aSAndroid Build Coastguard Worker   std::random_device r;
1187*6dbdd20aSAndroid Build Coastguard Worker   std::minstd_rand minstd(r());
1188*6dbdd20aSAndroid Build Coastguard Worker   std::uniform_int_distribution<uint32_t> dist(0, shard_count - 1);
1189*6dbdd20aSAndroid Build Coastguard Worker   uint32_t chosen_shard = dist(minstd);
1190*6dbdd20aSAndroid Build Coastguard Worker 
1191*6dbdd20aSAndroid Build Coastguard Worker   ProcessSharding ret;
1192*6dbdd20aSAndroid Build Coastguard Worker   ret.shard_count = shard_count;
1193*6dbdd20aSAndroid Build Coastguard Worker   ret.chosen_shard = chosen_shard;
1194*6dbdd20aSAndroid Build Coastguard Worker 
1195*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(ret.shard_count && ret.chosen_shard < ret.shard_count);
1196*6dbdd20aSAndroid Build Coastguard Worker   return ret;
1197*6dbdd20aSAndroid Build Coastguard Worker }
1198*6dbdd20aSAndroid Build Coastguard Worker 
StartMetatraceSource(DataSourceInstanceID ds_id,BufferID target_buffer)1199*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::StartMetatraceSource(DataSourceInstanceID ds_id,
1200*6dbdd20aSAndroid Build Coastguard Worker                                         BufferID target_buffer) {
1201*6dbdd20aSAndroid Build Coastguard Worker   auto writer = endpoint_->CreateTraceWriter(target_buffer);
1202*6dbdd20aSAndroid Build Coastguard Worker 
1203*6dbdd20aSAndroid Build Coastguard Worker   auto it_and_inserted = metatrace_writers_.emplace(
1204*6dbdd20aSAndroid Build Coastguard Worker       std::piecewise_construct, std::make_tuple(ds_id), std::make_tuple());
1205*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(it_and_inserted.second);
1206*6dbdd20aSAndroid Build Coastguard Worker   // Note: only the first concurrent writer will actually be active.
1207*6dbdd20aSAndroid Build Coastguard Worker   metatrace_writers_[ds_id].Enable(task_runner_, std::move(writer),
1208*6dbdd20aSAndroid Build Coastguard Worker                                    metatrace::TAG_ANY);
1209*6dbdd20aSAndroid Build Coastguard Worker }
1210*6dbdd20aSAndroid Build Coastguard Worker 
ConnectWithRetries(const char * socket_name)1211*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::ConnectWithRetries(const char* socket_name) {
1212*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(state_ == kNotStarted);
1213*6dbdd20aSAndroid Build Coastguard Worker   state_ = kNotConnected;
1214*6dbdd20aSAndroid Build Coastguard Worker 
1215*6dbdd20aSAndroid Build Coastguard Worker   ResetConnectionBackoff();
1216*6dbdd20aSAndroid Build Coastguard Worker   producer_socket_name_ = socket_name;
1217*6dbdd20aSAndroid Build Coastguard Worker   ConnectService();
1218*6dbdd20aSAndroid Build Coastguard Worker }
1219*6dbdd20aSAndroid Build Coastguard Worker 
ConnectService()1220*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::ConnectService() {
1221*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(state_ == kNotConnected);
1222*6dbdd20aSAndroid Build Coastguard Worker   state_ = kConnecting;
1223*6dbdd20aSAndroid Build Coastguard Worker   endpoint_ = ProducerIPCClient::Connect(
1224*6dbdd20aSAndroid Build Coastguard Worker       producer_socket_name_, this, kProducerName, task_runner_,
1225*6dbdd20aSAndroid Build Coastguard Worker       TracingService::ProducerSMBScrapingMode::kEnabled);
1226*6dbdd20aSAndroid Build Coastguard Worker }
1227*6dbdd20aSAndroid Build Coastguard Worker 
IncreaseConnectionBackoff()1228*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::IncreaseConnectionBackoff() {
1229*6dbdd20aSAndroid Build Coastguard Worker   connection_backoff_ms_ *= 2;
1230*6dbdd20aSAndroid Build Coastguard Worker   if (connection_backoff_ms_ > kMaxConnectionBackoffMs)
1231*6dbdd20aSAndroid Build Coastguard Worker     connection_backoff_ms_ = kMaxConnectionBackoffMs;
1232*6dbdd20aSAndroid Build Coastguard Worker }
1233*6dbdd20aSAndroid Build Coastguard Worker 
ResetConnectionBackoff()1234*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::ResetConnectionBackoff() {
1235*6dbdd20aSAndroid Build Coastguard Worker   connection_backoff_ms_ = kInitialConnectionBackoffMs;
1236*6dbdd20aSAndroid Build Coastguard Worker }
1237*6dbdd20aSAndroid Build Coastguard Worker 
OnConnect()1238*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::OnConnect() {
1239*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(state_ == kConnecting);
1240*6dbdd20aSAndroid Build Coastguard Worker   state_ = kConnected;
1241*6dbdd20aSAndroid Build Coastguard Worker   ResetConnectionBackoff();
1242*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_LOG("Connected to the service");
1243*6dbdd20aSAndroid Build Coastguard Worker 
1244*6dbdd20aSAndroid Build Coastguard Worker   {
1245*6dbdd20aSAndroid Build Coastguard Worker     // linux.perf
1246*6dbdd20aSAndroid Build Coastguard Worker     DataSourceDescriptor desc;
1247*6dbdd20aSAndroid Build Coastguard Worker     desc.set_name(kDataSourceName);
1248*6dbdd20aSAndroid Build Coastguard Worker     desc.set_handles_incremental_state_clear(true);
1249*6dbdd20aSAndroid Build Coastguard Worker     desc.set_will_notify_on_stop(true);
1250*6dbdd20aSAndroid Build Coastguard Worker     endpoint_->RegisterDataSource(desc);
1251*6dbdd20aSAndroid Build Coastguard Worker   }
1252*6dbdd20aSAndroid Build Coastguard Worker   {
1253*6dbdd20aSAndroid Build Coastguard Worker     // metatrace
1254*6dbdd20aSAndroid Build Coastguard Worker     DataSourceDescriptor desc;
1255*6dbdd20aSAndroid Build Coastguard Worker     desc.set_name(MetatraceWriter::kDataSourceName);
1256*6dbdd20aSAndroid Build Coastguard Worker     endpoint_->RegisterDataSource(desc);
1257*6dbdd20aSAndroid Build Coastguard Worker   }
1258*6dbdd20aSAndroid Build Coastguard Worker   // Used by tracebox to synchronize with traced_probes being registered.
1259*6dbdd20aSAndroid Build Coastguard Worker   if (all_data_sources_registered_cb_) {
1260*6dbdd20aSAndroid Build Coastguard Worker     endpoint_->Sync(all_data_sources_registered_cb_);
1261*6dbdd20aSAndroid Build Coastguard Worker   }
1262*6dbdd20aSAndroid Build Coastguard Worker }
1263*6dbdd20aSAndroid Build Coastguard Worker 
OnDisconnect()1264*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::OnDisconnect() {
1265*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(state_ == kConnected || state_ == kConnecting);
1266*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_LOG("Disconnected from tracing service");
1267*6dbdd20aSAndroid Build Coastguard Worker 
1268*6dbdd20aSAndroid Build Coastguard Worker   auto weak_producer = weak_factory_.GetWeakPtr();
1269*6dbdd20aSAndroid Build Coastguard Worker   if (state_ == kConnected)
1270*6dbdd20aSAndroid Build Coastguard Worker     return task_runner_->PostTask([weak_producer] {
1271*6dbdd20aSAndroid Build Coastguard Worker       if (weak_producer)
1272*6dbdd20aSAndroid Build Coastguard Worker         weak_producer->Restart();
1273*6dbdd20aSAndroid Build Coastguard Worker     });
1274*6dbdd20aSAndroid Build Coastguard Worker 
1275*6dbdd20aSAndroid Build Coastguard Worker   state_ = kNotConnected;
1276*6dbdd20aSAndroid Build Coastguard Worker   IncreaseConnectionBackoff();
1277*6dbdd20aSAndroid Build Coastguard Worker   task_runner_->PostDelayedTask(
1278*6dbdd20aSAndroid Build Coastguard Worker       [weak_producer] {
1279*6dbdd20aSAndroid Build Coastguard Worker         if (weak_producer)
1280*6dbdd20aSAndroid Build Coastguard Worker           weak_producer->ConnectService();
1281*6dbdd20aSAndroid Build Coastguard Worker       },
1282*6dbdd20aSAndroid Build Coastguard Worker       connection_backoff_ms_);
1283*6dbdd20aSAndroid Build Coastguard Worker }
1284*6dbdd20aSAndroid Build Coastguard Worker 
Restart()1285*6dbdd20aSAndroid Build Coastguard Worker void PerfProducer::Restart() {
1286*6dbdd20aSAndroid Build Coastguard Worker   // We lost the connection with the tracing service. At this point we need
1287*6dbdd20aSAndroid Build Coastguard Worker   // to reset all the data sources. Trying to handle that manually is going to
1288*6dbdd20aSAndroid Build Coastguard Worker   // be error prone. What we do here is simply destroy the instance and
1289*6dbdd20aSAndroid Build Coastguard Worker   // recreate it again.
1290*6dbdd20aSAndroid Build Coastguard Worker   base::TaskRunner* task_runner = task_runner_;
1291*6dbdd20aSAndroid Build Coastguard Worker   const char* socket_name = producer_socket_name_;
1292*6dbdd20aSAndroid Build Coastguard Worker   ProcDescriptorGetter* proc_fd_getter = proc_fd_getter_;
1293*6dbdd20aSAndroid Build Coastguard Worker 
1294*6dbdd20aSAndroid Build Coastguard Worker   // Invoke destructor and then the constructor again.
1295*6dbdd20aSAndroid Build Coastguard Worker   this->~PerfProducer();
1296*6dbdd20aSAndroid Build Coastguard Worker   new (this) PerfProducer(proc_fd_getter, task_runner);
1297*6dbdd20aSAndroid Build Coastguard Worker 
1298*6dbdd20aSAndroid Build Coastguard Worker   ConnectWithRetries(socket_name);
1299*6dbdd20aSAndroid Build Coastguard Worker }
1300*6dbdd20aSAndroid Build Coastguard Worker 
1301*6dbdd20aSAndroid Build Coastguard Worker }  // namespace profiling
1302*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
1303