aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2019-02-28 08:00:24 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-03-01 12:50:47 -0500
commitf435887ec0c941b97301bd6ed1f3e4b5200df409 (patch)
treee9a1be1b4803aa39ae58d93b000b9e773bbd35ef
parent076333870c2f5bdd9b6d31e7ca1909cf0c84cbfa (diff)
perf db-export: Add calls parent_id to enable creation of call trees
The call_path can be used to find the parent symbol for a call but not the exact parent call. To do that add parent_id to the call_return export. This enables the creation of a call tree from the exported data. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Link: https://lkml.kernel.org/n/tip-6j7tzdxo67cox6kan7k22oo6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/db-export.c15
-rw-r--r--tools/perf/util/db-export.h3
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c8
-rw-r--r--tools/perf/util/thread-stack.c16
-rw-r--r--tools/perf/util/thread-stack.h6
5 files changed, 35 insertions, 13 deletions
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index de9b4769d06c..d7315a00c731 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -510,18 +510,23 @@ int db_export__call_path(struct db_export *dbe, struct call_path *cp)
510 return 0; 510 return 0;
511} 511}
512 512
513int db_export__call_return(struct db_export *dbe, struct call_return *cr) 513int db_export__call_return(struct db_export *dbe, struct call_return *cr,
514 u64 *parent_db_id)
514{ 515{
515 int err; 516 int err;
516 517
517 if (cr->db_id)
518 return 0;
519
520 err = db_export__call_path(dbe, cr->cp); 518 err = db_export__call_path(dbe, cr->cp);
521 if (err) 519 if (err)
522 return err; 520 return err;
523 521
524 cr->db_id = ++dbe->call_return_last_db_id; 522 if (!cr->db_id)
523 cr->db_id = ++dbe->call_return_last_db_id;
524
525 if (parent_db_id) {
526 if (!*parent_db_id)
527 *parent_db_id = ++dbe->call_return_last_db_id;
528 cr->parent_db_id = *parent_db_id;
529 }
525 530
526 if (dbe->export_call_return) 531 if (dbe->export_call_return)
527 return dbe->export_call_return(dbe, cr); 532 return dbe->export_call_return(dbe, cr);
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index 67bc6b8ad2d6..4e2424c89df9 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -104,6 +104,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
104int db_export__branch_types(struct db_export *dbe); 104int db_export__branch_types(struct db_export *dbe);
105 105
106int db_export__call_path(struct db_export *dbe, struct call_path *cp); 106int db_export__call_path(struct db_export *dbe, struct call_path *cp);
107int db_export__call_return(struct db_export *dbe, struct call_return *cr); 107int db_export__call_return(struct db_export *dbe, struct call_return *cr,
108 u64 *parent_db_id);
108 109
109#endif 110#endif
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0e17db41b49b..09604c6508f0 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1173,7 +1173,7 @@ static int python_export_call_return(struct db_export *dbe,
1173 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; 1173 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
1174 PyObject *t; 1174 PyObject *t;
1175 1175
1176 t = tuple_new(11); 1176 t = tuple_new(12);
1177 1177
1178 tuple_set_u64(t, 0, cr->db_id); 1178 tuple_set_u64(t, 0, cr->db_id);
1179 tuple_set_u64(t, 1, cr->thread->db_id); 1179 tuple_set_u64(t, 1, cr->thread->db_id);
@@ -1186,6 +1186,7 @@ static int python_export_call_return(struct db_export *dbe,
1186 tuple_set_u64(t, 8, cr->return_ref); 1186 tuple_set_u64(t, 8, cr->return_ref);
1187 tuple_set_u64(t, 9, cr->cp->parent->db_id); 1187 tuple_set_u64(t, 9, cr->cp->parent->db_id);
1188 tuple_set_s32(t, 10, cr->flags); 1188 tuple_set_s32(t, 10, cr->flags);
1189 tuple_set_u64(t, 11, cr->parent_db_id);
1189 1190
1190 call_object(tables->call_return_handler, t, "call_return_table"); 1191 call_object(tables->call_return_handler, t, "call_return_table");
1191 1192
@@ -1194,11 +1195,12 @@ static int python_export_call_return(struct db_export *dbe,
1194 return 0; 1195 return 0;
1195} 1196}
1196 1197
1197static int python_process_call_return(struct call_return *cr, void *data) 1198static int python_process_call_return(struct call_return *cr, u64 *parent_db_id,
1199 void *data)
1198{ 1200{
1199 struct db_export *dbe = data; 1201 struct db_export *dbe = data;
1200 1202
1201 return db_export__call_return(dbe, cr); 1203 return db_export__call_return(dbe, cr, parent_db_id);
1202} 1204}
1203 1205
1204static void python_process_general_event(struct perf_sample *sample, 1206static void python_process_general_event(struct perf_sample *sample,
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index a8b45168513c..41942c2aaa18 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -49,6 +49,7 @@ enum retpoline_state_t {
49 * @timestamp: timestamp (if known) 49 * @timestamp: timestamp (if known)
50 * @ref: external reference (e.g. db_id of sample) 50 * @ref: external reference (e.g. db_id of sample)
51 * @branch_count: the branch count when the entry was created 51 * @branch_count: the branch count when the entry was created
52 * @db_id: id used for db-export
52 * @cp: call path 53 * @cp: call path
53 * @no_call: a 'call' was not seen 54 * @no_call: a 'call' was not seen
54 * @trace_end: a 'call' but trace ended 55 * @trace_end: a 'call' but trace ended
@@ -59,6 +60,7 @@ struct thread_stack_entry {
59 u64 timestamp; 60 u64 timestamp;
60 u64 ref; 61 u64 ref;
61 u64 branch_count; 62 u64 branch_count;
63 u64 db_id;
62 struct call_path *cp; 64 struct call_path *cp;
63 bool no_call; 65 bool no_call;
64 bool trace_end; 66 bool trace_end;
@@ -280,12 +282,14 @@ static int thread_stack__call_return(struct thread *thread,
280 .comm = ts->comm, 282 .comm = ts->comm,
281 .db_id = 0, 283 .db_id = 0,
282 }; 284 };
285 u64 *parent_db_id;
283 286
284 tse = &ts->stack[idx]; 287 tse = &ts->stack[idx];
285 cr.cp = tse->cp; 288 cr.cp = tse->cp;
286 cr.call_time = tse->timestamp; 289 cr.call_time = tse->timestamp;
287 cr.return_time = timestamp; 290 cr.return_time = timestamp;
288 cr.branch_count = ts->branch_count - tse->branch_count; 291 cr.branch_count = ts->branch_count - tse->branch_count;
292 cr.db_id = tse->db_id;
289 cr.call_ref = tse->ref; 293 cr.call_ref = tse->ref;
290 cr.return_ref = ref; 294 cr.return_ref = ref;
291 if (tse->no_call) 295 if (tse->no_call)
@@ -295,7 +299,14 @@ static int thread_stack__call_return(struct thread *thread,
295 if (tse->non_call) 299 if (tse->non_call)
296 cr.flags |= CALL_RETURN_NON_CALL; 300 cr.flags |= CALL_RETURN_NON_CALL;
297 301
298 return crp->process(&cr, crp->data); 302 /*
303 * The parent db_id must be assigned before exporting the child. Note
304 * it is not possible to export the parent first because its information
305 * is not yet complete because its 'return' has not yet been processed.
306 */
307 parent_db_id = idx ? &(tse - 1)->db_id : NULL;
308
309 return crp->process(&cr, parent_db_id, crp->data);
299} 310}
300 311
301static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts) 312static int __thread_stack__flush(struct thread *thread, struct thread_stack *ts)
@@ -484,7 +495,7 @@ void thread_stack__sample(struct thread *thread, int cpu,
484} 495}
485 496
486struct call_return_processor * 497struct call_return_processor *
487call_return_processor__new(int (*process)(struct call_return *cr, void *data), 498call_return_processor__new(int (*process)(struct call_return *cr, u64 *parent_db_id, void *data),
488 void *data) 499 void *data)
489{ 500{
490 struct call_return_processor *crp; 501 struct call_return_processor *crp;
@@ -537,6 +548,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
537 tse->no_call = no_call; 548 tse->no_call = no_call;
538 tse->trace_end = trace_end; 549 tse->trace_end = trace_end;
539 tse->non_call = false; 550 tse->non_call = false;
551 tse->db_id = 0;
540 552
541 return 0; 553 return 0;
542} 554}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index b7c04e19ad41..9c45f947f5a9 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -55,6 +55,7 @@ enum {
55 * @call_ref: external reference to 'call' sample (e.g. db_id) 55 * @call_ref: external reference to 'call' sample (e.g. db_id)
56 * @return_ref: external reference to 'return' sample (e.g. db_id) 56 * @return_ref: external reference to 'return' sample (e.g. db_id)
57 * @db_id: id used for db-export 57 * @db_id: id used for db-export
58 * @parent_db_id: id of parent call used for db-export
58 * @flags: Call/Return flags 59 * @flags: Call/Return flags
59 */ 60 */
60struct call_return { 61struct call_return {
@@ -67,6 +68,7 @@ struct call_return {
67 u64 call_ref; 68 u64 call_ref;
68 u64 return_ref; 69 u64 return_ref;
69 u64 db_id; 70 u64 db_id;
71 u64 parent_db_id;
70 u32 flags; 72 u32 flags;
71}; 73};
72 74
@@ -79,7 +81,7 @@ struct call_return {
79 */ 81 */
80struct call_return_processor { 82struct call_return_processor {
81 struct call_path_root *cpr; 83 struct call_path_root *cpr;
82 int (*process)(struct call_return *cr, void *data); 84 int (*process)(struct call_return *cr, u64 *parent_db_id, void *data);
83 void *data; 85 void *data;
84}; 86};
85 87
@@ -93,7 +95,7 @@ void thread_stack__free(struct thread *thread);
93size_t thread_stack__depth(struct thread *thread, int cpu); 95size_t thread_stack__depth(struct thread *thread, int cpu);
94 96
95struct call_return_processor * 97struct call_return_processor *
96call_return_processor__new(int (*process)(struct call_return *cr, void *data), 98call_return_processor__new(int (*process)(struct call_return *cr, u64 *parent_db_id, void *data),
97 void *data); 99 void *data);
98void call_return_processor__free(struct call_return_processor *crp); 100void call_return_processor__free(struct call_return_processor *crp);
99int thread_stack__process(struct thread *thread, struct comm *comm, 101int thread_stack__process(struct thread *thread, struct comm *comm,