hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/tools/perf/util/db-export.c
....@@ -1,101 +1,39 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * db-export.c: Support for exporting data suitable for import to a database
34 * Copyright (c) 2014, Intel Corporation.
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms and conditions of the GNU General Public License,
7
- * version 2, as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope it will be useful, but WITHOUT
10
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
- * more details.
13
- *
145 */
156
167 #include <errno.h>
8
+#include <stdlib.h>
179
10
+#include "dso.h"
1811 #include "evsel.h"
1912 #include "machine.h"
2013 #include "thread.h"
2114 #include "comm.h"
2215 #include "symbol.h"
16
+#include "map.h"
2317 #include "event.h"
24
-#include "util.h"
2518 #include "thread-stack.h"
2619 #include "callchain.h"
2720 #include "call-path.h"
2821 #include "db-export.h"
29
-
30
-struct deferred_export {
31
- struct list_head node;
32
- struct comm *comm;
33
-};
34
-
35
-static int db_export__deferred(struct db_export *dbe)
36
-{
37
- struct deferred_export *de;
38
- int err;
39
-
40
- while (!list_empty(&dbe->deferred)) {
41
- de = list_entry(dbe->deferred.next, struct deferred_export,
42
- node);
43
- err = dbe->export_comm(dbe, de->comm);
44
- list_del(&de->node);
45
- free(de);
46
- if (err)
47
- return err;
48
- }
49
-
50
- return 0;
51
-}
52
-
53
-static void db_export__free_deferred(struct db_export *dbe)
54
-{
55
- struct deferred_export *de;
56
-
57
- while (!list_empty(&dbe->deferred)) {
58
- de = list_entry(dbe->deferred.next, struct deferred_export,
59
- node);
60
- list_del(&de->node);
61
- free(de);
62
- }
63
-}
64
-
65
-static int db_export__defer_comm(struct db_export *dbe, struct comm *comm)
66
-{
67
- struct deferred_export *de;
68
-
69
- de = zalloc(sizeof(struct deferred_export));
70
- if (!de)
71
- return -ENOMEM;
72
-
73
- de->comm = comm;
74
- list_add_tail(&de->node, &dbe->deferred);
75
-
76
- return 0;
77
-}
22
+#include <linux/zalloc.h>
7823
7924 int db_export__init(struct db_export *dbe)
8025 {
8126 memset(dbe, 0, sizeof(struct db_export));
82
- INIT_LIST_HEAD(&dbe->deferred);
8327 return 0;
84
-}
85
-
86
-int db_export__flush(struct db_export *dbe)
87
-{
88
- return db_export__deferred(dbe);
8928 }
9029
9130 void db_export__exit(struct db_export *dbe)
9231 {
93
- db_export__free_deferred(dbe);
9432 call_return_processor__free(dbe->crp);
9533 dbe->crp = NULL;
9634 }
9735
98
-int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
36
+int db_export__evsel(struct db_export *dbe, struct evsel *evsel)
9937 {
10038 if (evsel->db_id)
10139 return 0;
....@@ -122,71 +60,73 @@
12260 }
12361
12462 int db_export__thread(struct db_export *dbe, struct thread *thread,
125
- struct machine *machine, struct comm *comm)
63
+ struct machine *machine, struct thread *main_thread)
12664 {
127
- struct thread *main_thread;
12865 u64 main_thread_db_id = 0;
129
- int err;
13066
13167 if (thread->db_id)
13268 return 0;
13369
13470 thread->db_id = ++dbe->thread_last_db_id;
13571
136
- if (thread->pid_ != -1) {
137
- if (thread->pid_ == thread->tid) {
138
- main_thread = thread;
139
- } else {
140
- main_thread = machine__findnew_thread(machine,
141
- thread->pid_,
142
- thread->pid_);
143
- if (!main_thread)
144
- return -ENOMEM;
145
- err = db_export__thread(dbe, main_thread, machine,
146
- comm);
147
- if (err)
148
- goto out_put;
149
- if (comm) {
150
- err = db_export__comm_thread(dbe, comm, thread);
151
- if (err)
152
- goto out_put;
153
- }
154
- }
72
+ if (main_thread)
15573 main_thread_db_id = main_thread->db_id;
156
- if (main_thread != thread)
157
- thread__put(main_thread);
158
- }
15974
16075 if (dbe->export_thread)
16176 return dbe->export_thread(dbe, thread, main_thread_db_id,
16277 machine);
16378
16479 return 0;
80
+}
16581
166
-out_put:
167
- thread__put(main_thread);
168
- return err;
82
+static int __db_export__comm(struct db_export *dbe, struct comm *comm,
83
+ struct thread *thread)
84
+{
85
+ comm->db_id = ++dbe->comm_last_db_id;
86
+
87
+ if (dbe->export_comm)
88
+ return dbe->export_comm(dbe, comm, thread);
89
+
90
+ return 0;
16991 }
17092
17193 int db_export__comm(struct db_export *dbe, struct comm *comm,
172
- struct thread *main_thread)
94
+ struct thread *thread)
95
+{
96
+ if (comm->db_id)
97
+ return 0;
98
+
99
+ return __db_export__comm(dbe, comm, thread);
100
+}
101
+
102
+/*
103
+ * Export the "exec" comm. The "exec" comm is the program / application command
104
+ * name at the time it first executes. It is used to group threads for the same
105
+ * program. Note that the main thread pid (or thread group id tgid) cannot be
106
+ * used because it does not change when a new program is exec'ed.
107
+ */
108
+int db_export__exec_comm(struct db_export *dbe, struct comm *comm,
109
+ struct thread *main_thread)
173110 {
174111 int err;
175112
176113 if (comm->db_id)
177114 return 0;
178115
179
- comm->db_id = ++dbe->comm_last_db_id;
116
+ err = __db_export__comm(dbe, comm, main_thread);
117
+ if (err)
118
+ return err;
180119
181
- if (dbe->export_comm) {
182
- if (main_thread->comm_set)
183
- err = dbe->export_comm(dbe, comm);
184
- else
185
- err = db_export__defer_comm(dbe, comm);
186
- if (err)
187
- return err;
188
- }
189
-
120
+ /*
121
+ * Record the main thread for this comm. Note that the main thread can
122
+ * have many "exec" comms because there will be a new one every time it
123
+ * exec's. An "exec" comm however will only ever have 1 main thread.
124
+ * That is different to any other threads for that same program because
125
+ * exec() will effectively kill them, so the relationship between the
126
+ * "exec" comm and non-main threads is 1-to-1. That is why
127
+ * db_export__comm_thread() is called here for the main thread, but it
128
+ * is called for non-main threads when they are exported.
129
+ */
190130 return db_export__comm_thread(dbe, comm, main_thread);
191131 }
192132
....@@ -241,7 +181,7 @@
241181 if (al->map) {
242182 struct dso *dso = al->map->dso;
243183
244
- err = db_export__dso(dbe, dso, al->machine);
184
+ err = db_export__dso(dbe, dso, al->maps->machine);
245185 if (err)
246186 return err;
247187 *dso_db_id = dso->db_id;
....@@ -270,7 +210,7 @@
270210 struct machine *machine,
271211 struct thread *thread,
272212 struct perf_sample *sample,
273
- struct perf_evsel *evsel)
213
+ struct evsel *evsel)
274214 {
275215 u64 kernel_start = machine__kernel_start(machine);
276216 struct call_path *current = &dbe->cpr->call_path;
....@@ -309,9 +249,9 @@
309249 * constructing an addr_location struct and then passing it to
310250 * db_ids_from_al() to perform the export.
311251 */
312
- al.sym = node->sym;
313
- al.map = node->map;
314
- al.machine = machine;
252
+ al.sym = node->ms.sym;
253
+ al.map = node->ms.map;
254
+ al.maps = thread->maps;
315255 al.addr = node->ip;
316256
317257 if (al.map && !al.sym)
....@@ -347,11 +287,65 @@
347287 return 0;
348288 }
349289
290
+static int db_export__threads(struct db_export *dbe, struct thread *thread,
291
+ struct thread *main_thread,
292
+ struct machine *machine, struct comm **comm_ptr)
293
+{
294
+ struct comm *comm = NULL;
295
+ struct comm *curr_comm;
296
+ int err;
297
+
298
+ if (main_thread) {
299
+ /*
300
+ * A thread has a reference to the main thread, so export the
301
+ * main thread first.
302
+ */
303
+ err = db_export__thread(dbe, main_thread, machine, main_thread);
304
+ if (err)
305
+ return err;
306
+ /*
307
+ * Export comm before exporting the non-main thread because
308
+ * db_export__comm_thread() can be called further below.
309
+ */
310
+ comm = machine__thread_exec_comm(machine, main_thread);
311
+ if (comm) {
312
+ err = db_export__exec_comm(dbe, comm, main_thread);
313
+ if (err)
314
+ return err;
315
+ *comm_ptr = comm;
316
+ }
317
+ }
318
+
319
+ if (thread != main_thread) {
320
+ /*
321
+ * For a non-main thread, db_export__comm_thread() must be
322
+ * called only if thread has not previously been exported.
323
+ */
324
+ bool export_comm_thread = comm && !thread->db_id;
325
+
326
+ err = db_export__thread(dbe, thread, machine, main_thread);
327
+ if (err)
328
+ return err;
329
+
330
+ if (export_comm_thread) {
331
+ err = db_export__comm_thread(dbe, comm, thread);
332
+ if (err)
333
+ return err;
334
+ }
335
+ }
336
+
337
+ curr_comm = thread__comm(thread);
338
+ if (curr_comm)
339
+ return db_export__comm(dbe, curr_comm, thread);
340
+
341
+ return 0;
342
+}
343
+
350344 int db_export__sample(struct db_export *dbe, union perf_event *event,
351
- struct perf_sample *sample, struct perf_evsel *evsel,
345
+ struct perf_sample *sample, struct evsel *evsel,
352346 struct addr_location *al)
353347 {
354
- struct thread* thread = al->thread;
348
+ struct thread *thread = al->thread;
355349 struct export_sample es = {
356350 .event = event,
357351 .sample = sample,
....@@ -366,24 +360,18 @@
366360 if (err)
367361 return err;
368362
369
- err = db_export__machine(dbe, al->machine);
363
+ err = db_export__machine(dbe, al->maps->machine);
370364 if (err)
371365 return err;
372366
373
- main_thread = thread__main_thread(al->machine, thread);
374
- if (main_thread)
375
- comm = machine__thread_exec_comm(al->machine, main_thread);
367
+ main_thread = thread__main_thread(al->maps->machine, thread);
376368
377
- err = db_export__thread(dbe, thread, al->machine, comm);
369
+ err = db_export__threads(dbe, thread, main_thread, al->maps->machine, &comm);
378370 if (err)
379371 goto out_put;
380372
381
- if (comm) {
382
- err = db_export__comm(dbe, comm, main_thread);
383
- if (err)
384
- goto out_put;
373
+ if (comm)
385374 es.comm_db_id = comm->db_id;
386
- }
387375
388376 es.db_id = ++dbe->sample_last_db_id;
389377
....@@ -392,7 +380,7 @@
392380 goto out_put;
393381
394382 if (dbe->cpr) {
395
- struct call_path *cp = call_path_from_sample(dbe, al->machine,
383
+ struct call_path *cp = call_path_from_sample(dbe, al->maps->machine,
396384 thread, sample,
397385 evsel);
398386 if (cp) {
....@@ -401,8 +389,8 @@
401389 }
402390 }
403391
404
- if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
405
- sample_addr_correlates_sym(&evsel->attr)) {
392
+ if ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
393
+ sample_addr_correlates_sym(&evsel->core.attr)) {
406394 struct addr_location addr_al;
407395
408396 thread__resolve(thread, &addr_al, sample);
....@@ -463,6 +451,28 @@
463451 if (err)
464452 break;
465453 }
454
+
455
+ /* Add trace begin / end variants */
456
+ for (i = 0; branch_types[i].name ; i++) {
457
+ const char *name = branch_types[i].name;
458
+ u32 type = branch_types[i].branch_type;
459
+ char buf[64];
460
+
461
+ if (type == PERF_IP_FLAG_BRANCH ||
462
+ (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
463
+ continue;
464
+
465
+ snprintf(buf, sizeof(buf), "trace begin / %s", name);
466
+ err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
467
+ if (err)
468
+ break;
469
+
470
+ snprintf(buf, sizeof(buf), "%s / trace end", name);
471
+ err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
472
+ if (err)
473
+ break;
474
+ }
475
+
466476 return err;
467477 }
468478
....@@ -487,21 +497,115 @@
487497 return 0;
488498 }
489499
490
-int db_export__call_return(struct db_export *dbe, struct call_return *cr)
500
+int db_export__call_return(struct db_export *dbe, struct call_return *cr,
501
+ u64 *parent_db_id)
491502 {
492503 int err;
493
-
494
- if (cr->db_id)
495
- return 0;
496504
497505 err = db_export__call_path(dbe, cr->cp);
498506 if (err)
499507 return err;
500508
501
- cr->db_id = ++dbe->call_return_last_db_id;
509
+ if (!cr->db_id)
510
+ cr->db_id = ++dbe->call_return_last_db_id;
511
+
512
+ if (parent_db_id) {
513
+ if (!*parent_db_id)
514
+ *parent_db_id = ++dbe->call_return_last_db_id;
515
+ cr->parent_db_id = *parent_db_id;
516
+ }
502517
503518 if (dbe->export_call_return)
504519 return dbe->export_call_return(dbe, cr);
505520
506521 return 0;
507522 }
523
+
524
+static int db_export__pid_tid(struct db_export *dbe, struct machine *machine,
525
+ pid_t pid, pid_t tid, u64 *db_id,
526
+ struct comm **comm_ptr, bool *is_idle)
527
+{
528
+ struct thread *thread = machine__find_thread(machine, pid, tid);
529
+ struct thread *main_thread;
530
+ int err = 0;
531
+
532
+ if (!thread || !thread->comm_set)
533
+ goto out_put;
534
+
535
+ *is_idle = !thread->pid_ && !thread->tid;
536
+
537
+ main_thread = thread__main_thread(machine, thread);
538
+
539
+ err = db_export__threads(dbe, thread, main_thread, machine, comm_ptr);
540
+
541
+ *db_id = thread->db_id;
542
+
543
+ thread__put(main_thread);
544
+out_put:
545
+ thread__put(thread);
546
+
547
+ return err;
548
+}
549
+
550
+int db_export__switch(struct db_export *dbe, union perf_event *event,
551
+ struct perf_sample *sample, struct machine *machine)
552
+{
553
+ bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
554
+ bool out_preempt = out &&
555
+ (event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT);
556
+ int flags = out | (out_preempt << 1);
557
+ bool is_idle_a = false, is_idle_b = false;
558
+ u64 th_a_id = 0, th_b_id = 0;
559
+ u64 comm_out_id, comm_in_id;
560
+ struct comm *comm_a = NULL;
561
+ struct comm *comm_b = NULL;
562
+ u64 th_out_id, th_in_id;
563
+ u64 db_id;
564
+ int err;
565
+
566
+ err = db_export__machine(dbe, machine);
567
+ if (err)
568
+ return err;
569
+
570
+ err = db_export__pid_tid(dbe, machine, sample->pid, sample->tid,
571
+ &th_a_id, &comm_a, &is_idle_a);
572
+ if (err)
573
+ return err;
574
+
575
+ if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
576
+ pid_t pid = event->context_switch.next_prev_pid;
577
+ pid_t tid = event->context_switch.next_prev_tid;
578
+
579
+ err = db_export__pid_tid(dbe, machine, pid, tid, &th_b_id,
580
+ &comm_b, &is_idle_b);
581
+ if (err)
582
+ return err;
583
+ }
584
+
585
+ /*
586
+ * Do not export if both threads are unknown (i.e. not being traced),
587
+ * or one is unknown and the other is the idle task.
588
+ */
589
+ if ((!th_a_id || is_idle_a) && (!th_b_id || is_idle_b))
590
+ return 0;
591
+
592
+ db_id = ++dbe->context_switch_last_db_id;
593
+
594
+ if (out) {
595
+ th_out_id = th_a_id;
596
+ th_in_id = th_b_id;
597
+ comm_out_id = comm_a ? comm_a->db_id : 0;
598
+ comm_in_id = comm_b ? comm_b->db_id : 0;
599
+ } else {
600
+ th_out_id = th_b_id;
601
+ th_in_id = th_a_id;
602
+ comm_out_id = comm_b ? comm_b->db_id : 0;
603
+ comm_in_id = comm_a ? comm_a->db_id : 0;
604
+ }
605
+
606
+ if (dbe->export_context_switch)
607
+ return dbe->export_context_switch(dbe, db_id, machine, sample,
608
+ th_out_id, comm_out_id,
609
+ th_in_id, comm_in_id, flags);
610
+ return 0;
611
+}