1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/ftrace/ftrace_parser.h"
18
19 #include "perfetto/base/logging.h"
20 #include "perfetto/ext/base/string_utils.h"
21 #include "perfetto/ext/base/string_writer.h"
22 #include "perfetto/protozero/proto_decoder.h"
23 #include "src/trace_processor/importers/common/args_tracker.h"
24 #include "src/trace_processor/importers/common/async_track_set_tracker.h"
25 #include "src/trace_processor/importers/common/metadata_tracker.h"
26 #include "src/trace_processor/importers/common/parser_types.h"
27 #include "src/trace_processor/importers/common/process_tracker.h"
28 #include "src/trace_processor/importers/common/track_tracker.h"
29 #include "src/trace_processor/importers/ftrace/binder_tracker.h"
30 #include "src/trace_processor/importers/ftrace/thread_state_tracker.h"
31 #include "src/trace_processor/importers/ftrace/v4l2_tracker.h"
32 #include "src/trace_processor/importers/ftrace/virtio_video_tracker.h"
33 #include "src/trace_processor/importers/i2c/i2c_tracker.h"
34 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
35 #include "src/trace_processor/importers/syscalls/syscall_tracker.h"
36 #include "src/trace_processor/importers/systrace/systrace_parser.h"
37 #include "src/trace_processor/storage/stats.h"
38 #include "src/trace_processor/storage/trace_storage.h"
39 #include "src/trace_processor/types/softirq_action.h"
40 #include "src/trace_processor/types/tcp_state.h"
41
42 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
43 #include "protos/perfetto/trace/ftrace/binder.pbzero.h"
44 #include "protos/perfetto/trace/ftrace/cma.pbzero.h"
45 #include "protos/perfetto/trace/ftrace/cpuhp.pbzero.h"
46 #include "protos/perfetto/trace/ftrace/cros_ec.pbzero.h"
47 #include "protos/perfetto/trace/ftrace/dmabuf_heap.pbzero.h"
48 #include "protos/perfetto/trace/ftrace/dpu.pbzero.h"
49 #include "protos/perfetto/trace/ftrace/fastrpc.pbzero.h"
50 #include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
51 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
52 #include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
53 #include "protos/perfetto/trace/ftrace/g2d.pbzero.h"
54 #include "protos/perfetto/trace/ftrace/generic.pbzero.h"
55 #include "protos/perfetto/trace/ftrace/gpu_mem.pbzero.h"
56 #include "protos/perfetto/trace/ftrace/i2c.pbzero.h"
57 #include "protos/perfetto/trace/ftrace/ion.pbzero.h"
58 #include "protos/perfetto/trace/ftrace/irq.pbzero.h"
59 #include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
60 #include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
61 #include "protos/perfetto/trace/ftrace/lwis.pbzero.h"
62 #include "protos/perfetto/trace/ftrace/mali.pbzero.h"
63 #include "protos/perfetto/trace/ftrace/mm_event.pbzero.h"
64 #include "protos/perfetto/trace/ftrace/net.pbzero.h"
65 #include "protos/perfetto/trace/ftrace/oom.pbzero.h"
66 #include "protos/perfetto/trace/ftrace/power.pbzero.h"
67 #include "protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h"
68 #include "protos/perfetto/trace/ftrace/sched.pbzero.h"
69 #include "protos/perfetto/trace/ftrace/scm.pbzero.h"
70 #include "protos/perfetto/trace/ftrace/sde.pbzero.h"
71 #include "protos/perfetto/trace/ftrace/signal.pbzero.h"
72 #include "protos/perfetto/trace/ftrace/skb.pbzero.h"
73 #include "protos/perfetto/trace/ftrace/sock.pbzero.h"
74 #include "protos/perfetto/trace/ftrace/synthetic.pbzero.h"
75 #include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
76 #include "protos/perfetto/trace/ftrace/task.pbzero.h"
77 #include "protos/perfetto/trace/ftrace/tcp.pbzero.h"
78 #include "protos/perfetto/trace/ftrace/thermal.pbzero.h"
79 #include "protos/perfetto/trace/ftrace/trusty.pbzero.h"
80 #include "protos/perfetto/trace/ftrace/ufs.pbzero.h"
81 #include "protos/perfetto/trace/ftrace/vmscan.pbzero.h"
82 #include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
83 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
84
85 namespace perfetto {
86 namespace trace_processor {
87
88 namespace {
89
90 using protozero::ConstBytes;
91 using protozero::ProtoDecoder;
92
93 struct FtraceEventAndFieldId {
94 uint32_t event_id;
95 uint32_t field_id;
96 };
97
98 // Contains a list of all the proto fields in ftrace events which represent
99 // kernel functions. This list is used to convert the iids in these fields to
100 // proper kernel symbols.
101 // TODO(lalitm): going through this array is O(n) on a hot-path (see
102 // ParseTypedFtraceToRaw). Consider changing this if we end up adding a lot of
103 // events here.
104 constexpr auto kKernelFunctionFields = std::array<FtraceEventAndFieldId, 6>{
105 FtraceEventAndFieldId{
106 protos::pbzero::FtraceEvent::kSchedBlockedReasonFieldNumber,
107 protos::pbzero::SchedBlockedReasonFtraceEvent::kCallerFieldNumber},
108 FtraceEventAndFieldId{
109 protos::pbzero::FtraceEvent::kWorkqueueExecuteStartFieldNumber,
110 protos::pbzero::WorkqueueExecuteStartFtraceEvent::kFunctionFieldNumber},
111 FtraceEventAndFieldId{
112 protos::pbzero::FtraceEvent::kWorkqueueQueueWorkFieldNumber,
113 protos::pbzero::WorkqueueQueueWorkFtraceEvent::kFunctionFieldNumber},
114 FtraceEventAndFieldId{
115 protos::pbzero::FtraceEvent::kFuncgraphEntryFieldNumber,
116 protos::pbzero::FuncgraphEntryFtraceEvent::kFuncFieldNumber},
117 FtraceEventAndFieldId{
118 protos::pbzero::FtraceEvent::kFuncgraphExitFieldNumber,
119 protos::pbzero::FuncgraphExitFtraceEvent::kFuncFieldNumber},
120 FtraceEventAndFieldId{
121 protos::pbzero::FtraceEvent::kMmShrinkSlabStartFieldNumber,
122 protos::pbzero::MmShrinkSlabStartFtraceEvent::kShrinkFieldNumber}};
123
GetUfsCmdString(uint32_t ufsopcode,uint32_t gid)124 std::string GetUfsCmdString(uint32_t ufsopcode, uint32_t gid) {
125 std::string buffer;
126 switch (ufsopcode) {
127 case 4:
128 buffer = "FORMAT UNIT";
129 break;
130 case 18:
131 buffer = "INQUIRY";
132 break;
133 case 85:
134 buffer = "MODE SELECT (10)";
135 break;
136 case 90:
137 buffer = "MODE SENSE (10)";
138 break;
139 case 52:
140 buffer = "PRE-FETCH (10)";
141 break;
142 case 144:
143 buffer = "PRE-FETCH (16)";
144 break;
145 case 8:
146 buffer = "READ (6)";
147 break;
148 case 40:
149 buffer = "READ (10)";
150 break;
151 case 136:
152 buffer = "READ (16)";
153 break;
154 case 60:
155 buffer = "READ BUFFER";
156 break;
157 case 37:
158 buffer = "READ CAPACITY (10)";
159 break;
160 case 158:
161 buffer = "READ CAPACITY (16)";
162 break;
163 case 160:
164 buffer = "REPORT LUNS";
165 break;
166 case 3:
167 buffer = "REQUEST SENSE";
168 break;
169 case 162:
170 buffer = "SECURITY PROTOCOL IN";
171 break;
172 case 181:
173 buffer = "SECURITY PROTOCOL OUT";
174 break;
175 case 29:
176 buffer = "SEND DIAGNOSTIC";
177 break;
178 case 27:
179 buffer = "START STOP UNIT";
180 break;
181 case 53:
182 buffer = "SYNCHRONIZE CACHE (10)";
183 break;
184 case 145:
185 buffer = "SYNCHRONIZE CACHE (16)";
186 break;
187 case 0:
188 buffer = "TEST UNIT READY";
189 break;
190 case 66:
191 buffer = "UNMAP";
192 break;
193 case 47:
194 buffer = "VERIFY";
195 break;
196 case 10:
197 buffer = "WRITE (6)";
198 break;
199 case 42:
200 buffer = "WRITE (10)";
201 break;
202 case 138:
203 buffer = "WRITE (16)";
204 break;
205 case 59:
206 buffer = "WRITE BUFFER";
207 break;
208 default:
209 buffer = "UNDEFINED";
210 break;
211 }
212 if (gid > 0) {
213 base::StackString<32> gid_str(" (GID=0x%x)", gid);
214 buffer = buffer + gid_str.c_str();
215 }
216 return buffer;
217 }
218 } // namespace
219
FtraceParser(TraceProcessorContext * context)220 FtraceParser::FtraceParser(TraceProcessorContext* context)
221 : context_(context),
222 rss_stat_tracker_(context),
223 drm_tracker_(context),
224 iostat_tracker_(context),
225 virtio_gpu_tracker_(context),
226 mali_gpu_event_tracker_(context),
227 pkvm_hyp_cpu_tracker_(context),
228 sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
229 sched_waking_name_id_(context->storage->InternString("sched_waking")),
230 cpu_id_(context->storage->InternString("cpu")),
231 cpu_freq_name_id_(context->storage->InternString("cpufreq")),
232 gpu_freq_name_id_(context->storage->InternString("gpufreq")),
233 cpu_idle_name_id_(context->storage->InternString("cpuidle")),
234 suspend_resume_name_id_(
235 context->storage->InternString("Suspend/Resume Latency")),
236 suspend_resume_minimal_name_id_(
237 context->storage->InternString("Suspend/Resume Minimal")),
238 suspend_resume_minimal_slice_name_id_(
239 context->storage->InternString("Suspended")),
240 kfree_skb_name_id_(context->storage->InternString("Kfree Skb IP Prot")),
241 ion_total_id_(context->storage->InternString("mem.ion")),
242 ion_change_id_(context->storage->InternString("mem.ion_change")),
243 ion_buffer_id_(context->storage->InternString("mem.ion_buffer")),
244 dma_heap_total_id_(context->storage->InternString("mem.dma_heap")),
245 dma_heap_change_id_(
246 context->storage->InternString("mem.dma_heap_change")),
247 dma_buffer_id_(context->storage->InternString("mem.dma_buffer")),
248 ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
249 ion_change_unknown_id_(
250 context->storage->InternString("mem.ion_change.unknown")),
251 signal_generate_id_(context->storage->InternString("signal_generate")),
252 signal_deliver_id_(context->storage->InternString("signal_deliver")),
253 oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
254 lmk_id_(context->storage->InternString("mem.lmk")),
255 comm_name_id_(context->storage->InternString("comm")),
256 signal_name_id_(context_->storage->InternString("signal.sig")),
257 oom_kill_id_(context_->storage->InternString("mem.oom_kill")),
258 workqueue_id_(context_->storage->InternString("workqueue")),
259 irq_id_(context_->storage->InternString("irq")),
260 tcp_state_id_(context_->storage->InternString("tcp_state")),
261 tcp_event_id_(context_->storage->InternString("tcp_event")),
262 protocol_arg_id_(context_->storage->InternString("protocol")),
263 napi_gro_id_(context_->storage->InternString("napi_gro")),
264 tcp_retransmited_name_id_(
265 context_->storage->InternString("TCP Retransmit Skb")),
266 ret_arg_id_(context_->storage->InternString("ret")),
267 len_arg_id_(context->storage->InternString("len")),
268 direct_reclaim_nr_reclaimed_id_(
269 context->storage->InternString("direct_reclaim_nr_reclaimed")),
270 direct_reclaim_order_id_(
271 context->storage->InternString("direct_reclaim_order")),
272 direct_reclaim_may_writepage_id_(
273 context->storage->InternString("direct_reclaim_may_writepage")),
274 direct_reclaim_gfp_flags_id_(
275 context->storage->InternString("direct_reclaim_gfp_flags")),
276 vec_arg_id_(context->storage->InternString("vec")),
277 gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
278 gpu_mem_total_unit_id_(context->storage->InternString(
279 std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
280 gpu_mem_total_global_desc_id_(context->storage->InternString(
281 "Total GPU memory used by the entire system")),
282 gpu_mem_total_proc_desc_id_(context->storage->InternString(
283 "Total GPU memory used by this process")),
284 io_wait_id_(context->storage->InternString("io_wait")),
285 function_id_(context->storage->InternString("function")),
286 waker_utid_id_(context->storage->InternString("waker_utid")),
287 cros_ec_arg_num_id_(context->storage->InternString("ec_num")),
288 cros_ec_arg_ec_id_(context->storage->InternString("ec_delta")),
289 cros_ec_arg_sample_ts_id_(context->storage->InternString("sample_ts")),
290 ufs_clkgating_id_(context->storage->InternString(
291 "io.ufs.clkgating (OFF:0/REQ_OFF/REQ_ON/ON:3)")),
292 ufs_command_count_id_(
293 context->storage->InternString("io.ufs.command.count")),
294 shrink_slab_id_(context_->storage->InternString("mm_vmscan_shrink_slab")),
295 shrink_name_id_(context->storage->InternString("shrink_name")),
296 shrink_total_scan_id_(context->storage->InternString("total_scan")),
297 shrink_freed_id_(context->storage->InternString("freed")),
298 shrink_priority_id_(context->storage->InternString("priority")),
299 trusty_category_id_(context_->storage->InternString("tipc")),
300 trusty_name_trusty_std_id_(context_->storage->InternString("trusty_std")),
301 trusty_name_tipc_rx_id_(context_->storage->InternString("tipc_rx")),
302 cma_alloc_id_(context_->storage->InternString("mm_cma_alloc")),
303 cma_name_id_(context_->storage->InternString("cma_name")),
304 cma_pfn_id_(context_->storage->InternString("cma_pfn")),
305 cma_req_pages_id_(context_->storage->InternString("cma_req_pages")),
306 cma_nr_migrated_id_(context_->storage->InternString("cma_nr_migrated")),
307 cma_nr_reclaimed_id_(context_->storage->InternString("cma_nr_reclaimed")),
308 cma_nr_mapped_id_(context_->storage->InternString("cma_nr_mapped")),
309 cma_nr_isolate_fail_id_(
310 context_->storage->InternString("cma_nr_isolate_fail")),
311 cma_nr_migrate_fail_id_(
312 context_->storage->InternString("cma_nr_migrate_fail")),
313 cma_nr_test_fail_id_(context_->storage->InternString("cma_nr_test_fail")),
314 syscall_ret_id_(context->storage->InternString("ret")),
315 syscall_args_id_(context->storage->InternString("args")),
316 replica_slice_id_(context->storage->InternString("replica_slice")) {
317 // Build the lookup table for the strings inside ftrace events (e.g. the
318 // name of ftrace event fields and the names of their args).
319 for (size_t i = 0; i < GetDescriptorsSize(); i++) {
320 auto* descriptor = GetMessageDescriptorForId(i);
321 if (!descriptor->name) {
322 ftrace_message_strings_.emplace_back();
323 continue;
324 }
325
326 FtraceMessageStrings ftrace_strings;
327 ftrace_strings.message_name_id =
328 context->storage->InternString(descriptor->name);
329
330 for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
331 const auto& field = descriptor->fields[fid];
332 if (!field.name)
333 continue;
334 ftrace_strings.field_name_ids[fid] =
335 context->storage->InternString(field.name);
336 }
337 ftrace_message_strings_.emplace_back(ftrace_strings);
338 }
339
340 // Array initialization causes a spurious warning due to llvm bug.
341 // See https://bugs.llvm.org/show_bug.cgi?id=21629
342 fast_rpc_delta_names_[0] =
343 context->storage->InternString("mem.fastrpc_change[ASDP]");
344 fast_rpc_delta_names_[1] =
345 context->storage->InternString("mem.fastrpc_change[MDSP]");
346 fast_rpc_delta_names_[2] =
347 context->storage->InternString("mem.fastrpc_change[SDSP]");
348 fast_rpc_delta_names_[3] =
349 context->storage->InternString("mem.fastrpc_change[CDSP]");
350 fast_rpc_total_names_[0] =
351 context->storage->InternString("mem.fastrpc[ASDP]");
352 fast_rpc_total_names_[1] =
353 context->storage->InternString("mem.fastrpc[MDSP]");
354 fast_rpc_total_names_[2] =
355 context->storage->InternString("mem.fastrpc[SDSP]");
356 fast_rpc_total_names_[3] =
357 context->storage->InternString("mem.fastrpc[CDSP]");
358
359 mm_event_counter_names_ = {
360 {MmEventCounterNames(
361 context->storage->InternString("mem.mm.min_flt.count"),
362 context->storage->InternString("mem.mm.min_flt.max_lat"),
363 context->storage->InternString("mem.mm.min_flt.avg_lat")),
364 MmEventCounterNames(
365 context->storage->InternString("mem.mm.maj_flt.count"),
366 context->storage->InternString("mem.mm.maj_flt.max_lat"),
367 context->storage->InternString("mem.mm.maj_flt.avg_lat")),
368 MmEventCounterNames(
369 context->storage->InternString("mem.mm.read_io.count"),
370 context->storage->InternString("mem.mm.read_io.max_lat"),
371 context->storage->InternString("mem.mm.read_io.avg_lat")),
372 MmEventCounterNames(
373 context->storage->InternString("mem.mm.compaction.count"),
374 context->storage->InternString("mem.mm.compaction.max_lat"),
375 context->storage->InternString("mem.mm.compaction.avg_lat")),
376 MmEventCounterNames(
377 context->storage->InternString("mem.mm.reclaim.count"),
378 context->storage->InternString("mem.mm.reclaim.max_lat"),
379 context->storage->InternString("mem.mm.reclaim.avg_lat")),
380 MmEventCounterNames(
381 context->storage->InternString("mem.mm.swp_flt.count"),
382 context->storage->InternString("mem.mm.swp_flt.max_lat"),
383 context->storage->InternString("mem.mm.swp_flt.avg_lat")),
384 MmEventCounterNames(
385 context->storage->InternString("mem.mm.kern_alloc.count"),
386 context->storage->InternString("mem.mm.kern_alloc.max_lat"),
387 context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
388 }
389
ParseFtraceStats(ConstBytes blob,uint32_t packet_sequence_id)390 void FtraceParser::ParseFtraceStats(ConstBytes blob,
391 uint32_t packet_sequence_id) {
392 protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
393 bool is_start =
394 evt.phase() == protos::pbzero::FtraceStats::Phase::START_OF_TRACE;
395 bool is_end = evt.phase() == protos::pbzero::FtraceStats::Phase::END_OF_TRACE;
396 if (!is_start && !is_end) {
397 PERFETTO_ELOG("Ignoring unknown ftrace stats phase %d", evt.phase());
398 return;
399 }
400 size_t phase = is_end ? 1 : 0;
401
402 // This code relies on the fact that each ftrace_cpu_XXX_end event is
403 // just after the corresponding ftrace_cpu_XXX_begin event.
404 static_assert(
405 stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
406 1 &&
407 stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
408 "ftrace_cpu_XXX stats definition are messed up");
409
410 auto* storage = context_->storage.get();
411 for (auto it = evt.cpu_stats(); it; ++it) {
412 protos::pbzero::FtraceCpuStats::Decoder cpu_stats(*it);
413 int cpu = static_cast<int>(cpu_stats.cpu());
414
415 int64_t entries = static_cast<int64_t>(cpu_stats.entries());
416 int64_t overrun = static_cast<int64_t>(cpu_stats.overrun());
417 int64_t commit_overrun = static_cast<int64_t>(cpu_stats.commit_overrun());
418 int64_t bytes_read = static_cast<int64_t>(cpu_stats.bytes_read());
419 int64_t dropped_events = static_cast<int64_t>(cpu_stats.dropped_events());
420 int64_t read_events = static_cast<int64_t>(cpu_stats.read_events());
421 int64_t now_ts = static_cast<int64_t>(cpu_stats.now_ts() * 1e9);
422
423 storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
424 entries);
425 storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
426 overrun);
427 storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
428 cpu, commit_overrun);
429 storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
430 bytes_read);
431 storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
432 cpu, dropped_events);
433 storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
434 read_events);
435 storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
436 now_ts);
437
438 if (is_end) {
439 auto opt_entries_begin =
440 storage->GetIndexedStats(stats::ftrace_cpu_entries_begin, cpu);
441 if (opt_entries_begin) {
442 int64_t delta_entries = entries - opt_entries_begin.value();
443 storage->SetIndexedStats(stats::ftrace_cpu_entries_delta, cpu,
444 delta_entries);
445 }
446
447 auto opt_overrun_begin =
448 storage->GetIndexedStats(stats::ftrace_cpu_overrun_begin, cpu);
449 if (opt_overrun_begin) {
450 int64_t delta_overrun = overrun - opt_overrun_begin.value();
451 storage->SetIndexedStats(stats::ftrace_cpu_overrun_delta, cpu,
452 delta_overrun);
453 }
454
455 auto opt_commit_overrun_begin =
456 storage->GetIndexedStats(stats::ftrace_cpu_commit_overrun_begin, cpu);
457 if (opt_commit_overrun_begin) {
458 int64_t delta_commit_overrun =
459 commit_overrun - opt_commit_overrun_begin.value();
460 storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_delta, cpu,
461 delta_commit_overrun);
462 }
463
464 auto opt_bytes_read_begin =
465 storage->GetIndexedStats(stats::ftrace_cpu_bytes_read_begin, cpu);
466 if (opt_bytes_read_begin) {
467 int64_t delta_bytes_read = bytes_read - opt_bytes_read_begin.value();
468 storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_delta, cpu,
469 delta_bytes_read);
470 }
471
472 auto opt_dropped_events_begin =
473 storage->GetIndexedStats(stats::ftrace_cpu_dropped_events_begin, cpu);
474 if (opt_dropped_events_begin) {
475 int64_t delta_dropped_events =
476 dropped_events - opt_dropped_events_begin.value();
477 storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_delta, cpu,
478 delta_dropped_events);
479 }
480
481 auto opt_read_events_begin =
482 storage->GetIndexedStats(stats::ftrace_cpu_read_events_begin, cpu);
483 if (opt_read_events_begin) {
484 int64_t delta_read_events = read_events - opt_read_events_begin.value();
485 storage->SetIndexedStats(stats::ftrace_cpu_read_events_delta, cpu,
486 delta_read_events);
487 }
488 }
489
490 // oldest_event_ts can often be set to very high values, possibly because
491 // of wrapping. Ensure that we are not overflowing to avoid ubsan
492 // complaining.
493 double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
494 // NB: This comparison is correct only because of the >=, it would be
495 // incorrect with >. std::numeric_limits<int64_t>::max() converted to
496 // a double is the next value representable as a double that is *larger*
497 // than std::numeric_limits<int64_t>::max(). All values that are
498 // representable as doubles and < than that value are thus representable
499 // as int64_t.
500 if (oldest_event_ts >=
501 static_cast<double>(std::numeric_limits<int64_t>::max())) {
502 storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
503 cpu, std::numeric_limits<int64_t>::max());
504 } else {
505 storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
506 cpu, static_cast<int64_t>(oldest_event_ts));
507 }
508 }
509
510 // Compute atrace + ftrace setup errors. We do two things here:
511 // 1. We add up all the errors and put the counter in the stats table (which
512 // can hold only numerals).
513 // 2. We concatenate together all the errors in a string and put that in the
514 // medatata table.
515 // Both will be reported in the 'Info & stats' page in the UI.
516 if (is_start) {
517 if (seen_errors_for_sequence_id_.count(packet_sequence_id) == 0) {
518 std::string error_str;
519 for (auto it = evt.failed_ftrace_events(); it; ++it) {
520 storage->IncrementStats(stats::ftrace_setup_errors, 1);
521 error_str += "Ftrace event failed: " + it->as_std_string() + "\n";
522 }
523 for (auto it = evt.unknown_ftrace_events(); it; ++it) {
524 storage->IncrementStats(stats::ftrace_setup_errors, 1);
525 error_str += "Ftrace event unknown: " + it->as_std_string() + "\n";
526 }
527 if (evt.atrace_errors().size > 0) {
528 storage->IncrementStats(stats::ftrace_setup_errors, 1);
529 error_str += "Atrace failures: " + evt.atrace_errors().ToStdString();
530 }
531 if (!error_str.empty()) {
532 auto error_str_id = storage->InternString(base::StringView(error_str));
533 context_->metadata_tracker->AppendMetadata(
534 metadata::ftrace_setup_errors, Variadic::String(error_str_id));
535 seen_errors_for_sequence_id_.insert(packet_sequence_id);
536 }
537 }
538 if (evt.preserve_ftrace_buffer()) {
539 preserve_ftrace_buffer_ = true;
540 }
541 }
542 }
543
ParseFtraceEvent(uint32_t cpu,int64_t ts,const TracePacketData & data)544 util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
545 int64_t ts,
546 const TracePacketData& data) {
547 MaybeOnFirstFtraceEvent();
548 if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
549 context_->storage->IncrementStats(
550 stats::ftrace_packet_before_tracing_start);
551 return util::OkStatus();
552 }
553 using protos::pbzero::FtraceEvent;
554 const TraceBlobView& event = data.packet;
555 PacketSequenceStateGeneration* seq_state = data.sequence_state.get();
556 ProtoDecoder decoder(event.data(), event.length());
557 uint64_t raw_pid = 0;
558 bool no_pid = false;
559 if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
560 raw_pid = pid_field.as_uint64();
561 } else {
562 no_pid = true;
563 }
564 uint32_t pid = static_cast<uint32_t>(raw_pid);
565
566 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
567 bool is_metadata_field = fld.id() == FtraceEvent::kPidFieldNumber ||
568 fld.id() == FtraceEvent::kTimestampFieldNumber;
569 if (is_metadata_field)
570 continue;
571
572 // pKVM hypervisor events are recorded as ftrace events, however they are
573 // not associated with any pid. The rest of trace parsing logic for
574 // hypervisor events will use the pid 0.
575 if (no_pid && !PkvmHypervisorCpuTracker::IsPkvmHypervisorEvent(fld.id())) {
576 return util::ErrStatus("Pid field not found in ftrace packet");
577 }
578
579 ConstBytes fld_bytes = fld.as_bytes();
580 if (fld.id() == FtraceEvent::kGenericFieldNumber) {
581 ParseGenericFtrace(ts, cpu, pid, fld_bytes);
582 } else if (fld.id() != FtraceEvent::kSchedSwitchFieldNumber) {
583 // sched_switch parsing populates the raw table by itself
584 ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, fld_bytes, seq_state);
585 }
586
587 if (PkvmHypervisorCpuTracker::IsPkvmHypervisorEvent(fld.id())) {
588 pkvm_hyp_cpu_tracker_.ParseHypEvent(cpu, ts, fld.id(), fld_bytes);
589 }
590
591 switch (fld.id()) {
592 case FtraceEvent::kSchedSwitchFieldNumber: {
593 ParseSchedSwitch(cpu, ts, fld_bytes);
594 break;
595 }
596 case FtraceEvent::kSchedWakingFieldNumber: {
597 ParseSchedWaking(ts, pid, fld_bytes);
598 break;
599 }
600 case FtraceEvent::kSchedProcessFreeFieldNumber: {
601 ParseSchedProcessFree(ts, fld_bytes);
602 break;
603 }
604 case FtraceEvent::kCpuFrequencyFieldNumber: {
605 ParseCpuFreq(ts, fld_bytes);
606 break;
607 }
608 case FtraceEvent::kGpuFrequencyFieldNumber: {
609 ParseGpuFreq(ts, fld_bytes);
610 break;
611 }
612 case FtraceEvent::kCpuIdleFieldNumber: {
613 ParseCpuIdle(ts, fld_bytes);
614 break;
615 }
616 case FtraceEvent::kPrintFieldNumber: {
617 ParsePrint(ts, pid, fld_bytes);
618 break;
619 }
620 case FtraceEvent::kZeroFieldNumber: {
621 ParseZero(ts, pid, fld_bytes);
622 break;
623 }
624 case FtraceEvent::kRssStatThrottledFieldNumber:
625 case FtraceEvent::kRssStatFieldNumber: {
626 rss_stat_tracker_.ParseRssStat(ts, fld.id(), pid, fld_bytes);
627 break;
628 }
629 case FtraceEvent::kIonHeapGrowFieldNumber: {
630 ParseIonHeapGrowOrShrink(ts, pid, fld_bytes, true);
631 break;
632 }
633 case FtraceEvent::kIonHeapShrinkFieldNumber: {
634 ParseIonHeapGrowOrShrink(ts, pid, fld_bytes, false);
635 break;
636 }
637 case FtraceEvent::kIonStatFieldNumber: {
638 ParseIonStat(ts, pid, fld_bytes);
639 break;
640 }
641 case FtraceEvent::kDmaHeapStatFieldNumber: {
642 ParseDmaHeapStat(ts, pid, fld_bytes);
643 break;
644 }
645 case FtraceEvent::kSignalGenerateFieldNumber: {
646 ParseSignalGenerate(ts, fld_bytes);
647 break;
648 }
649 case FtraceEvent::kSignalDeliverFieldNumber: {
650 ParseSignalDeliver(ts, pid, fld_bytes);
651 break;
652 }
653 case FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
654 ParseOOMScoreAdjUpdate(ts, fld_bytes);
655 break;
656 }
657 case FtraceEvent::kMarkVictimFieldNumber: {
658 ParseOOMKill(ts, fld_bytes);
659 break;
660 }
661 case FtraceEvent::kMmEventRecordFieldNumber: {
662 ParseMmEventRecord(ts, pid, fld_bytes);
663 break;
664 }
665 case FtraceEvent::kSysEnterFieldNumber: {
666 ParseSysEnterEvent(ts, pid, fld_bytes);
667 break;
668 }
669 case FtraceEvent::kSysExitFieldNumber: {
670 ParseSysExitEvent(ts, pid, fld_bytes);
671 break;
672 }
673 case FtraceEvent::kTaskNewtaskFieldNumber: {
674 ParseTaskNewTask(ts, pid, fld_bytes);
675 break;
676 }
677 case FtraceEvent::kTaskRenameFieldNumber: {
678 ParseTaskRename(fld_bytes);
679 break;
680 }
681 case FtraceEvent::kBinderTransactionFieldNumber: {
682 ParseBinderTransaction(ts, pid, fld_bytes);
683 break;
684 }
685 case FtraceEvent::kBinderTransactionReceivedFieldNumber: {
686 ParseBinderTransactionReceived(ts, pid, fld_bytes);
687 break;
688 }
689 case FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
690 ParseBinderTransactionAllocBuf(ts, pid, fld_bytes);
691 break;
692 }
693 case FtraceEvent::kBinderLockFieldNumber: {
694 ParseBinderLock(ts, pid, fld_bytes);
695 break;
696 }
697 case FtraceEvent::kBinderUnlockFieldNumber: {
698 ParseBinderUnlock(ts, pid, fld_bytes);
699 break;
700 }
701 case FtraceEvent::kBinderLockedFieldNumber: {
702 ParseBinderLocked(ts, pid, fld_bytes);
703 break;
704 }
705 case FtraceEvent::kSdeTracingMarkWriteFieldNumber: {
706 ParseSdeTracingMarkWrite(ts, pid, fld_bytes);
707 break;
708 }
709 case FtraceEvent::kClockSetRateFieldNumber: {
710 ParseClockSetRate(ts, fld_bytes);
711 break;
712 }
713 case FtraceEvent::kClockEnableFieldNumber: {
714 ParseClockEnable(ts, fld_bytes);
715 break;
716 }
717 case FtraceEvent::kClockDisableFieldNumber: {
718 ParseClockDisable(ts, fld_bytes);
719 break;
720 }
721 case FtraceEvent::kScmCallStartFieldNumber: {
722 ParseScmCallStart(ts, pid, fld_bytes);
723 break;
724 }
725 case FtraceEvent::kScmCallEndFieldNumber: {
726 ParseScmCallEnd(ts, pid, fld_bytes);
727 break;
728 }
729 case FtraceEvent::kCmaAllocStartFieldNumber: {
730 ParseCmaAllocStart(ts, pid);
731 break;
732 }
733 case FtraceEvent::kCmaAllocInfoFieldNumber: {
734 ParseCmaAllocInfo(ts, pid, fld_bytes);
735 break;
736 }
737 case FtraceEvent::kMmVmscanDirectReclaimBeginFieldNumber: {
738 ParseDirectReclaimBegin(ts, pid, fld_bytes);
739 break;
740 }
741 case FtraceEvent::kMmVmscanDirectReclaimEndFieldNumber: {
742 ParseDirectReclaimEnd(ts, pid, fld_bytes);
743 break;
744 }
745 case FtraceEvent::kMmShrinkSlabStartFieldNumber: {
746 ParseShrinkSlabStart(ts, pid, fld_bytes, seq_state);
747 break;
748 }
749 case FtraceEvent::kMmShrinkSlabEndFieldNumber: {
750 ParseShrinkSlabEnd(ts, pid, fld_bytes);
751 break;
752 }
753 case FtraceEvent::kWorkqueueExecuteStartFieldNumber: {
754 ParseWorkqueueExecuteStart(cpu, ts, pid, fld_bytes, seq_state);
755 break;
756 }
757 case FtraceEvent::kWorkqueueExecuteEndFieldNumber: {
758 ParseWorkqueueExecuteEnd(ts, pid, fld_bytes);
759 break;
760 }
761 case FtraceEvent::kIrqHandlerEntryFieldNumber: {
762 ParseIrqHandlerEntry(cpu, ts, fld_bytes);
763 break;
764 }
765 case FtraceEvent::kIrqHandlerExitFieldNumber: {
766 ParseIrqHandlerExit(cpu, ts, fld_bytes);
767 break;
768 }
769 case FtraceEvent::kSoftirqEntryFieldNumber: {
770 ParseSoftIrqEntry(cpu, ts, fld_bytes);
771 break;
772 }
773 case FtraceEvent::kSoftirqExitFieldNumber: {
774 ParseSoftIrqExit(cpu, ts, fld_bytes);
775 break;
776 }
777 case FtraceEvent::kGpuMemTotalFieldNumber: {
778 ParseGpuMemTotal(ts, fld_bytes);
779 break;
780 }
781 case FtraceEvent::kThermalTemperatureFieldNumber: {
782 ParseThermalTemperature(ts, fld_bytes);
783 break;
784 }
785 case FtraceEvent::kCdevUpdateFieldNumber: {
786 ParseCdevUpdate(ts, fld_bytes);
787 break;
788 }
789 case FtraceEvent::kSchedBlockedReasonFieldNumber: {
790 ParseSchedBlockedReason(fld_bytes, seq_state);
791 break;
792 }
793 case FtraceEvent::kFastrpcDmaStatFieldNumber: {
794 ParseFastRpcDmaStat(ts, pid, fld_bytes);
795 break;
796 }
797 case FtraceEvent::kG2dTracingMarkWriteFieldNumber: {
798 ParseG2dTracingMarkWrite(ts, pid, fld_bytes);
799 break;
800 }
801 case FtraceEvent::kDpuTracingMarkWriteFieldNumber: {
802 ParseDpuTracingMarkWrite(ts, pid, fld_bytes);
803 break;
804 }
805 case FtraceEvent::kMaliTracingMarkWriteFieldNumber: {
806 ParseMaliTracingMarkWrite(ts, pid, fld_bytes);
807 break;
808 }
809 case FtraceEvent::kLwisTracingMarkWriteFieldNumber: {
810 ParseLwisTracingMarkWrite(ts, pid, fld_bytes);
811 break;
812 }
813 case FtraceEvent::kVirtioGpuCmdQueueFieldNumber:
814 case FtraceEvent::kVirtioGpuCmdResponseFieldNumber: {
815 virtio_gpu_tracker_.ParseVirtioGpu(ts, fld.id(), pid, fld_bytes);
816 break;
817 }
818 case FtraceEvent::kCpuhpPauseFieldNumber: {
819 ParseCpuhpPause(ts, pid, fld_bytes);
820 break;
821 }
822 case FtraceEvent::kNetifReceiveSkbFieldNumber: {
823 ParseNetifReceiveSkb(cpu, ts, fld_bytes);
824 break;
825 }
826 case FtraceEvent::kNetDevXmitFieldNumber: {
827 ParseNetDevXmit(cpu, ts, fld_bytes);
828 break;
829 }
830 case FtraceEvent::kInetSockSetStateFieldNumber: {
831 ParseInetSockSetState(ts, pid, fld_bytes);
832 break;
833 }
834 case FtraceEvent::kTcpRetransmitSkbFieldNumber: {
835 ParseTcpRetransmitSkb(ts, fld_bytes);
836 break;
837 }
838 case FtraceEvent::kNapiGroReceiveEntryFieldNumber: {
839 ParseNapiGroReceiveEntry(cpu, ts, fld_bytes);
840 break;
841 }
842 case FtraceEvent::kNapiGroReceiveExitFieldNumber: {
843 ParseNapiGroReceiveExit(cpu, ts, fld_bytes);
844 break;
845 }
846 case FtraceEvent::kCpuFrequencyLimitsFieldNumber: {
847 ParseCpuFrequencyLimits(ts, fld_bytes);
848 break;
849 }
850 case FtraceEvent::kKfreeSkbFieldNumber: {
851 ParseKfreeSkb(ts, fld_bytes);
852 break;
853 }
854 case FtraceEvent::kCrosEcSensorhubDataFieldNumber: {
855 ParseCrosEcSensorhubData(ts, fld_bytes);
856 break;
857 }
858 case FtraceEvent::kUfshcdCommandFieldNumber: {
859 ParseUfshcdCommand(ts, fld_bytes);
860 break;
861 }
862 case FtraceEvent::kWakeupSourceActivateFieldNumber: {
863 ParseWakeSourceActivate(ts, fld_bytes);
864 break;
865 }
866 case FtraceEvent::kWakeupSourceDeactivateFieldNumber: {
867 ParseWakeSourceDeactivate(ts, fld_bytes);
868 break;
869 }
870 case FtraceEvent::kUfshcdClkGatingFieldNumber: {
871 ParseUfshcdClkGating(ts, fld_bytes);
872 break;
873 }
874 case FtraceEvent::kSuspendResumeFieldNumber: {
875 ParseSuspendResume(ts, fld_bytes);
876 break;
877 }
878 case FtraceEvent::kSuspendResumeMinimalFieldNumber: {
879 ParseSuspendResumeMinimal(ts, fld_bytes);
880 break;
881 }
882 case FtraceEvent::kDrmVblankEventFieldNumber:
883 case FtraceEvent::kDrmVblankEventDeliveredFieldNumber:
884 case FtraceEvent::kDrmSchedJobFieldNumber:
885 case FtraceEvent::kDrmRunJobFieldNumber:
886 case FtraceEvent::kDrmSchedProcessJobFieldNumber:
887 case FtraceEvent::kDmaFenceInitFieldNumber:
888 case FtraceEvent::kDmaFenceEmitFieldNumber:
889 case FtraceEvent::kDmaFenceSignaledFieldNumber:
890 case FtraceEvent::kDmaFenceWaitStartFieldNumber:
891 case FtraceEvent::kDmaFenceWaitEndFieldNumber: {
892 drm_tracker_.ParseDrm(ts, fld.id(), pid, fld_bytes);
893 break;
894 }
895 case FtraceEvent::kF2fsIostatFieldNumber: {
896 iostat_tracker_.ParseF2fsIostat(ts, fld_bytes);
897 break;
898 }
899 case FtraceEvent::kF2fsIostatLatencyFieldNumber: {
900 iostat_tracker_.ParseF2fsIostatLatency(ts, fld_bytes);
901 break;
902 }
903 case FtraceEvent::kSchedCpuUtilCfsFieldNumber: {
904 ParseSchedCpuUtilCfs(ts, fld_bytes);
905 break;
906 }
907 case FtraceEvent::kI2cReadFieldNumber: {
908 ParseI2cReadEvent(ts, pid, fld_bytes);
909 break;
910 }
911 case FtraceEvent::kI2cWriteFieldNumber: {
912 ParseI2cWriteEvent(ts, pid, fld_bytes);
913 break;
914 }
915 case FtraceEvent::kI2cResultFieldNumber: {
916 ParseI2cResultEvent(ts, pid, fld_bytes);
917 break;
918 }
919 case FtraceEvent::kFuncgraphEntryFieldNumber: {
920 ParseFuncgraphEntry(ts, pid, fld_bytes, seq_state);
921 break;
922 }
923 case FtraceEvent::kFuncgraphExitFieldNumber: {
924 ParseFuncgraphExit(ts, pid, fld_bytes, seq_state);
925 break;
926 }
927 case FtraceEvent::kV4l2QbufFieldNumber:
928 case FtraceEvent::kV4l2DqbufFieldNumber:
929 case FtraceEvent::kVb2V4l2BufQueueFieldNumber:
930 case FtraceEvent::kVb2V4l2BufDoneFieldNumber:
931 case FtraceEvent::kVb2V4l2QbufFieldNumber:
932 case FtraceEvent::kVb2V4l2DqbufFieldNumber: {
933 V4l2Tracker::GetOrCreate(context_)->ParseV4l2Event(fld.id(), ts, pid,
934 fld_bytes);
935 break;
936 }
937 case FtraceEvent::kVirtioVideoCmdFieldNumber:
938 case FtraceEvent::kVirtioVideoCmdDoneFieldNumber:
939 case FtraceEvent::kVirtioVideoResourceQueueFieldNumber:
940 case FtraceEvent::kVirtioVideoResourceQueueDoneFieldNumber: {
941 VirtioVideoTracker::GetOrCreate(context_)->ParseVirtioVideoEvent(
942 fld.id(), ts, fld_bytes);
943 break;
944 }
945 case FtraceEvent::kTrustySmcFieldNumber: {
946 ParseTrustySmc(pid, ts, fld_bytes);
947 break;
948 }
949 case FtraceEvent::kTrustySmcDoneFieldNumber: {
950 ParseTrustySmcDone(pid, ts, fld_bytes);
951 break;
952 }
953 case FtraceEvent::kTrustyStdCall32FieldNumber: {
954 ParseTrustyStdCall32(pid, ts, fld_bytes);
955 break;
956 }
957 case FtraceEvent::kTrustyStdCall32DoneFieldNumber: {
958 ParseTrustyStdCall32Done(pid, ts, fld_bytes);
959 break;
960 }
961 case FtraceEvent::kTrustyShareMemoryFieldNumber: {
962 ParseTrustyShareMemory(pid, ts, fld_bytes);
963 break;
964 }
965 case FtraceEvent::kTrustyShareMemoryDoneFieldNumber: {
966 ParseTrustyShareMemoryDone(pid, ts, fld_bytes);
967 break;
968 }
969 case FtraceEvent::kTrustyReclaimMemoryFieldNumber: {
970 ParseTrustyReclaimMemory(pid, ts, fld_bytes);
971 break;
972 }
973 case FtraceEvent::kTrustyReclaimMemoryDoneFieldNumber: {
974 ParseTrustyReclaimMemoryDone(pid, ts, fld_bytes);
975 break;
976 }
977 case FtraceEvent::kTrustyIrqFieldNumber: {
978 ParseTrustyIrq(pid, ts, fld_bytes);
979 break;
980 }
981 case FtraceEvent::kTrustyIpcHandleEventFieldNumber: {
982 ParseTrustyIpcHandleEvent(pid, ts, fld_bytes);
983 break;
984 }
985 case FtraceEvent::kTrustyIpcConnectFieldNumber: {
986 ParseTrustyIpcConnect(pid, ts, fld_bytes);
987 break;
988 }
989 case FtraceEvent::kTrustyIpcConnectEndFieldNumber: {
990 ParseTrustyIpcConnectEnd(pid, ts, fld_bytes);
991 break;
992 }
993 case FtraceEvent::kTrustyIpcWriteFieldNumber: {
994 ParseTrustyIpcWrite(pid, ts, fld_bytes);
995 break;
996 }
997 case FtraceEvent::kTrustyIpcReadFieldNumber: {
998 ParseTrustyIpcRead(pid, ts, fld_bytes);
999 break;
1000 }
1001 case FtraceEvent::kTrustyIpcReadEndFieldNumber: {
1002 ParseTrustyIpcReadEnd(pid, ts, fld_bytes);
1003 break;
1004 }
1005 case FtraceEvent::kTrustyIpcPollFieldNumber: {
1006 ParseTrustyIpcPoll(pid, ts, fld_bytes);
1007 break;
1008 }
1009 case FtraceEvent::kTrustyIpcRxFieldNumber: {
1010 ParseTrustyIpcRx(pid, ts, fld_bytes);
1011 break;
1012 }
1013 case FtraceEvent::kTrustyEnqueueNopFieldNumber: {
1014 ParseTrustyEnqueueNop(pid, ts, fld_bytes);
1015 break;
1016 }
1017 case FtraceEvent::kMaliMaliKCPUCQSSETFieldNumber:
1018 case FtraceEvent::kMaliMaliKCPUCQSWAITSTARTFieldNumber:
1019 case FtraceEvent::kMaliMaliKCPUCQSWAITENDFieldNumber:
1020 case FtraceEvent::kMaliMaliKCPUFENCESIGNALFieldNumber:
1021 case FtraceEvent::kMaliMaliKCPUFENCEWAITSTARTFieldNumber:
1022 case FtraceEvent::kMaliMaliKCPUFENCEWAITENDFieldNumber: {
1023 mali_gpu_event_tracker_.ParseMaliGpuEvent(ts, fld.id(), pid);
1024 break;
1025 }
1026 case FtraceEvent::kMaliMaliCSFINTERRUPTSTARTFieldNumber:
1027 case FtraceEvent::kMaliMaliCSFINTERRUPTENDFieldNumber: {
1028 mali_gpu_event_tracker_.ParseMaliGpuIrqEvent(ts, fld.id(), cpu,
1029 fld_bytes);
1030 break;
1031 }
1032
1033 default:
1034 break;
1035 }
1036 }
1037
1038 PERFETTO_DCHECK(!decoder.bytes_left());
1039 return util::OkStatus();
1040 }
ParseInlineSchedSwitch(uint32_t cpu,int64_t ts,const InlineSchedSwitch & data)1041 util::Status FtraceParser::ParseInlineSchedSwitch(
1042 uint32_t cpu,
1043 int64_t ts,
1044 const InlineSchedSwitch& data) {
1045 MaybeOnFirstFtraceEvent();
1046 if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
1047 context_->storage->IncrementStats(
1048 stats::ftrace_packet_before_tracing_start);
1049 return util::OkStatus();
1050 }
1051
1052 using protos::pbzero::FtraceEvent;
1053 SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
1054 sched_tracker->PushSchedSwitchCompact(cpu, ts, data.prev_state,
1055 static_cast<uint32_t>(data.next_pid),
1056 data.next_prio, data.next_comm);
1057 return util::OkStatus();
1058 }
1059
ParseInlineSchedWaking(uint32_t cpu,int64_t ts,const InlineSchedWaking & data)1060 util::Status FtraceParser::ParseInlineSchedWaking(
1061 uint32_t cpu,
1062 int64_t ts,
1063 const InlineSchedWaking& data) {
1064 MaybeOnFirstFtraceEvent();
1065 if (PERFETTO_UNLIKELY(ts < drop_ftrace_data_before_ts_)) {
1066 context_->storage->IncrementStats(
1067 stats::ftrace_packet_before_tracing_start);
1068 return util::OkStatus();
1069 }
1070 using protos::pbzero::FtraceEvent;
1071 SchedEventTracker* sched_tracker = SchedEventTracker::GetOrCreate(context_);
1072 sched_tracker->PushSchedWakingCompact(cpu, ts,
1073 static_cast<uint32_t>(data.pid),
1074 data.target_cpu, data.prio, data.comm);
1075 return util::OkStatus();
1076 }
1077
MaybeOnFirstFtraceEvent()1078 void FtraceParser::MaybeOnFirstFtraceEvent() {
1079 if (PERFETTO_LIKELY(has_seen_first_ftrace_packet_)) {
1080 return;
1081 }
1082
1083 DropFtraceDataBefore drop_before =
1084 preserve_ftrace_buffer_ ? DropFtraceDataBefore::kNoDrop
1085 : context_->config.drop_ftrace_data_before;
1086 switch (drop_before) {
1087 case DropFtraceDataBefore::kNoDrop: {
1088 drop_ftrace_data_before_ts_ = 0;
1089 break;
1090 }
1091 case DropFtraceDataBefore::kAllDataSourcesStarted:
1092 case DropFtraceDataBefore::kTracingStarted: {
1093 metadata::KeyId event_key =
1094 drop_before == DropFtraceDataBefore::kAllDataSourcesStarted
1095 ? metadata::all_data_source_started_ns
1096 : metadata::tracing_started_ns;
1097 const auto& metadata = context_->storage->metadata_table();
1098 std::optional<uint32_t> opt_row =
1099 metadata.name().IndexOf(metadata::kNames[event_key]);
1100 if (opt_row) {
1101 drop_ftrace_data_before_ts_ = *metadata.int_value()[*opt_row];
1102 }
1103 break;
1104 }
1105 }
1106 has_seen_first_ftrace_packet_ = true;
1107 }
1108
ParseGenericFtrace(int64_t ts,uint32_t cpu,uint32_t tid,ConstBytes blob)1109 void FtraceParser::ParseGenericFtrace(int64_t ts,
1110 uint32_t cpu,
1111 uint32_t tid,
1112 ConstBytes blob) {
1113 protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
1114 StringId event_id = context_->storage->InternString(evt.event_name());
1115 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1116 RawId id = context_->storage->mutable_ftrace_event_table()
1117 ->Insert({ts, event_id, cpu, utid})
1118 .id;
1119 auto inserter = context_->args_tracker->AddArgsTo(id);
1120
1121 for (auto it = evt.field(); it; ++it) {
1122 protos::pbzero::GenericFtraceEvent::Field::Decoder fld(*it);
1123 auto field_name_id = context_->storage->InternString(fld.name());
1124 if (fld.has_int_value()) {
1125 inserter.AddArg(field_name_id, Variadic::Integer(fld.int_value()));
1126 } else if (fld.has_uint_value()) {
1127 inserter.AddArg(
1128 field_name_id,
1129 Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
1130 } else if (fld.has_str_value()) {
1131 StringId str_value = context_->storage->InternString(fld.str_value());
1132 inserter.AddArg(field_name_id, Variadic::String(str_value));
1133 }
1134 }
1135 }
1136
ParseTypedFtraceToRaw(uint32_t ftrace_id,int64_t timestamp,uint32_t cpu,uint32_t tid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)1137 void FtraceParser::ParseTypedFtraceToRaw(
1138 uint32_t ftrace_id,
1139 int64_t timestamp,
1140 uint32_t cpu,
1141 uint32_t tid,
1142 ConstBytes blob,
1143 PacketSequenceStateGeneration* seq_state) {
1144 if (PERFETTO_UNLIKELY(!context_->config.ingest_ftrace_in_raw_table))
1145 return;
1146
1147 ProtoDecoder decoder(blob.data, blob.size);
1148 if (ftrace_id >= GetDescriptorsSize()) {
1149 PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
1150 ftrace_id);
1151 return;
1152 }
1153
1154 FtraceMessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
1155 const auto& message_strings = ftrace_message_strings_[ftrace_id];
1156 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1157 RawId id =
1158 context_->storage->mutable_ftrace_event_table()
1159 ->Insert({timestamp, message_strings.message_name_id, cpu, utid})
1160 .id;
1161 auto inserter = context_->args_tracker->AddArgsTo(id);
1162
1163 for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
1164 uint16_t field_id = fld.id();
1165 if (PERFETTO_UNLIKELY(field_id >= kMaxFtraceEventFields)) {
1166 PERFETTO_DLOG(
1167 "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
1168 field_id);
1169 continue;
1170 }
1171
1172 ProtoSchemaType type = m->fields[field_id].type;
1173 StringId name_id = message_strings.field_name_ids[field_id];
1174
1175 // Check if this field represents a kernel function.
1176 auto it = std::find_if(
1177 kKernelFunctionFields.begin(), kKernelFunctionFields.end(),
1178 [ftrace_id, field_id](const FtraceEventAndFieldId& ev) {
1179 return ev.event_id == ftrace_id && ev.field_id == field_id;
1180 });
1181 if (it != kKernelFunctionFields.end()) {
1182 PERFETTO_CHECK(type == ProtoSchemaType::kUint64);
1183
1184 auto* interned_string = seq_state->LookupInternedMessage<
1185 protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
1186 protos::pbzero::InternedString>(fld.as_uint64());
1187
1188 // If we don't have the string for this field (can happen if
1189 // symbolization wasn't enabled, if reading the symbols errored out or
1190 // on legacy traces) then just add the field as a normal arg.
1191 if (interned_string) {
1192 protozero::ConstBytes str = interned_string->str();
1193 StringId str_id = context_->storage->InternString(base::StringView(
1194 reinterpret_cast<const char*>(str.data), str.size));
1195 inserter.AddArg(name_id, Variadic::String(str_id));
1196 continue;
1197 }
1198 }
1199
1200 switch (type) {
1201 case ProtoSchemaType::kInt32:
1202 case ProtoSchemaType::kInt64:
1203 case ProtoSchemaType::kSfixed32:
1204 case ProtoSchemaType::kSfixed64:
1205 case ProtoSchemaType::kSint32:
1206 case ProtoSchemaType::kSint64:
1207 case ProtoSchemaType::kBool:
1208 case ProtoSchemaType::kEnum: {
1209 inserter.AddArg(name_id, Variadic::Integer(fld.as_int64()));
1210 break;
1211 }
1212 case ProtoSchemaType::kUint32:
1213 case ProtoSchemaType::kUint64:
1214 case ProtoSchemaType::kFixed32:
1215 case ProtoSchemaType::kFixed64: {
1216 // Note that SQLite functions will still treat unsigned values
1217 // as a signed 64 bit integers (but the translation back to ftrace
1218 // refers to this storage directly).
1219 inserter.AddArg(name_id, Variadic::UnsignedInteger(fld.as_uint64()));
1220 break;
1221 }
1222 case ProtoSchemaType::kString:
1223 case ProtoSchemaType::kBytes: {
1224 StringId value = context_->storage->InternString(fld.as_string());
1225 inserter.AddArg(name_id, Variadic::String(value));
1226 break;
1227 }
1228 case ProtoSchemaType::kDouble: {
1229 inserter.AddArg(name_id, Variadic::Real(fld.as_double()));
1230 break;
1231 }
1232 case ProtoSchemaType::kFloat: {
1233 inserter.AddArg(name_id,
1234 Variadic::Real(static_cast<double>(fld.as_float())));
1235 break;
1236 }
1237 case ProtoSchemaType::kUnknown:
1238 case ProtoSchemaType::kGroup:
1239 case ProtoSchemaType::kMessage:
1240 PERFETTO_DLOG("Could not store %s as a field in args table.",
1241 ProtoSchemaToString(type));
1242 break;
1243 }
1244 }
1245 }
1246
1247 PERFETTO_ALWAYS_INLINE
ParseSchedSwitch(uint32_t cpu,int64_t timestamp,ConstBytes blob)1248 void FtraceParser::ParseSchedSwitch(uint32_t cpu,
1249 int64_t timestamp,
1250 ConstBytes blob) {
1251 protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
1252 uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
1253 uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
1254 SchedEventTracker::GetOrCreate(context_)->PushSchedSwitch(
1255 cpu, timestamp, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
1256 next_pid, ss.next_comm(), ss.next_prio());
1257 }
1258
ParseSchedWaking(int64_t timestamp,uint32_t pid,ConstBytes blob)1259 void FtraceParser::ParseSchedWaking(int64_t timestamp,
1260 uint32_t pid,
1261 ConstBytes blob) {
1262 protos::pbzero::SchedWakingFtraceEvent::Decoder sw(blob.data, blob.size);
1263 uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
1264 StringId name_id = context_->storage->InternString(sw.comm());
1265 auto wakee_utid = context_->process_tracker->UpdateThreadName(
1266 wakee_pid, name_id, ThreadNamePriority::kFtrace);
1267 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1268 ThreadStateTracker::GetOrCreate(context_)->PushWakingEvent(timestamp,
1269 wakee_utid, utid);
1270 }
1271
ParseSchedProcessFree(int64_t timestamp,ConstBytes blob)1272 void FtraceParser::ParseSchedProcessFree(int64_t timestamp, ConstBytes blob) {
1273 protos::pbzero::SchedProcessFreeFtraceEvent::Decoder ex(blob.data, blob.size);
1274 uint32_t pid = static_cast<uint32_t>(ex.pid());
1275 context_->process_tracker->EndThread(timestamp, pid);
1276 }
1277
ParseCpuFreq(int64_t timestamp,ConstBytes blob)1278 void FtraceParser::ParseCpuFreq(int64_t timestamp, ConstBytes blob) {
1279 protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
1280 uint32_t cpu = freq.cpu_id();
1281 uint32_t new_freq = freq.state();
1282 TrackId track =
1283 context_->track_tracker->InternCpuCounterTrack(cpu_freq_name_id_, cpu);
1284 context_->event_tracker->PushCounter(timestamp, new_freq, track);
1285 }
1286
ParseGpuFreq(int64_t timestamp,ConstBytes blob)1287 void FtraceParser::ParseGpuFreq(int64_t timestamp, ConstBytes blob) {
1288 protos::pbzero::GpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
1289 uint32_t gpu = freq.gpu_id();
1290 uint32_t new_freq = freq.state();
1291 TrackId track =
1292 context_->track_tracker->InternGpuCounterTrack(gpu_freq_name_id_, gpu);
1293 context_->event_tracker->PushCounter(timestamp, new_freq, track);
1294 }
1295
ParseCpuIdle(int64_t timestamp,ConstBytes blob)1296 void FtraceParser::ParseCpuIdle(int64_t timestamp, ConstBytes blob) {
1297 protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
1298 uint32_t cpu = idle.cpu_id();
1299 uint32_t new_state = idle.state();
1300 TrackId track =
1301 context_->track_tracker->InternCpuCounterTrack(cpu_idle_name_id_, cpu);
1302 context_->event_tracker->PushCounter(timestamp, new_state, track);
1303 }
1304
ParsePrint(int64_t timestamp,uint32_t pid,ConstBytes blob)1305 void FtraceParser::ParsePrint(int64_t timestamp,
1306 uint32_t pid,
1307 ConstBytes blob) {
1308 // Atrace slices are emitted as begin/end events written into the tracefs
1309 // trace_marker. If we're tracing syscalls, the reconstructed atrace slice
1310 // would start and end in the middle of different sys_write slices (on the
1311 // same track). Since trace_processor enforces strict slice nesting, we need
1312 // to resolve this conflict. The chosen approach is to distort the data, and
1313 // pretend that the write syscall ended at the atrace slice's boundary.
1314 //
1315 // In other words, this true structure:
1316 // [write...].....[write...]
1317 // ....[atrace_slice..].....
1318 //
1319 // Is turned into:
1320 // [wr][atrace_slice..]
1321 // ...............[wri]
1322 //
1323 std::optional<UniqueTid> opt_utid =
1324 context_->process_tracker->GetThreadOrNull(pid);
1325 if (opt_utid) {
1326 SyscallTracker::GetOrCreate(context_)->MaybeTruncateOngoingWriteSlice(
1327 timestamp, *opt_utid);
1328 }
1329
1330 protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
1331 SystraceParser::GetOrCreate(context_)->ParsePrintEvent(timestamp, pid,
1332 evt.buf());
1333 }
1334
ParseZero(int64_t timestamp,uint32_t pid,ConstBytes blob)1335 void FtraceParser::ParseZero(int64_t timestamp, uint32_t pid, ConstBytes blob) {
1336 protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
1337 uint32_t tgid = static_cast<uint32_t>(evt.pid());
1338 SystraceParser::GetOrCreate(context_)->ParseZeroEvent(
1339 timestamp, pid, evt.flag(), evt.name(), tgid, evt.value());
1340 }
1341
ParseSdeTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1342 void FtraceParser::ParseSdeTracingMarkWrite(int64_t timestamp,
1343 uint32_t pid,
1344 ConstBytes blob) {
1345 protos::pbzero::SdeTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1346 blob.size);
1347 if (!evt.has_trace_type() && !evt.has_trace_begin()) {
1348 context_->storage->IncrementStats(stats::systrace_parse_failure);
1349 return;
1350 }
1351
1352 uint32_t tgid = static_cast<uint32_t>(evt.pid());
1353 SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1354 timestamp, pid, static_cast<char>(evt.trace_type()), evt.trace_begin(),
1355 evt.trace_name(), tgid, evt.value());
1356 }
1357
ParseDpuTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1358 void FtraceParser::ParseDpuTracingMarkWrite(int64_t timestamp,
1359 uint32_t pid,
1360 ConstBytes blob) {
1361 protos::pbzero::DpuTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1362 blob.size);
1363 if (!evt.type()) {
1364 context_->storage->IncrementStats(stats::systrace_parse_failure);
1365 return;
1366 }
1367
1368 uint32_t tgid = static_cast<uint32_t>(evt.pid());
1369 SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1370 timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1371 evt.name(), tgid, evt.value());
1372 }
1373
ParseG2dTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1374 void FtraceParser::ParseG2dTracingMarkWrite(int64_t timestamp,
1375 uint32_t pid,
1376 ConstBytes blob) {
1377 protos::pbzero::G2dTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1378 blob.size);
1379 if (!evt.type()) {
1380 context_->storage->IncrementStats(stats::systrace_parse_failure);
1381 return;
1382 }
1383
1384 uint32_t tgid = static_cast<uint32_t>(evt.pid());
1385 SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1386 timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1387 evt.name(), tgid, evt.value());
1388 }
1389
ParseMaliTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1390 void FtraceParser::ParseMaliTracingMarkWrite(int64_t timestamp,
1391 uint32_t pid,
1392 ConstBytes blob) {
1393 protos::pbzero::MaliTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1394 blob.size);
1395 if (!evt.type()) {
1396 context_->storage->IncrementStats(stats::systrace_parse_failure);
1397 return;
1398 }
1399
1400 uint32_t tgid = static_cast<uint32_t>(evt.pid());
1401 SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1402 timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1403 evt.name(), tgid, evt.value());
1404 }
1405
ParseLwisTracingMarkWrite(int64_t timestamp,uint32_t pid,ConstBytes blob)1406 void FtraceParser::ParseLwisTracingMarkWrite(int64_t timestamp,
1407 uint32_t pid,
1408 ConstBytes blob) {
1409 protos::pbzero::LwisTracingMarkWriteFtraceEvent::Decoder evt(blob.data,
1410 blob.size);
1411 if (!evt.type()) {
1412 context_->storage->IncrementStats(stats::systrace_parse_failure);
1413 return;
1414 }
1415
1416 uint32_t tgid = static_cast<uint32_t>(evt.pid());
1417 SystraceParser::GetOrCreate(context_)->ParseKernelTracingMarkWrite(
1418 timestamp, pid, static_cast<char>(evt.type()), false /*trace_begin*/,
1419 evt.func_name(), tgid, evt.value());
1420 }
1421
1422 /** Parses ion heap events present in Pixel kernels. */
ParseIonHeapGrowOrShrink(int64_t timestamp,uint32_t pid,ConstBytes blob,bool grow)1423 void FtraceParser::ParseIonHeapGrowOrShrink(int64_t timestamp,
1424 uint32_t pid,
1425 ConstBytes blob,
1426 bool grow) {
1427 protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
1428 int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
1429 // The total_allocated ftrace event reports the value before the
1430 // atomic_long_add / sub takes place.
1431 int64_t total_bytes = ion.total_allocated() + change_bytes;
1432 StringId global_name_id = ion_total_unknown_id_;
1433 StringId change_name_id = ion_change_unknown_id_;
1434
1435 if (ion.has_heap_name()) {
1436 base::StringView heap_name = ion.heap_name();
1437 base::StackString<255> ion_name("mem.ion.%.*s", int(heap_name.size()),
1438 heap_name.data());
1439 global_name_id = context_->storage->InternString(ion_name.string_view());
1440
1441 base::StackString<255> change_name("mem.ion_change.%.*s",
1442 int(heap_name.size()), heap_name.data());
1443 change_name_id = context_->storage->InternString(change_name.string_view());
1444 }
1445
1446 // Push the global counter.
1447 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1448 TrackTracker::Group::kMemory, global_name_id);
1449 context_->event_tracker->PushCounter(timestamp,
1450 static_cast<double>(total_bytes), track);
1451
1452 // Push the change counter.
1453 // TODO(b/121331269): these should really be instant events.
1454 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1455 track =
1456 context_->track_tracker->InternThreadCounterTrack(change_name_id, utid);
1457 context_->event_tracker->PushCounter(
1458 timestamp, static_cast<double>(change_bytes), track);
1459
1460 // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
1461 // It is fine as the arguments are the same, but we need to be sure that the
1462 // protobuf field id for both are the same.
1463 static_assert(
1464 static_cast<int>(
1465 protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
1466 static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
1467 kTotalAllocatedFieldNumber) &&
1468 static_cast<int>(
1469 protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
1470 static_cast<int>(
1471 protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
1472 static_cast<int>(
1473 protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
1474 static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
1475 kHeapNameFieldNumber),
1476 "ION field mismatch");
1477 }
1478
1479 /** Parses ion heap events (introduced in 4.19 kernels). */
ParseIonStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)1480 void FtraceParser::ParseIonStat(int64_t timestamp,
1481 uint32_t pid,
1482 protozero::ConstBytes data) {
1483 protos::pbzero::IonStatFtraceEvent::Decoder ion(data.data, data.size);
1484 // Push the global counter.
1485 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1486 TrackTracker::Group::kMemory, ion_total_id_);
1487 context_->event_tracker->PushCounter(
1488 timestamp, static_cast<double>(ion.total_allocated()), track);
1489
1490 // Push the change counter.
1491 // TODO(b/121331269): these should really be instant events.
1492 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1493 track =
1494 context_->track_tracker->InternThreadCounterTrack(ion_change_id_, utid);
1495 context_->event_tracker->PushCounter(timestamp,
1496 static_cast<double>(ion.len()), track);
1497
1498 // Global track for individual buffer tracking
1499 auto async_track =
1500 context_->async_track_set_tracker->InternGlobalTrackSet(ion_buffer_id_);
1501 if (ion.len() > 0) {
1502 TrackId start_id =
1503 context_->async_track_set_tracker->Begin(async_track, ion.buffer_id());
1504 std::string buf = std::to_string(ion.len() / 1024) + " kB";
1505 context_->slice_tracker->Begin(
1506 timestamp, start_id, kNullStringId,
1507 context_->storage->InternString(base::StringView(buf)));
1508 } else {
1509 TrackId end_id =
1510 context_->async_track_set_tracker->End(async_track, ion.buffer_id());
1511 context_->slice_tracker->End(timestamp, end_id);
1512 }
1513 }
1514
ParseDmaHeapStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes data)1515 void FtraceParser::ParseDmaHeapStat(int64_t timestamp,
1516 uint32_t pid,
1517 protozero::ConstBytes data) {
1518 protos::pbzero::DmaHeapStatFtraceEvent::Decoder dma_heap(data.data,
1519 data.size);
1520 // Push the global counter.
1521 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1522 TrackTracker::Group::kMemory, dma_heap_total_id_);
1523 context_->event_tracker->PushCounter(
1524 timestamp, static_cast<double>(dma_heap.total_allocated()), track);
1525
1526 // Push the change counter.
1527 // TODO(b/121331269): these should really be instant events.
1528 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1529 track = context_->track_tracker->InternThreadCounterTrack(dma_heap_change_id_,
1530 utid);
1531 context_->event_tracker->PushCounter(
1532 timestamp, static_cast<double>(dma_heap.len()), track);
1533
1534 // Global track for individual buffer tracking
1535 auto async_track =
1536 context_->async_track_set_tracker->InternGlobalTrackSet(dma_buffer_id_);
1537 if (dma_heap.len() > 0) {
1538 TrackId start_id = context_->async_track_set_tracker->Begin(
1539 async_track, static_cast<int64_t>(dma_heap.inode()));
1540 std::string buf = std::to_string(dma_heap.len() / 1024) + " kB";
1541 context_->slice_tracker->Begin(
1542 timestamp, start_id, kNullStringId,
1543 context_->storage->InternString(base::StringView(buf)));
1544 } else {
1545 TrackId end_id = context_->async_track_set_tracker->End(
1546 async_track, static_cast<int64_t>(dma_heap.inode()));
1547 context_->slice_tracker->End(timestamp, end_id);
1548 }
1549 }
1550
1551 // This event has both the pid of the thread that sent the signal and the
1552 // destination of the signal. Currently storing the pid of the destination.
ParseSignalGenerate(int64_t timestamp,ConstBytes blob)1553 void FtraceParser::ParseSignalGenerate(int64_t timestamp, ConstBytes blob) {
1554 protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
1555
1556 UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1557 static_cast<uint32_t>(sig.pid()));
1558 int signal = sig.sig();
1559 TrackId track = context_->track_tracker->InternThreadTrack(utid);
1560 context_->slice_tracker->Scoped(
1561 timestamp, track, kNullStringId, signal_generate_id_, 0,
1562 [this, signal](ArgsTracker::BoundInserter* inserter) {
1563 inserter->AddArg(signal_name_id_, Variadic::Integer(signal));
1564 });
1565 }
1566
ParseSignalDeliver(int64_t timestamp,uint32_t pid,ConstBytes blob)1567 void FtraceParser::ParseSignalDeliver(int64_t timestamp,
1568 uint32_t pid,
1569 ConstBytes blob) {
1570 protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
1571 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1572 int signal = sig.sig();
1573 TrackId track = context_->track_tracker->InternThreadTrack(utid);
1574 context_->slice_tracker->Scoped(
1575 timestamp, track, kNullStringId, signal_deliver_id_, 0,
1576 [this, signal](ArgsTracker::BoundInserter* inserter) {
1577 inserter->AddArg(signal_name_id_, Variadic::Integer(signal));
1578 });
1579 }
1580
ParseOOMScoreAdjUpdate(int64_t timestamp,ConstBytes blob)1581 void FtraceParser::ParseOOMScoreAdjUpdate(int64_t timestamp, ConstBytes blob) {
1582 protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
1583 blob.size);
1584 // The int16_t static cast is because older version of the on-device tracer
1585 // had a bug on negative varint encoding (b/120618641).
1586 int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
1587 uint32_t tid = static_cast<uint32_t>(evt.pid());
1588 UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
1589 context_->event_tracker->PushProcessCounterForThread(timestamp, oom_adj,
1590 oom_score_adj_id_, utid);
1591 }
1592
ParseOOMKill(int64_t timestamp,ConstBytes blob)1593 void FtraceParser::ParseOOMKill(int64_t timestamp, ConstBytes blob) {
1594 protos::pbzero::MarkVictimFtraceEvent::Decoder evt(blob.data, blob.size);
1595 UniqueTid utid = context_->process_tracker->GetOrCreateThread(
1596 static_cast<uint32_t>(evt.pid()));
1597 TrackId track = context_->track_tracker->InternThreadTrack(utid);
1598 context_->slice_tracker->Scoped(timestamp, track, kNullStringId, oom_kill_id_,
1599 0);
1600 }
1601
ParseMmEventRecord(int64_t timestamp,uint32_t pid,ConstBytes blob)1602 void FtraceParser::ParseMmEventRecord(int64_t timestamp,
1603 uint32_t pid,
1604 ConstBytes blob) {
1605 protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
1606 uint32_t type = evt.type();
1607 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1608
1609 if (type >= mm_event_counter_names_.size()) {
1610 context_->storage->IncrementStats(stats::mm_unknown_type);
1611 return;
1612 }
1613
1614 const auto& counter_names = mm_event_counter_names_[type];
1615 context_->event_tracker->PushProcessCounterForThread(
1616 timestamp, evt.count(), counter_names.count, utid);
1617 context_->event_tracker->PushProcessCounterForThread(
1618 timestamp, evt.max_lat(), counter_names.max_lat, utid);
1619 context_->event_tracker->PushProcessCounterForThread(
1620 timestamp, evt.avg_lat(), counter_names.avg_lat, utid);
1621 }
1622
ParseSysEnterEvent(int64_t timestamp,uint32_t pid,ConstBytes blob)1623 void FtraceParser::ParseSysEnterEvent(int64_t timestamp,
1624 uint32_t pid,
1625 ConstBytes blob) {
1626 protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
1627 uint32_t syscall_num = static_cast<uint32_t>(evt.id());
1628 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1629
1630 SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
1631 auto args_callback = [this, &evt](ArgsTracker::BoundInserter* inserter) {
1632 // process all syscall arguments
1633 uint32_t count = 0;
1634 for (auto it = evt.args(); it; ++it) {
1635 if (syscall_arg_name_ids_.size() == count) {
1636 base::StackString<32> string_arg("args[%" PRId32 "]", count);
1637 auto string_id =
1638 context_->storage->InternString(string_arg.string_view());
1639 syscall_arg_name_ids_.emplace_back(string_id);
1640 }
1641 inserter->AddArg(syscall_args_id_, syscall_arg_name_ids_[count],
1642 Variadic::UnsignedInteger(*it));
1643 ++count;
1644 }
1645 };
1646 syscall_tracker->Enter(timestamp, utid, syscall_num, args_callback);
1647 }
1648
ParseSysExitEvent(int64_t timestamp,uint32_t pid,ConstBytes blob)1649 void FtraceParser::ParseSysExitEvent(int64_t timestamp,
1650 uint32_t pid,
1651 ConstBytes blob) {
1652 // Note: Although this seems duplicated to ParseSysEnterEvent, it is
1653 // not. We decode SysExitFtraceEvent here to handle the return
1654 // value of a syscall whereas SysEnterFtraceEvent is decoded
1655 // above to handle the syscall arguments.
1656 protos::pbzero::SysExitFtraceEvent::Decoder evt(blob.data, blob.size);
1657 uint32_t syscall_num = static_cast<uint32_t>(evt.id());
1658 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1659
1660 SyscallTracker* syscall_tracker = SyscallTracker::GetOrCreate(context_);
1661 auto args_callback = [this, &evt](ArgsTracker::BoundInserter* inserter) {
1662 if (evt.has_ret()) {
1663 const auto ret = evt.ret();
1664 inserter->AddArg(syscall_ret_id_, Variadic::Integer(ret));
1665 }
1666 };
1667 syscall_tracker->Exit(timestamp, utid, syscall_num, args_callback);
1668 }
1669
ParseI2cReadEvent(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1670 void FtraceParser::ParseI2cReadEvent(int64_t timestamp,
1671 uint32_t pid,
1672 protozero::ConstBytes blob) {
1673 protos::pbzero::I2cReadFtraceEvent::Decoder evt(blob.data, blob.size);
1674 uint32_t adapter_nr = static_cast<uint32_t>(evt.adapter_nr());
1675 uint32_t msg_nr = static_cast<uint32_t>(evt.msg_nr());
1676 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1677
1678 I2cTracker* i2c_tracker = I2cTracker::GetOrCreate(context_);
1679 i2c_tracker->Enter(timestamp, utid, adapter_nr, msg_nr);
1680 }
1681
ParseI2cWriteEvent(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1682 void FtraceParser::ParseI2cWriteEvent(int64_t timestamp,
1683 uint32_t pid,
1684 protozero::ConstBytes blob) {
1685 protos::pbzero::I2cWriteFtraceEvent::Decoder evt(blob.data, blob.size);
1686 uint32_t adapter_nr = static_cast<uint32_t>(evt.adapter_nr());
1687 uint32_t msg_nr = static_cast<uint32_t>(evt.msg_nr());
1688 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1689
1690 I2cTracker* i2c_tracker = I2cTracker::GetOrCreate(context_);
1691 i2c_tracker->Enter(timestamp, utid, adapter_nr, msg_nr);
1692 }
1693
ParseI2cResultEvent(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)1694 void FtraceParser::ParseI2cResultEvent(int64_t timestamp,
1695 uint32_t pid,
1696 protozero::ConstBytes blob) {
1697 protos::pbzero::I2cResultFtraceEvent::Decoder evt(blob.data, blob.size);
1698 uint32_t adapter_nr = static_cast<uint32_t>(evt.adapter_nr());
1699 uint32_t nr_msgs = static_cast<uint32_t>(evt.nr_msgs());
1700 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1701
1702 I2cTracker* i2c_tracker = I2cTracker::GetOrCreate(context_);
1703 i2c_tracker->Exit(timestamp, utid, adapter_nr, nr_msgs);
1704 }
1705
ParseTaskNewTask(int64_t timestamp,uint32_t source_tid,ConstBytes blob)1706 void FtraceParser::ParseTaskNewTask(int64_t timestamp,
1707 uint32_t source_tid,
1708 ConstBytes blob) {
1709 protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
1710 uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
1711 uint32_t new_tid = static_cast<uint32_t>(evt.pid());
1712 StringId new_comm = context_->storage->InternString(evt.comm());
1713 auto* proc_tracker = context_->process_tracker.get();
1714
1715 // task_newtask is raised both in the case of a new process creation (fork()
1716 // family) and thread creation (clone(CLONE_THREAD, ...)).
1717 static const uint32_t kCloneThread = 0x00010000; // From kernel's sched.h.
1718
1719 // If the process is a fork, start a new process.
1720 if ((clone_flags & kCloneThread) == 0) {
1721 // This is a plain-old fork() or equivalent.
1722 proc_tracker->StartNewProcess(timestamp, source_tid, new_tid, new_comm,
1723 ThreadNamePriority::kFtrace);
1724 return;
1725 }
1726
1727 // This is a pthread_create or similar. Bind the two threads together, so
1728 // they get resolved to the same process.
1729 auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
1730 auto new_utid = proc_tracker->StartNewThread(timestamp, new_tid);
1731 proc_tracker->UpdateThreadNameByUtid(new_utid, new_comm,
1732 ThreadNamePriority::kFtrace);
1733 proc_tracker->AssociateThreads(source_utid, new_utid);
1734
1735 ThreadStateTracker::GetOrCreate(context_)->PushNewTaskEvent(
1736 timestamp, new_utid, source_utid);
1737 }
1738
ParseTaskRename(ConstBytes blob)1739 void FtraceParser::ParseTaskRename(ConstBytes blob) {
1740 protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
1741 uint32_t tid = static_cast<uint32_t>(evt.pid());
1742 StringId comm = context_->storage->InternString(evt.newcomm());
1743 context_->process_tracker->UpdateThreadNameAndMaybeProcessName(
1744 tid, comm, ThreadNamePriority::kFtrace);
1745 }
1746
ParseBinderTransaction(int64_t timestamp,uint32_t pid,ConstBytes blob)1747 void FtraceParser::ParseBinderTransaction(int64_t timestamp,
1748 uint32_t pid,
1749 ConstBytes blob) {
1750 protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
1751 blob.size);
1752 int32_t dest_node = static_cast<int32_t>(evt.target_node());
1753 uint32_t dest_tgid = static_cast<uint32_t>(evt.to_proc());
1754 uint32_t dest_tid = static_cast<uint32_t>(evt.to_thread());
1755 int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1756 bool is_reply = static_cast<int32_t>(evt.reply()) == 1;
1757 uint32_t flags = static_cast<uint32_t>(evt.flags());
1758 auto code_str = base::IntToHexString(evt.code()) + " Java Layer Dependent";
1759 StringId code = context_->storage->InternString(base::StringView(code_str));
1760 BinderTracker::GetOrCreate(context_)->Transaction(
1761 timestamp, pid, transaction_id, dest_node, dest_tgid, dest_tid, is_reply,
1762 flags, code);
1763 }
1764
ParseBinderTransactionReceived(int64_t timestamp,uint32_t pid,ConstBytes blob)1765 void FtraceParser::ParseBinderTransactionReceived(int64_t timestamp,
1766 uint32_t pid,
1767 ConstBytes blob) {
1768 protos::pbzero::BinderTransactionReceivedFtraceEvent::Decoder evt(blob.data,
1769 blob.size);
1770 int32_t transaction_id = static_cast<int32_t>(evt.debug_id());
1771 BinderTracker::GetOrCreate(context_)->TransactionReceived(timestamp, pid,
1772 transaction_id);
1773 }
1774
ParseBinderTransactionAllocBuf(int64_t timestamp,uint32_t pid,ConstBytes blob)1775 void FtraceParser::ParseBinderTransactionAllocBuf(int64_t timestamp,
1776 uint32_t pid,
1777 ConstBytes blob) {
1778 protos::pbzero::BinderTransactionAllocBufFtraceEvent::Decoder evt(blob.data,
1779 blob.size);
1780 uint64_t data_size = static_cast<uint64_t>(evt.data_size());
1781 uint64_t offsets_size = static_cast<uint64_t>(evt.offsets_size());
1782
1783 BinderTracker::GetOrCreate(context_)->TransactionAllocBuf(
1784 timestamp, pid, data_size, offsets_size);
1785 }
1786
ParseBinderLocked(int64_t timestamp,uint32_t pid,ConstBytes blob)1787 void FtraceParser::ParseBinderLocked(int64_t timestamp,
1788 uint32_t pid,
1789 ConstBytes blob) {
1790 protos::pbzero::BinderLockedFtraceEvent::Decoder evt(blob.data, blob.size);
1791 BinderTracker::GetOrCreate(context_)->Locked(timestamp, pid);
1792 }
1793
ParseBinderLock(int64_t timestamp,uint32_t pid,ConstBytes blob)1794 void FtraceParser::ParseBinderLock(int64_t timestamp,
1795 uint32_t pid,
1796 ConstBytes blob) {
1797 protos::pbzero::BinderLockFtraceEvent::Decoder evt(blob.data, blob.size);
1798 BinderTracker::GetOrCreate(context_)->Lock(timestamp, pid);
1799 }
1800
ParseBinderUnlock(int64_t timestamp,uint32_t pid,ConstBytes blob)1801 void FtraceParser::ParseBinderUnlock(int64_t timestamp,
1802 uint32_t pid,
1803 ConstBytes blob) {
1804 protos::pbzero::BinderUnlockFtraceEvent::Decoder evt(blob.data, blob.size);
1805 BinderTracker::GetOrCreate(context_)->Unlock(timestamp, pid);
1806 }
1807
ParseClockSetRate(int64_t timestamp,ConstBytes blob)1808 void FtraceParser::ParseClockSetRate(int64_t timestamp, ConstBytes blob) {
1809 protos::pbzero::ClockSetRateFtraceEvent::Decoder evt(blob.data, blob.size);
1810 static const char kSubtitle[] = "Frequency";
1811 ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1812 }
1813
ParseClockEnable(int64_t timestamp,ConstBytes blob)1814 void FtraceParser::ParseClockEnable(int64_t timestamp, ConstBytes blob) {
1815 protos::pbzero::ClockEnableFtraceEvent::Decoder evt(blob.data, blob.size);
1816 static const char kSubtitle[] = "State";
1817 ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1818 }
1819
ParseClockDisable(int64_t timestamp,ConstBytes blob)1820 void FtraceParser::ParseClockDisable(int64_t timestamp, ConstBytes blob) {
1821 protos::pbzero::ClockDisableFtraceEvent::Decoder evt(blob.data, blob.size);
1822 static const char kSubtitle[] = "State";
1823 ClockRate(timestamp, evt.name(), kSubtitle, evt.state());
1824 }
1825
ClockRate(int64_t timestamp,base::StringView clock_name,base::StringView subtitle,uint64_t rate)1826 void FtraceParser::ClockRate(int64_t timestamp,
1827 base::StringView clock_name,
1828 base::StringView subtitle,
1829 uint64_t rate) {
1830 base::StackString<255> counter_name("%.*s %.*s", int(clock_name.size()),
1831 clock_name.data(), int(subtitle.size()),
1832 subtitle.data());
1833 StringId name = context_->storage->InternString(counter_name.c_str());
1834 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
1835 TrackTracker::Group::kClockFrequency, name);
1836 context_->event_tracker->PushCounter(timestamp, static_cast<double>(rate),
1837 track);
1838 }
1839
ParseScmCallStart(int64_t timestamp,uint32_t pid,ConstBytes blob)1840 void FtraceParser::ParseScmCallStart(int64_t timestamp,
1841 uint32_t pid,
1842 ConstBytes blob) {
1843 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1844 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1845 protos::pbzero::ScmCallStartFtraceEvent::Decoder evt(blob.data, blob.size);
1846
1847 base::StackString<64> str("scm id=%#" PRIx64, evt.x0());
1848 StringId name_id = context_->storage->InternString(str.string_view());
1849 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id);
1850 }
1851
ParseScmCallEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1852 void FtraceParser::ParseScmCallEnd(int64_t timestamp,
1853 uint32_t pid,
1854 ConstBytes blob) {
1855 protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1856 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1857 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1858 context_->slice_tracker->End(timestamp, track_id);
1859 }
1860
ParseCmaAllocStart(int64_t timestamp,uint32_t pid)1861 void FtraceParser::ParseCmaAllocStart(int64_t timestamp, uint32_t pid) {
1862 std::optional<VersionNumber> kernel_version =
1863 SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
1864 // CmaAllocInfo event only exists after 5.10
1865 if (kernel_version < VersionNumber{5, 10})
1866 return;
1867
1868 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1869 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1870
1871 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
1872 cma_alloc_id_);
1873 }
1874
ParseCmaAllocInfo(int64_t timestamp,uint32_t pid,ConstBytes blob)1875 void FtraceParser::ParseCmaAllocInfo(int64_t timestamp,
1876 uint32_t pid,
1877 ConstBytes blob) {
1878 std::optional<VersionNumber> kernel_version =
1879 SystemInfoTracker::GetOrCreate(context_)->GetKernelVersion();
1880 // CmaAllocInfo event only exists after 5.10
1881 if (kernel_version < VersionNumber{5, 10})
1882 return;
1883
1884 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1885 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1886 protos::pbzero::CmaAllocInfoFtraceEvent::Decoder cma_alloc_info(blob.data,
1887 blob.size);
1888 auto args_inserter = [this,
1889 &cma_alloc_info](ArgsTracker::BoundInserter* inserter) {
1890 inserter->AddArg(cma_name_id_,
1891 Variadic::String(context_->storage->InternString(
1892 cma_alloc_info.name())));
1893 inserter->AddArg(cma_pfn_id_,
1894 Variadic::UnsignedInteger(cma_alloc_info.pfn()));
1895 inserter->AddArg(cma_req_pages_id_,
1896 Variadic::UnsignedInteger(cma_alloc_info.count()));
1897 inserter->AddArg(cma_nr_migrated_id_,
1898 Variadic::UnsignedInteger(cma_alloc_info.nr_migrated()));
1899 inserter->AddArg(cma_nr_reclaimed_id_,
1900 Variadic::UnsignedInteger(cma_alloc_info.nr_reclaimed()));
1901 inserter->AddArg(cma_nr_mapped_id_,
1902 Variadic::UnsignedInteger(cma_alloc_info.nr_mapped()));
1903 inserter->AddArg(cma_nr_isolate_fail_id_,
1904 Variadic::UnsignedInteger(cma_alloc_info.err_iso()));
1905 inserter->AddArg(cma_nr_migrate_fail_id_,
1906 Variadic::UnsignedInteger(cma_alloc_info.err_mig()));
1907 inserter->AddArg(cma_nr_test_fail_id_,
1908 Variadic::UnsignedInteger(cma_alloc_info.err_test()));
1909 };
1910 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
1911 kNullStringId, args_inserter);
1912 }
1913
ParseDirectReclaimBegin(int64_t timestamp,uint32_t pid,ConstBytes blob)1914 void FtraceParser::ParseDirectReclaimBegin(int64_t timestamp,
1915 uint32_t pid,
1916 ConstBytes blob) {
1917 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1918 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1919 protos::pbzero::MmVmscanDirectReclaimBeginFtraceEvent::Decoder
1920 direct_reclaim_begin(blob.data, blob.size);
1921
1922 StringId name_id =
1923 context_->storage->InternString("mm_vmscan_direct_reclaim");
1924
1925 auto args_inserter = [this, &direct_reclaim_begin](
1926 ArgsTracker::BoundInserter* inserter) {
1927 inserter->AddArg(direct_reclaim_order_id_,
1928 Variadic::Integer(direct_reclaim_begin.order()));
1929 inserter->AddArg(direct_reclaim_may_writepage_id_,
1930 Variadic::Integer(direct_reclaim_begin.may_writepage()));
1931 inserter->AddArg(
1932 direct_reclaim_gfp_flags_id_,
1933 Variadic::UnsignedInteger(direct_reclaim_begin.gfp_flags()));
1934 };
1935 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId, name_id,
1936 args_inserter);
1937 }
1938
ParseDirectReclaimEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1939 void FtraceParser::ParseDirectReclaimEnd(int64_t timestamp,
1940 uint32_t pid,
1941 ConstBytes blob) {
1942 protos::pbzero::ScmCallEndFtraceEvent::Decoder evt(blob.data, blob.size);
1943 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1944 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
1945 protos::pbzero::MmVmscanDirectReclaimEndFtraceEvent::Decoder
1946 direct_reclaim_end(blob.data, blob.size);
1947
1948 auto args_inserter =
1949 [this, &direct_reclaim_end](ArgsTracker::BoundInserter* inserter) {
1950 inserter->AddArg(
1951 direct_reclaim_nr_reclaimed_id_,
1952 Variadic::UnsignedInteger(direct_reclaim_end.nr_reclaimed()));
1953 };
1954 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
1955 kNullStringId, args_inserter);
1956 }
1957
ParseShrinkSlabStart(int64_t timestamp,uint32_t pid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)1958 void FtraceParser::ParseShrinkSlabStart(
1959 int64_t timestamp,
1960 uint32_t pid,
1961 ConstBytes blob,
1962 PacketSequenceStateGeneration* seq_state) {
1963 protos::pbzero::MmShrinkSlabStartFtraceEvent::Decoder shrink_slab_start(
1964 blob.data, blob.size);
1965
1966 StringId shrink_name =
1967 InternedKernelSymbolOrFallback(shrink_slab_start.shrink(), seq_state);
1968
1969 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1970 TrackId track = context_->track_tracker->InternThreadTrack(utid);
1971
1972 auto args_inserter = [this, &shrink_slab_start,
1973 shrink_name](ArgsTracker::BoundInserter* inserter) {
1974 inserter->AddArg(shrink_name_id_, Variadic::String(shrink_name));
1975 inserter->AddArg(shrink_total_scan_id_,
1976 Variadic::UnsignedInteger(shrink_slab_start.total_scan()));
1977 inserter->AddArg(shrink_priority_id_,
1978 Variadic::Integer(shrink_slab_start.priority()));
1979 };
1980
1981 context_->slice_tracker->Begin(timestamp, track, kNullStringId,
1982 shrink_slab_id_, args_inserter);
1983 }
1984
ParseShrinkSlabEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)1985 void FtraceParser::ParseShrinkSlabEnd(int64_t timestamp,
1986 uint32_t pid,
1987 ConstBytes blob) {
1988 protos::pbzero::MmShrinkSlabEndFtraceEvent::Decoder shrink_slab_end(
1989 blob.data, blob.size);
1990 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
1991 TrackId track = context_->track_tracker->InternThreadTrack(utid);
1992
1993 auto args_inserter =
1994 [this, &shrink_slab_end](ArgsTracker::BoundInserter* inserter) {
1995 inserter->AddArg(shrink_freed_id_,
1996 Variadic::Integer(shrink_slab_end.retval()));
1997 };
1998 context_->slice_tracker->End(timestamp, track, kNullStringId, kNullStringId,
1999 args_inserter);
2000 }
2001
ParseWorkqueueExecuteStart(uint32_t cpu,int64_t timestamp,uint32_t pid,ConstBytes blob,PacketSequenceStateGeneration * seq_state)2002 void FtraceParser::ParseWorkqueueExecuteStart(
2003 uint32_t cpu,
2004 int64_t timestamp,
2005 uint32_t pid,
2006 ConstBytes blob,
2007 PacketSequenceStateGeneration* seq_state) {
2008 protos::pbzero::WorkqueueExecuteStartFtraceEvent::Decoder evt(blob.data,
2009 blob.size);
2010 StringId name_id = InternedKernelSymbolOrFallback(evt.function(), seq_state);
2011
2012 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2013 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2014
2015 auto args_inserter = [this, cpu](ArgsTracker::BoundInserter* inserter) {
2016 inserter->AddArg(cpu_id_, Variadic::Integer(cpu));
2017 };
2018 context_->slice_tracker->Begin(timestamp, track, workqueue_id_, name_id,
2019 args_inserter);
2020 }
2021
ParseWorkqueueExecuteEnd(int64_t timestamp,uint32_t pid,ConstBytes blob)2022 void FtraceParser::ParseWorkqueueExecuteEnd(int64_t timestamp,
2023 uint32_t pid,
2024 ConstBytes blob) {
2025 protos::pbzero::WorkqueueExecuteEndFtraceEvent::Decoder evt(blob.data,
2026 blob.size);
2027 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2028 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2029 context_->slice_tracker->End(timestamp, track, workqueue_id_);
2030 }
2031
ParseIrqHandlerEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2032 void FtraceParser::ParseIrqHandlerEntry(uint32_t cpu,
2033 int64_t timestamp,
2034 protozero::ConstBytes blob) {
2035 protos::pbzero::IrqHandlerEntryFtraceEvent::Decoder evt(blob.data, blob.size);
2036 base::StackString<255> track_name("Irq Cpu %d", cpu);
2037 StringId track_name_id =
2038 context_->storage->InternString(track_name.string_view());
2039
2040 base::StringView irq_name = evt.name();
2041 base::StackString<255> slice_name("IRQ (%.*s)", int(irq_name.size()),
2042 irq_name.data());
2043 StringId slice_name_id =
2044 context_->storage->InternString(slice_name.string_view());
2045 TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2046 context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
2047 }
2048
ParseIrqHandlerExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2049 void FtraceParser::ParseIrqHandlerExit(uint32_t cpu,
2050 int64_t timestamp,
2051 protozero::ConstBytes blob) {
2052 protos::pbzero::IrqHandlerExitFtraceEvent::Decoder evt(blob.data, blob.size);
2053 base::StackString<255> track_name("Irq Cpu %d", cpu);
2054 StringId track_name_id =
2055 context_->storage->InternString(track_name.string_view());
2056 TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2057
2058 base::StackString<255> status("%s", evt.ret() == 1 ? "handled" : "unhandled");
2059 StringId status_id = context_->storage->InternString(status.string_view());
2060 auto args_inserter = [this,
2061 &status_id](ArgsTracker::BoundInserter* inserter) {
2062 inserter->AddArg(ret_arg_id_, Variadic::String(status_id));
2063 };
2064 context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
2065 }
2066
ParseSoftIrqEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2067 void FtraceParser::ParseSoftIrqEntry(uint32_t cpu,
2068 int64_t timestamp,
2069 protozero::ConstBytes blob) {
2070 protos::pbzero::SoftirqEntryFtraceEvent::Decoder evt(blob.data, blob.size);
2071 base::StackString<255> track_name("SoftIrq Cpu %d", cpu);
2072 StringId track_name_id =
2073 context_->storage->InternString(track_name.string_view());
2074 auto num_actions = sizeof(kActionNames) / sizeof(*kActionNames);
2075 if (evt.vec() >= num_actions) {
2076 PERFETTO_DFATAL("No action name at index %d for softirq event.", evt.vec());
2077 return;
2078 }
2079 base::StringView slice_name = kActionNames[evt.vec()];
2080 StringId slice_name_id = context_->storage->InternString(slice_name);
2081 TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2082 context_->slice_tracker->Begin(timestamp, track, irq_id_, slice_name_id);
2083 }
2084
ParseSoftIrqExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2085 void FtraceParser::ParseSoftIrqExit(uint32_t cpu,
2086 int64_t timestamp,
2087 protozero::ConstBytes blob) {
2088 protos::pbzero::SoftirqExitFtraceEvent::Decoder evt(blob.data, blob.size);
2089 base::StackString<255> track_name("SoftIrq Cpu %d", cpu);
2090 StringId track_name_id =
2091 context_->storage->InternString(track_name.string_view());
2092 TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2093 auto vec = evt.vec();
2094 auto args_inserter = [this, vec](ArgsTracker::BoundInserter* inserter) {
2095 inserter->AddArg(vec_arg_id_, Variadic::Integer(vec));
2096 };
2097 context_->slice_tracker->End(timestamp, track, irq_id_, {}, args_inserter);
2098 }
2099
ParseGpuMemTotal(int64_t timestamp,protozero::ConstBytes data)2100 void FtraceParser::ParseGpuMemTotal(int64_t timestamp,
2101 protozero::ConstBytes data) {
2102 protos::pbzero::GpuMemTotalFtraceEvent::Decoder gpu_mem_total(data.data,
2103 data.size);
2104
2105 TrackId track = kInvalidTrackId;
2106 const uint32_t pid = gpu_mem_total.pid();
2107 if (pid == 0) {
2108 // Pid 0 is used to indicate the global total
2109 track = context_->track_tracker->InternGlobalCounterTrack(
2110 TrackTracker::Group::kMemory, gpu_mem_total_name_id_, {},
2111 gpu_mem_total_unit_id_, gpu_mem_total_global_desc_id_);
2112 } else {
2113 // It's possible for GpuMemTotal ftrace events to be emitted by kworker
2114 // threads *after* process death. In this case, we simply want to discard
2115 // the event as otherwise we would create fake processes which we
2116 // definitely want to avoid.
2117 // See b/192274404 for more info.
2118 std::optional<UniqueTid> opt_utid =
2119 context_->process_tracker->GetThreadOrNull(pid);
2120 if (!opt_utid)
2121 return;
2122
2123 // If the thread does exist, the |pid| in gpu_mem_total events is always a
2124 // true process id (and not a thread id) so ensure there is an association
2125 // between the tid and pid.
2126 UniqueTid updated_utid = context_->process_tracker->UpdateThread(pid, pid);
2127 PERFETTO_DCHECK(updated_utid == *opt_utid);
2128
2129 // UpdateThread above should ensure this is always set.
2130 UniquePid upid = *context_->storage->thread_table().upid()[*opt_utid];
2131 PERFETTO_DCHECK(context_->storage->process_table().pid()[upid] == pid);
2132
2133 track = context_->track_tracker->InternProcessCounterTrack(
2134 gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
2135 gpu_mem_total_proc_desc_id_);
2136 }
2137 context_->event_tracker->PushCounter(
2138 timestamp, static_cast<double>(gpu_mem_total.size()), track);
2139 }
2140
ParseThermalTemperature(int64_t timestamp,protozero::ConstBytes blob)2141 void FtraceParser::ParseThermalTemperature(int64_t timestamp,
2142 protozero::ConstBytes blob) {
2143 protos::pbzero::ThermalTemperatureFtraceEvent::Decoder event(blob.data,
2144 blob.size);
2145 base::StringView thermal_zone = event.thermal_zone();
2146 base::StackString<255> counter_name(
2147 "%.*s Temperature", int(thermal_zone.size()), thermal_zone.data());
2148 StringId name = context_->storage->InternString(counter_name.string_view());
2149 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2150 TrackTracker::Group::kThermals, name);
2151 context_->event_tracker->PushCounter(timestamp, event.temp(), track);
2152 }
2153
ParseCdevUpdate(int64_t timestamp,protozero::ConstBytes blob)2154 void FtraceParser::ParseCdevUpdate(int64_t timestamp,
2155 protozero::ConstBytes blob) {
2156 protos::pbzero::CdevUpdateFtraceEvent::Decoder event(blob.data, blob.size);
2157 base::StringView type = event.type();
2158 base::StackString<255> counter_name("%.*s Cooling Device", int(type.size()),
2159 type.data());
2160 StringId name = context_->storage->InternString(counter_name.string_view());
2161 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2162 TrackTracker::Group::kThermals, name);
2163 context_->event_tracker->PushCounter(
2164 timestamp, static_cast<double>(event.target()), track);
2165 }
2166
ParseSchedBlockedReason(protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)2167 void FtraceParser::ParseSchedBlockedReason(
2168 protozero::ConstBytes blob,
2169 PacketSequenceStateGeneration* seq_state) {
2170 protos::pbzero::SchedBlockedReasonFtraceEvent::Decoder event(blob);
2171 uint32_t pid = static_cast<uint32_t>(event.pid());
2172 auto utid = context_->process_tracker->GetOrCreateThread(pid);
2173 uint32_t caller_iid = static_cast<uint32_t>(event.caller());
2174 auto* interned_string = seq_state->LookupInternedMessage<
2175 protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
2176 protos::pbzero::InternedString>(caller_iid);
2177
2178 std::optional<StringId> blocked_function_str_id = std::nullopt;
2179 if (interned_string) {
2180 protozero::ConstBytes str = interned_string->str();
2181 blocked_function_str_id = context_->storage->InternString(
2182 base::StringView(reinterpret_cast<const char*>(str.data), str.size));
2183 }
2184
2185 ThreadStateTracker::GetOrCreate(context_)->PushBlockedReason(
2186 utid, event.io_wait(), blocked_function_str_id);
2187 }
2188
ParseFastRpcDmaStat(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)2189 void FtraceParser::ParseFastRpcDmaStat(int64_t timestamp,
2190 uint32_t pid,
2191 protozero::ConstBytes blob) {
2192 protos::pbzero::FastrpcDmaStatFtraceEvent::Decoder event(blob.data,
2193 blob.size);
2194
2195 StringId name;
2196 if (0 <= event.cid() &&
2197 event.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
2198 name = fast_rpc_delta_names_[static_cast<size_t>(event.cid())];
2199 } else {
2200 base::StackString<64> str("mem.fastrpc[%" PRId32 "]", event.cid());
2201 name = context_->storage->InternString(str.string_view());
2202 }
2203
2204 StringId total_name;
2205 if (0 <= event.cid() &&
2206 event.cid() < static_cast<int32_t>(kFastRpcCounterSize)) {
2207 total_name = fast_rpc_total_names_[static_cast<size_t>(event.cid())];
2208 } else {
2209 base::StackString<64> str("mem.fastrpc[%" PRId32 "]", event.cid());
2210 total_name = context_->storage->InternString(str.string_view());
2211 }
2212
2213 // Push the global counter.
2214 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2215 TrackTracker::Group::kMemory, total_name);
2216 context_->event_tracker->PushCounter(
2217 timestamp, static_cast<double>(event.total_allocated()), track);
2218
2219 // Push the change counter.
2220 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2221 TrackId delta_track =
2222 context_->track_tracker->InternThreadCounterTrack(name, utid);
2223 context_->event_tracker->PushCounter(
2224 timestamp, static_cast<double>(event.len()), delta_track);
2225 }
2226
ParseCpuhpPause(int64_t,uint32_t,protozero::ConstBytes blob)2227 void FtraceParser::ParseCpuhpPause(int64_t,
2228 uint32_t,
2229 protozero::ConstBytes blob) {
2230 protos::pbzero::CpuhpPauseFtraceEvent::Decoder evt(blob.data, blob.size);
2231 // TODO(b/183110813): Parse and visualize this event.
2232 }
2233
ParseNetifReceiveSkb(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2234 void FtraceParser::ParseNetifReceiveSkb(uint32_t cpu,
2235 int64_t timestamp,
2236 protozero::ConstBytes blob) {
2237 protos::pbzero::NetifReceiveSkbFtraceEvent::Decoder event(blob.data,
2238 blob.size);
2239 base::StringView net_device = event.name();
2240 base::StackString<255> counter_name("%.*s Received KB",
2241 static_cast<int>(net_device.size()),
2242 net_device.data());
2243 StringId name = context_->storage->InternString(counter_name.string_view());
2244
2245 nic_received_bytes_[name] += event.len();
2246
2247 uint64_t nic_received_kilobytes = nic_received_bytes_[name] / 1024;
2248 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2249 TrackTracker::Group::kNetwork, name);
2250 std::optional<CounterId> id = context_->event_tracker->PushCounter(
2251 timestamp, static_cast<double>(nic_received_kilobytes), track);
2252 if (!id) {
2253 return;
2254 }
2255 // Store cpu & len as args for metrics computation
2256 StringId cpu_key = context_->storage->InternString("cpu");
2257 StringId len_key = context_->storage->InternString("len");
2258 context_->args_tracker->AddArgsTo(*id)
2259 .AddArg(cpu_key, Variadic::UnsignedInteger(cpu))
2260 .AddArg(len_key, Variadic::UnsignedInteger(event.len()));
2261 }
2262
ParseNetDevXmit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2263 void FtraceParser::ParseNetDevXmit(uint32_t cpu,
2264 int64_t timestamp,
2265 protozero::ConstBytes blob) {
2266 protos::pbzero::NetDevXmitFtraceEvent::Decoder evt(blob.data, blob.size);
2267 base::StringView net_device = evt.name();
2268 base::StackString<255> counter_name("%.*s Transmitted KB",
2269 static_cast<int>(net_device.size()),
2270 net_device.data());
2271 StringId name = context_->storage->InternString(counter_name.string_view());
2272
2273 // Make sure driver took care of packet.
2274 if (evt.rc() != 0) {
2275 return;
2276 }
2277 nic_transmitted_bytes_[name] += evt.len();
2278
2279 uint64_t nic_transmitted_kilobytes = nic_transmitted_bytes_[name] / 1024;
2280 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2281 TrackTracker::Group::kNetwork, name);
2282 std::optional<CounterId> id = context_->event_tracker->PushCounter(
2283 timestamp, static_cast<double>(nic_transmitted_kilobytes), track);
2284 if (!id) {
2285 return;
2286 }
2287 // Store cpu & len as args for metrics computation.
2288 context_->args_tracker->AddArgsTo(*id)
2289 .AddArg(cpu_id_, Variadic::UnsignedInteger(cpu))
2290 .AddArg(len_arg_id_, Variadic::UnsignedInteger(evt.len()));
2291 }
2292
ParseInetSockSetState(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob)2293 void FtraceParser::ParseInetSockSetState(int64_t timestamp,
2294 uint32_t pid,
2295 protozero::ConstBytes blob) {
2296 protos::pbzero::InetSockSetStateFtraceEvent::Decoder evt(blob.data,
2297 blob.size);
2298
2299 // Skip non TCP protocol.
2300 if (evt.protocol() != kIpprotoTcp) {
2301 PERFETTO_ELOG("skip non tcp protocol");
2302 return;
2303 }
2304
2305 // Skip non IP protocol.
2306 if (evt.family() != kAfNet && evt.family() != kAfNet6) {
2307 PERFETTO_ELOG("skip non IP protocol");
2308 return;
2309 }
2310
2311 // Skip invalid TCP state.
2312 if (evt.newstate() >= TCP_MAX_STATES || evt.oldstate() >= TCP_MAX_STATES) {
2313 PERFETTO_ELOG("skip invalid tcp state");
2314 return;
2315 }
2316
2317 auto got = skaddr_to_stream_.find(evt.skaddr());
2318 if (got == skaddr_to_stream_.end()) {
2319 skaddr_to_stream_[evt.skaddr()] = ++num_of_tcp_stream_;
2320 }
2321 uint32_t stream = skaddr_to_stream_[evt.skaddr()];
2322 base::StackString<64> stream_str("TCP stream#%" PRIu32 "", stream);
2323 StringId stream_id =
2324 context_->storage->InternString(stream_str.string_view());
2325
2326 StringId slice_name_id;
2327 if (evt.newstate() == TCP_SYN_SENT) {
2328 base::StackString<32> str("%s(pid=%" PRIu32 ")",
2329 kTcpStateNames[evt.newstate()], pid);
2330 slice_name_id = context_->storage->InternString(str.string_view());
2331 } else if (evt.newstate() == TCP_ESTABLISHED) {
2332 base::StackString<64> str("%s(sport=%" PRIu32 ",dport=%" PRIu32 ")",
2333 kTcpStateNames[evt.newstate()], evt.sport(),
2334 evt.dport());
2335 slice_name_id = context_->storage->InternString(str.string_view());
2336 } else {
2337 base::StringView slice_name = kTcpStateNames[evt.newstate()];
2338 slice_name_id = context_->storage->InternString(slice_name);
2339 }
2340
2341 // Push to async task set tracker.
2342 auto async_track =
2343 context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2344 TrackId end_id = context_->async_track_set_tracker->End(
2345 async_track, static_cast<int64_t>(evt.skaddr()));
2346 context_->slice_tracker->End(timestamp, end_id);
2347 TrackId start_id = context_->async_track_set_tracker->Begin(
2348 async_track, static_cast<int64_t>(evt.skaddr()));
2349 context_->slice_tracker->Begin(timestamp, start_id, tcp_state_id_,
2350 slice_name_id);
2351 }
2352
ParseTcpRetransmitSkb(int64_t timestamp,protozero::ConstBytes blob)2353 void FtraceParser::ParseTcpRetransmitSkb(int64_t timestamp,
2354 protozero::ConstBytes blob) {
2355 protos::pbzero::TcpRetransmitSkbFtraceEvent::Decoder evt(blob.data,
2356 blob.size);
2357
2358 // Push event as instant to async task set tracker.
2359 auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2360 tcp_retransmited_name_id_);
2361 base::StackString<64> str("sport=%" PRIu32 ",dport=%" PRIu32 "", evt.sport(),
2362 evt.dport());
2363 StringId slice_name_id = context_->storage->InternString(str.string_view());
2364 TrackId track_id =
2365 context_->async_track_set_tracker->Scoped(async_track, timestamp, 0);
2366 context_->slice_tracker->Scoped(timestamp, track_id, tcp_event_id_,
2367 slice_name_id, 0);
2368 }
2369
ParseNapiGroReceiveEntry(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2370 void FtraceParser::ParseNapiGroReceiveEntry(uint32_t cpu,
2371 int64_t timestamp,
2372 protozero::ConstBytes blob) {
2373 protos::pbzero::NapiGroReceiveEntryFtraceEvent::Decoder evt(blob.data,
2374 blob.size);
2375 base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
2376 StringId track_name_id =
2377 context_->storage->InternString(track_name.string_view());
2378 base::StringView net_device = evt.name();
2379 StringId slice_name_id = context_->storage->InternString(net_device);
2380 TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2381 auto len = evt.len();
2382 auto args_inserter = [this, len](ArgsTracker::BoundInserter* inserter) {
2383 inserter->AddArg(len_arg_id_, Variadic::Integer(len));
2384 };
2385 context_->slice_tracker->Begin(timestamp, track, napi_gro_id_, slice_name_id,
2386 args_inserter);
2387 }
2388
ParseNapiGroReceiveExit(uint32_t cpu,int64_t timestamp,protozero::ConstBytes blob)2389 void FtraceParser::ParseNapiGroReceiveExit(uint32_t cpu,
2390 int64_t timestamp,
2391 protozero::ConstBytes blob) {
2392 protos::pbzero::NapiGroReceiveExitFtraceEvent::Decoder evt(blob.data,
2393 blob.size);
2394 base::StackString<255> track_name("Napi Gro Cpu %d", cpu);
2395 StringId track_name_id =
2396 context_->storage->InternString(track_name.string_view());
2397 TrackId track = context_->track_tracker->InternCpuTrack(track_name_id, cpu);
2398 auto ret = evt.ret();
2399 auto args_inserter = [this, ret](ArgsTracker::BoundInserter* inserter) {
2400 inserter->AddArg(ret_arg_id_, Variadic::Integer(ret));
2401 };
2402 context_->slice_tracker->End(timestamp, track, napi_gro_id_, {},
2403 args_inserter);
2404 }
2405
ParseCpuFrequencyLimits(int64_t timestamp,protozero::ConstBytes blob)2406 void FtraceParser::ParseCpuFrequencyLimits(int64_t timestamp,
2407 protozero::ConstBytes blob) {
2408 protos::pbzero::CpuFrequencyLimitsFtraceEvent::Decoder evt(blob.data,
2409 blob.size);
2410 base::StackString<255> max_counter_name("Cpu %" PRIu32 " Max Freq Limit",
2411 evt.cpu_id());
2412 base::StackString<255> min_counter_name("Cpu %" PRIu32 " Min Freq Limit",
2413 evt.cpu_id());
2414 // Push max freq to global counter.
2415 StringId max_name = context_->storage->InternString(max_counter_name.c_str());
2416 TrackId max_track =
2417 context_->track_tracker->InternCpuCounterTrack(max_name, evt.cpu_id());
2418 context_->event_tracker->PushCounter(
2419 timestamp, static_cast<double>(evt.max_freq()), max_track);
2420
2421 // Push min freq to global counter.
2422 StringId min_name = context_->storage->InternString(min_counter_name.c_str());
2423 TrackId min_track =
2424 context_->track_tracker->InternCpuCounterTrack(min_name, evt.cpu_id());
2425 context_->event_tracker->PushCounter(
2426 timestamp, static_cast<double>(evt.min_freq()), min_track);
2427 }
2428
ParseKfreeSkb(int64_t timestamp,protozero::ConstBytes blob)2429 void FtraceParser::ParseKfreeSkb(int64_t timestamp,
2430 protozero::ConstBytes blob) {
2431 protos::pbzero::KfreeSkbFtraceEvent::Decoder evt(blob.data, blob.size);
2432
2433 // Skip non IP & IPV6 protocol.
2434 if (evt.protocol() != kEthPIp && evt.protocol() != kEthPIp6) {
2435 return;
2436 }
2437 num_of_kfree_skb_ip_prot += 1;
2438
2439 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2440 TrackTracker::Group::kNetwork, kfree_skb_name_id_);
2441 std::optional<CounterId> id = context_->event_tracker->PushCounter(
2442 timestamp, static_cast<double>(num_of_kfree_skb_ip_prot), track);
2443 if (!id) {
2444 return;
2445 }
2446 base::StackString<255> prot("%s", evt.protocol() == kEthPIp ? "IP" : "IPV6");
2447 StringId prot_id = context_->storage->InternString(prot.string_view());
2448 // Store protocol as args for metrics computation.
2449 context_->args_tracker->AddArgsTo(*id).AddArg(protocol_arg_id_,
2450 Variadic::String(prot_id));
2451 }
2452
ParseCrosEcSensorhubData(int64_t timestamp,protozero::ConstBytes blob)2453 void FtraceParser::ParseCrosEcSensorhubData(int64_t timestamp,
2454 protozero::ConstBytes blob) {
2455 protos::pbzero::CrosEcSensorhubDataFtraceEvent::Decoder evt(blob.data,
2456 blob.size);
2457
2458 // Push the global counter.
2459 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2460 TrackTracker::Group::kDeviceState,
2461 context_->storage->InternString(
2462 base::StringView("cros_ec.cros_ec_sensorhub_data." +
2463 std::to_string(evt.ec_sensor_num()))));
2464
2465 auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
2466 inserter->AddArg(cros_ec_arg_num_id_,
2467 Variadic::Integer(evt.ec_sensor_num()));
2468 inserter->AddArg(
2469 cros_ec_arg_ec_id_,
2470 Variadic::Integer(evt.fifo_timestamp() - evt.current_timestamp()));
2471 inserter->AddArg(cros_ec_arg_sample_ts_id_,
2472 Variadic::Integer(evt.current_timestamp()));
2473 };
2474
2475 context_->event_tracker->PushCounter(
2476 timestamp,
2477 static_cast<double>(evt.current_time() - evt.current_timestamp()), track,
2478 args_inserter);
2479 }
2480
ParseUfshcdClkGating(int64_t timestamp,protozero::ConstBytes blob)2481 void FtraceParser::ParseUfshcdClkGating(int64_t timestamp,
2482 protozero::ConstBytes blob) {
2483 protos::pbzero::UfshcdClkGatingFtraceEvent::Decoder evt(blob.data, blob.size);
2484 int32_t clk_state = 0;
2485
2486 switch (evt.state()) {
2487 case 1:
2488 // Change ON state to 3
2489 clk_state = 3;
2490 break;
2491 case 2:
2492 // Change REQ_OFF state to 1
2493 clk_state = 1;
2494 break;
2495 case 3:
2496 // Change REQ_ON state to 2
2497 clk_state = 2;
2498 break;
2499 }
2500 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2501 TrackTracker::Group::kNetwork, ufs_clkgating_id_);
2502 context_->event_tracker->PushCounter(timestamp,
2503 static_cast<double>(clk_state), track);
2504 }
2505
ParseTrustySmc(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2506 void FtraceParser::ParseTrustySmc(uint32_t pid,
2507 int64_t timestamp,
2508 protozero::ConstBytes blob) {
2509 protos::pbzero::TrustySmcFtraceEvent::Decoder evt(blob.data, blob.size);
2510
2511 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2512 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2513
2514 base::StackString<48> name("trusty_smc:r0= %" PRIu64, evt.r0());
2515 StringId name_generic = context_->storage->InternString(name.string_view());
2516
2517 context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2518 name_generic);
2519 }
2520
ParseTrustySmcDone(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2521 void FtraceParser::ParseTrustySmcDone(uint32_t pid,
2522 int64_t timestamp,
2523 protozero::ConstBytes blob) {
2524 protos::pbzero::TrustySmcDoneFtraceEvent::Decoder evt(blob.data, blob.size);
2525
2526 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2527 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2528
2529 context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2530 base::StackString<256> name("trusty_smc_done:r0= %" PRIu64, evt.ret());
2531 StringId name_generic = context_->storage->InternString(name.string_view());
2532 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2533 name_generic, 0);
2534 }
2535
ParseTrustyStdCall32(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2536 void FtraceParser::ParseTrustyStdCall32(uint32_t pid,
2537 int64_t timestamp,
2538 protozero::ConstBytes blob) {
2539 protos::pbzero::TrustyStdCall32FtraceEvent::Decoder evt(blob.data, blob.size);
2540
2541 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2542 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2543
2544 context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2545 trusty_name_trusty_std_id_);
2546 }
2547
ParseTrustyStdCall32Done(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2548 void FtraceParser::ParseTrustyStdCall32Done(uint32_t pid,
2549 int64_t timestamp,
2550 protozero::ConstBytes blob) {
2551 protos::pbzero::TrustyStdCall32DoneFtraceEvent::Decoder evt(blob.data,
2552 blob.size);
2553
2554 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2555 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2556
2557 context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2558 if (evt.ret() < 0) {
2559 base::StackString<256> name("trusty_err_std: err= %" PRIi64, evt.ret());
2560 StringId name_generic = context_->storage->InternString(name.string_view());
2561 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2562 name_generic, 0);
2563 }
2564 }
2565
ParseTrustyShareMemory(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2566 void FtraceParser::ParseTrustyShareMemory(uint32_t pid,
2567 int64_t timestamp,
2568 protozero::ConstBytes blob) {
2569 protos::pbzero::TrustyShareMemoryFtraceEvent::Decoder evt(blob.data,
2570 blob.size);
2571
2572 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2573 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2574
2575 base::StackString<256> name(
2576 "trusty_share_mem: len= %" PRIu64 " nents= %" PRIu32 " lend= %" PRIu32,
2577 static_cast<uint64_t>(evt.len()), evt.nents(), evt.lend());
2578 StringId name_generic = context_->storage->InternString(name.string_view());
2579
2580 context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2581 name_generic);
2582 }
2583
ParseTrustyShareMemoryDone(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2584 void FtraceParser::ParseTrustyShareMemoryDone(uint32_t pid,
2585 int64_t timestamp,
2586 protozero::ConstBytes blob) {
2587 protos::pbzero::TrustyShareMemoryDoneFtraceEvent::Decoder evt(blob.data,
2588 blob.size);
2589
2590 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2591 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2592 context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2593
2594 base::StackString<256> name("trusty_share_mem: handle= %" PRIu64
2595 " ret= %" PRIi32,
2596 evt.handle(), evt.ret());
2597 StringId name_generic = context_->storage->InternString(name.string_view());
2598 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2599 name_generic, 0);
2600 }
2601
ParseTrustyReclaimMemory(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2602 void FtraceParser::ParseTrustyReclaimMemory(uint32_t pid,
2603 int64_t timestamp,
2604 protozero::ConstBytes blob) {
2605 protos::pbzero::TrustyReclaimMemoryFtraceEvent::Decoder evt(blob.data,
2606 blob.size);
2607
2608 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2609 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2610
2611 base::StackString<256> name("trusty_reclaim_mem: id=%" PRIu64, evt.id());
2612 StringId name_generic = context_->storage->InternString(name.string_view());
2613
2614 context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2615 name_generic);
2616 }
2617
ParseTrustyReclaimMemoryDone(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2618 void FtraceParser::ParseTrustyReclaimMemoryDone(uint32_t pid,
2619 int64_t timestamp,
2620 protozero::ConstBytes blob) {
2621 protos::pbzero::TrustyReclaimMemoryDoneFtraceEvent::Decoder evt(blob.data,
2622 blob.size);
2623
2624 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2625 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2626 context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2627
2628 if (evt.ret() < 0) {
2629 base::StackString<256> name("trusty_reclaim_mem_err: err= %" PRIi32,
2630 evt.ret());
2631 StringId name_generic = context_->storage->InternString(name.string_view());
2632 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2633 name_generic, 0);
2634 }
2635 }
2636
ParseTrustyIrq(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2637 void FtraceParser::ParseTrustyIrq(uint32_t pid,
2638 int64_t timestamp,
2639 protozero::ConstBytes blob) {
2640 protos::pbzero::TrustyIrqFtraceEvent::Decoder evt(blob.data, blob.size);
2641
2642 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2643 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2644
2645 base::StackString<256> name("trusty_irq: irq= %" PRIi32, evt.irq());
2646 StringId name_generic = context_->storage->InternString(name.string_view());
2647
2648 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2649 name_generic, 0);
2650 }
2651
ParseTrustyIpcHandleEvent(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2652 void FtraceParser::ParseTrustyIpcHandleEvent(uint32_t pid,
2653 int64_t timestamp,
2654 protozero::ConstBytes blob) {
2655 protos::pbzero::TrustyIpcHandleEventFtraceEvent::Decoder evt(blob.data,
2656 blob.size);
2657
2658 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2659 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2660
2661 base::StackString<256> name(
2662 "trusty_ipc_handle_event: chan=%" PRIu32 " srv_name=%s event=%" PRIu32,
2663 evt.chan(), evt.srv_name().ToStdString().c_str(), evt.event_id());
2664 StringId name_generic = context_->storage->InternString(name.string_view());
2665
2666 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2667 name_generic, 0);
2668 }
2669
ParseTrustyEnqueueNop(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2670 void FtraceParser::ParseTrustyEnqueueNop(uint32_t pid,
2671 int64_t timestamp,
2672 protozero::ConstBytes blob) {
2673 protos::pbzero::TrustyEnqueueNopFtraceEvent::Decoder evt(blob.data,
2674 blob.size);
2675
2676 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2677 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2678
2679 base::StackString<256> name("trusty_enqueue_nop: arg1= %" PRIu32
2680 " arg2= %" PRIu32 " arg3=%" PRIu32,
2681 evt.arg1(), evt.arg2(), evt.arg3());
2682 StringId name_generic = context_->storage->InternString(name.string_view());
2683 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2684 name_generic, 0);
2685 }
2686
ParseTrustyIpcConnect(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2687 void FtraceParser::ParseTrustyIpcConnect(uint32_t pid,
2688 int64_t timestamp,
2689 protozero::ConstBytes blob) {
2690 protos::pbzero::TrustyIpcConnectFtraceEvent::Decoder evt(blob.data,
2691 blob.size);
2692
2693 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2694 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2695
2696 base::StackString<256> name("tipc_connect: %s",
2697 evt.port().ToStdString().c_str());
2698 StringId name_generic = context_->storage->InternString(name.string_view());
2699
2700 context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2701 name_generic);
2702 }
2703
ParseTrustyIpcConnectEnd(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2704 void FtraceParser::ParseTrustyIpcConnectEnd(uint32_t pid,
2705 int64_t timestamp,
2706 protozero::ConstBytes blob) {
2707 protos::pbzero::TrustyIpcConnectEndFtraceEvent::Decoder evt(blob.data,
2708 blob.size);
2709
2710 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2711 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2712
2713 context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2714 if (evt.err()) {
2715 base::StackString<256> name("tipc_err_connect:err= %" PRIi32, evt.err());
2716 StringId name_generic = context_->storage->InternString(name.string_view());
2717 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2718 name_generic, 0);
2719 }
2720 }
2721
ParseTrustyIpcWrite(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2722 void FtraceParser::ParseTrustyIpcWrite(uint32_t pid,
2723 int64_t timestamp,
2724 protozero::ConstBytes blob) {
2725 protos::pbzero::TrustyIpcWriteFtraceEvent::Decoder evt(blob.data, blob.size);
2726
2727 StringId name_generic = kNullStringId;
2728 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2729 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2730
2731 if (evt.shm_cnt() > 0) {
2732 base::StackString<256> name("tipc_write: %s shm_cnt:[%" PRIu64 "]",
2733 evt.srv_name().ToStdString().c_str(),
2734 evt.shm_cnt());
2735 name_generic = context_->storage->InternString(name.string_view());
2736 } else {
2737 base::StackString<256> name("tipc_write: %s",
2738 evt.srv_name().ToStdString().c_str());
2739 name_generic = context_->storage->InternString(name.string_view());
2740 }
2741 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2742 name_generic, 0);
2743
2744 if (evt.len_or_err() < 0) {
2745 base::StackString<256> name("tipc_err_write:len_or_err= %" PRIi32,
2746 evt.len_or_err());
2747 name_generic = context_->storage->InternString(name.string_view());
2748 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2749 name_generic, 0);
2750 }
2751 }
2752
ParseTrustyIpcRead(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2753 void FtraceParser::ParseTrustyIpcRead(uint32_t pid,
2754 int64_t timestamp,
2755 protozero::ConstBytes blob) {
2756 protos::pbzero::TrustyIpcReadFtraceEvent::Decoder evt(blob.data, blob.size);
2757
2758 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2759 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2760
2761 base::StackString<256> name("tipc_read: %s",
2762 evt.srv_name().ToStdString().c_str());
2763 StringId name_generic = context_->storage->InternString(name.string_view());
2764 context_->slice_tracker->Begin(timestamp, track, trusty_category_id_,
2765 name_generic);
2766 }
2767
ParseTrustyIpcReadEnd(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2768 void FtraceParser::ParseTrustyIpcReadEnd(uint32_t pid,
2769 int64_t timestamp,
2770 protozero::ConstBytes blob) {
2771 protos::pbzero::TrustyIpcReadEndFtraceEvent::Decoder evt(blob.data,
2772 blob.size);
2773
2774 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2775 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2776 context_->slice_tracker->End(timestamp, track, trusty_category_id_);
2777
2778 if (evt.len_or_err() <= 0) {
2779 base::StackString<256> name("tipc_err_read:len_or_err= %" PRIi32,
2780 evt.len_or_err());
2781 StringId name_generic = context_->storage->InternString(name.string_view());
2782 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2783 name_generic, 0);
2784 }
2785 }
2786
ParseTrustyIpcPoll(uint32_t pid,int64_t timestamp,protozero::ConstBytes blob)2787 void FtraceParser::ParseTrustyIpcPoll(uint32_t pid,
2788 int64_t timestamp,
2789 protozero::ConstBytes blob) {
2790 protos::pbzero::TrustyIpcPollFtraceEvent::Decoder evt(blob.data, blob.size);
2791
2792 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2793 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2794
2795 base::StackString<256> name("tipc_poll: %s",
2796 evt.srv_name().ToStdString().c_str());
2797 StringId name_generic = context_->storage->InternString(name.string_view());
2798 context_->slice_tracker->Scoped(timestamp, track, trusty_category_id_,
2799 name_generic, 0);
2800 }
2801
ParseTrustyIpcRx(uint32_t pid,int64_t ts,protozero::ConstBytes blob)2802 void FtraceParser::ParseTrustyIpcRx(uint32_t pid,
2803 int64_t ts,
2804 protozero::ConstBytes blob) {
2805 protos::pbzero::TrustyIpcRxFtraceEvent::Decoder evt(blob.data, blob.size);
2806
2807 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
2808 TrackId track = context_->track_tracker->InternThreadTrack(utid);
2809
2810 context_->slice_tracker->Scoped(ts, track, trusty_category_id_,
2811 trusty_name_tipc_rx_id_, 0);
2812 }
2813
ParseUfshcdCommand(int64_t timestamp,protozero::ConstBytes blob)2814 void FtraceParser::ParseUfshcdCommand(int64_t timestamp,
2815 protozero::ConstBytes blob) {
2816 protos::pbzero::UfshcdCommandFtraceEvent::Decoder evt(blob.data, blob.size);
2817
2818 // Parse occupied ufs command queue
2819 uint32_t num = evt.doorbell() > 0
2820 ? static_cast<uint32_t>(PERFETTO_POPCOUNT(evt.doorbell()))
2821 : (evt.str_t() == 1 ? 0 : 1);
2822 TrackId track = context_->track_tracker->InternGlobalCounterTrack(
2823 TrackTracker::Group::kIo, ufs_command_count_id_);
2824 context_->event_tracker->PushCounter(timestamp, static_cast<double>(num),
2825 track);
2826
2827 // Parse ufs command tag
2828 base::StackString<32> cmd_track_name("io.ufs.command.tag[%03d]", evt.tag());
2829 auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2830 context_->storage->InternString(cmd_track_name.string_view()));
2831 if (evt.str_t() == 0) {
2832 std::string ufs_op_str = GetUfsCmdString(evt.opcode(), evt.group_id());
2833 StringId ufs_slice_name =
2834 context_->storage->InternString(base::StringView(ufs_op_str));
2835 TrackId start_id = context_->async_track_set_tracker->Begin(async_track, 0);
2836 context_->slice_tracker->Begin(timestamp, start_id, kNullStringId,
2837 ufs_slice_name);
2838 } else {
2839 TrackId end_id = context_->async_track_set_tracker->End(async_track, 0);
2840 context_->slice_tracker->End(timestamp, end_id);
2841 }
2842 }
2843
ParseWakeSourceActivate(int64_t timestamp,protozero::ConstBytes blob)2844 void FtraceParser::ParseWakeSourceActivate(int64_t timestamp,
2845 protozero::ConstBytes blob) {
2846 protos::pbzero::WakeupSourceActivateFtraceEvent::Decoder evt(blob.data,
2847 blob.size);
2848 std::string event_name = evt.name().ToStdString();
2849
2850 uint32_t count = active_wakelock_to_count_[event_name];
2851
2852 active_wakelock_to_count_[event_name] += 1;
2853
2854 // There is already an active track with this name, don't create another.
2855 if (count > 0) {
2856 return;
2857 }
2858
2859 base::StackString<32> str("Wakelock(%s)", event_name.c_str());
2860 StringId stream_id = context_->storage->InternString(str.string_view());
2861
2862 auto async_track =
2863 context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2864
2865 TrackId start_id = context_->async_track_set_tracker->Begin(async_track, 0);
2866
2867 context_->slice_tracker->Begin(timestamp, start_id, kNullStringId, stream_id);
2868 }
2869
ParseWakeSourceDeactivate(int64_t timestamp,protozero::ConstBytes blob)2870 void FtraceParser::ParseWakeSourceDeactivate(int64_t timestamp,
2871 protozero::ConstBytes blob) {
2872 protos::pbzero::WakeupSourceDeactivateFtraceEvent::Decoder evt(blob.data,
2873 blob.size);
2874
2875 std::string event_name = evt.name().ToStdString();
2876 uint32_t count = active_wakelock_to_count_[event_name];
2877 active_wakelock_to_count_[event_name] = count > 0 ? count - 1 : 0;
2878 if (count != 1) {
2879 return;
2880 }
2881
2882 base::StackString<32> str("Wakelock(%s)", event_name.c_str());
2883 StringId stream_id = context_->storage->InternString(str.string_view());
2884 auto async_track =
2885 context_->async_track_set_tracker->InternGlobalTrackSet(stream_id);
2886
2887 TrackId end_id = context_->async_track_set_tracker->End(async_track, 0);
2888 context_->slice_tracker->End(timestamp, end_id);
2889 }
2890
ParseSuspendResume(int64_t timestamp,protozero::ConstBytes blob)2891 void FtraceParser::ParseSuspendResume(int64_t timestamp,
2892 protozero::ConstBytes blob) {
2893 protos::pbzero::SuspendResumeFtraceEvent::Decoder evt(blob.data, blob.size);
2894
2895 auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2896 suspend_resume_name_id_);
2897
2898 std::string action_name = evt.action().ToStdString();
2899
2900 // Hard code fix the timekeeping_freeze action's value to zero, the value is
2901 // processor_id and device could enter suspend/resume from different
2902 // processor.
2903 auto val = (action_name == "timekeeping_freeze") ? 0 : evt.val();
2904
2905 base::StackString<64> str("%s(%" PRIu32 ")", action_name.c_str(), val);
2906 std::string current_action = str.ToStdString();
2907
2908 StringId slice_name_id = context_->storage->InternString(str.string_view());
2909
2910 if (!evt.start()) {
2911 TrackId end_id = context_->async_track_set_tracker->End(
2912 async_track, static_cast<int64_t>(val));
2913 context_->slice_tracker->End(timestamp, end_id);
2914 ongoing_suspend_resume_actions[current_action] = false;
2915 return;
2916 }
2917
2918 // Complete the previous action before starting a new one.
2919 if (ongoing_suspend_resume_actions[current_action]) {
2920 TrackId end_id = context_->async_track_set_tracker->End(
2921 async_track, static_cast<int64_t>(val));
2922 auto args_inserter = [this](ArgsTracker::BoundInserter* inserter) {
2923 inserter->AddArg(replica_slice_id_, Variadic::Boolean(true));
2924 };
2925 context_->slice_tracker->End(timestamp, end_id, kNullStringId,
2926 kNullStringId, args_inserter);
2927 }
2928
2929 TrackId start_id = context_->async_track_set_tracker->Begin(
2930 async_track, static_cast<int64_t>(val));
2931 context_->slice_tracker->Begin(timestamp, start_id, suspend_resume_name_id_,
2932 slice_name_id);
2933 ongoing_suspend_resume_actions[current_action] = true;
2934 }
2935
ParseSuspendResumeMinimal(int64_t timestamp,protozero::ConstBytes blob)2936 void FtraceParser::ParseSuspendResumeMinimal(int64_t timestamp,
2937 protozero::ConstBytes blob) {
2938 protos::pbzero::SuspendResumeMinimalFtraceEvent::Decoder evt(blob.data,
2939 blob.size);
2940 auto async_track = context_->async_track_set_tracker->InternGlobalTrackSet(
2941 suspend_resume_minimal_name_id_);
2942
2943 if (evt.start()) {
2944 TrackId start_id = context_->async_track_set_tracker->Begin(
2945 async_track, static_cast<int64_t>(0));
2946 context_->slice_tracker->Begin(timestamp, start_id,
2947 suspend_resume_minimal_name_id_,
2948 suspend_resume_minimal_slice_name_id_);
2949 } else {
2950 TrackId end_id = context_->async_track_set_tracker->End(
2951 async_track, static_cast<int64_t>(0));
2952 context_->slice_tracker->End(timestamp, end_id);
2953 }
2954 }
2955
ParseSchedCpuUtilCfs(int64_t timestamp,protozero::ConstBytes blob)2956 void FtraceParser::ParseSchedCpuUtilCfs(int64_t timestamp,
2957 protozero::ConstBytes blob) {
2958 protos::pbzero::SchedCpuUtilCfsFtraceEvent::Decoder evt(blob.data, blob.size);
2959 base::StackString<255> util_track_name("Cpu %" PRIu32 " Util", evt.cpu());
2960 StringId util_track_name_id =
2961 context_->storage->InternString(util_track_name.string_view());
2962
2963 TrackId util_track = context_->track_tracker->InternCpuCounterTrack(
2964 util_track_name_id, evt.cpu());
2965 context_->event_tracker->PushCounter(
2966 timestamp, static_cast<double>(evt.cpu_util()), util_track);
2967
2968 base::StackString<255> cap_track_name("Cpu %" PRIu32 " Cap", evt.cpu());
2969 StringId cap_track_name_id =
2970 context_->storage->InternString(cap_track_name.string_view());
2971
2972 TrackId cap_track = context_->track_tracker->InternCpuCounterTrack(
2973 cap_track_name_id, evt.cpu());
2974 context_->event_tracker->PushCounter(
2975 timestamp, static_cast<double>(evt.capacity()), cap_track);
2976
2977 base::StackString<255> nrr_track_name("Cpu %" PRIu32 " Nr Running",
2978 evt.cpu());
2979 StringId nrr_track_name_id =
2980 context_->storage->InternString(nrr_track_name.string_view());
2981
2982 TrackId nrr_track = context_->track_tracker->InternCpuCounterTrack(
2983 nrr_track_name_id, evt.cpu());
2984 context_->event_tracker->PushCounter(
2985 timestamp, static_cast<double>(evt.nr_running()), nrr_track);
2986 }
2987
ParseFuncgraphEntry(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)2988 void FtraceParser::ParseFuncgraphEntry(
2989 int64_t timestamp,
2990 uint32_t pid,
2991 protozero::ConstBytes blob,
2992 PacketSequenceStateGeneration* seq_state) {
2993 // TODO(rsavitski): remove if/when we stop collapsing all idle (swapper)
2994 // threads to a single track, otherwise this breaks slice nesting.
2995 if (pid == 0)
2996 return;
2997
2998 protos::pbzero::FuncgraphEntryFtraceEvent::Decoder evt(blob.data, blob.size);
2999 StringId name_id = InternedKernelSymbolOrFallback(evt.func(), seq_state);
3000
3001 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
3002 TrackId track = context_->track_tracker->InternThreadTrack(utid);
3003 context_->slice_tracker->Begin(timestamp, track, kNullStringId, name_id);
3004 }
3005
ParseFuncgraphExit(int64_t timestamp,uint32_t pid,protozero::ConstBytes blob,PacketSequenceStateGeneration * seq_state)3006 void FtraceParser::ParseFuncgraphExit(
3007 int64_t timestamp,
3008 uint32_t pid,
3009 protozero::ConstBytes blob,
3010 PacketSequenceStateGeneration* seq_state) {
3011 // TODO(rsavitski): remove if/when we stop collapsing all idle (swapper)
3012 // threads to a single track, otherwise this breaks slice nesting.
3013 if (pid == 0)
3014 return;
3015
3016 protos::pbzero::FuncgraphExitFtraceEvent::Decoder evt(blob.data, blob.size);
3017 StringId name_id = InternedKernelSymbolOrFallback(evt.func(), seq_state);
3018
3019 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
3020 TrackId track = context_->track_tracker->InternThreadTrack(utid);
3021 context_->slice_tracker->End(timestamp, track, kNullStringId, name_id);
3022 }
3023
InternedKernelSymbolOrFallback(uint64_t key,PacketSequenceStateGeneration * seq_state)3024 StringId FtraceParser::InternedKernelSymbolOrFallback(
3025 uint64_t key,
3026 PacketSequenceStateGeneration* seq_state) {
3027 auto* interned_string = seq_state->LookupInternedMessage<
3028 protos::pbzero::InternedData::kKernelSymbolsFieldNumber,
3029 protos::pbzero::InternedString>(key);
3030 StringId name_id;
3031 if (interned_string) {
3032 protozero::ConstBytes str = interned_string->str();
3033 name_id = context_->storage->InternString(
3034 base::StringView(reinterpret_cast<const char*>(str.data), str.size));
3035 } else {
3036 base::StackString<255> slice_name("%#" PRIx64, key);
3037 name_id = context_->storage->InternString(slice_name.string_view());
3038 }
3039 return name_id;
3040 }
3041
3042 } // namespace trace_processor
3043 } // namespace perfetto
3044