diff options
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index fbd05242b4e5..091bce67844c 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "../thread-stack.h" | 41 | #include "../thread-stack.h" |
42 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
43 | #include "../machine.h" | 43 | #include "../machine.h" |
44 | #include "../call-path.h" | ||
44 | #include "thread_map.h" | 45 | #include "thread_map.h" |
45 | #include "cpumap.h" | 46 | #include "cpumap.h" |
46 | #include "stat.h" | 47 | #include "stat.h" |
@@ -323,7 +324,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
323 | if (!symbol_conf.use_callchain || !sample->callchain) | 324 | if (!symbol_conf.use_callchain || !sample->callchain) |
324 | goto exit; | 325 | goto exit; |
325 | 326 | ||
326 | if (thread__resolve_callchain(al->thread, evsel, | 327 | if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, |
327 | sample, NULL, NULL, | 328 | sample, NULL, NULL, |
328 | scripting_max_stack) != 0) { | 329 | scripting_max_stack) != 0) { |
329 | pr_err("Failed to resolve callchain. Skipping\n"); | 330 | pr_err("Failed to resolve callchain. Skipping\n"); |
@@ -681,7 +682,7 @@ static int python_export_sample(struct db_export *dbe, | |||
681 | struct tables *tables = container_of(dbe, struct tables, dbe); | 682 | struct tables *tables = container_of(dbe, struct tables, dbe); |
682 | PyObject *t; | 683 | PyObject *t; |
683 | 684 | ||
684 | t = tuple_new(21); | 685 | t = tuple_new(22); |
685 | 686 | ||
686 | tuple_set_u64(t, 0, es->db_id); | 687 | tuple_set_u64(t, 0, es->db_id); |
687 | tuple_set_u64(t, 1, es->evsel->db_id); | 688 | tuple_set_u64(t, 1, es->evsel->db_id); |
@@ -704,6 +705,7 @@ static int python_export_sample(struct db_export *dbe, | |||
704 | tuple_set_u64(t, 18, es->sample->data_src); | 705 | tuple_set_u64(t, 18, es->sample->data_src); |
705 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); | 706 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); |
706 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | 707 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); |
708 | tuple_set_u64(t, 21, es->call_path_id); | ||
707 | 709 | ||
708 | call_object(tables->sample_handler, t, "sample_table"); | 710 | call_object(tables->sample_handler, t, "sample_table"); |
709 | 711 | ||
@@ -998,8 +1000,10 @@ static void set_table_handlers(struct tables *tables) | |||
998 | { | 1000 | { |
999 | const char *perf_db_export_mode = "perf_db_export_mode"; | 1001 | const char *perf_db_export_mode = "perf_db_export_mode"; |
1000 | const char *perf_db_export_calls = "perf_db_export_calls"; | 1002 | const char *perf_db_export_calls = "perf_db_export_calls"; |
1001 | PyObject *db_export_mode, *db_export_calls; | 1003 | const char *perf_db_export_callchains = "perf_db_export_callchains"; |
1004 | PyObject *db_export_mode, *db_export_calls, *db_export_callchains; | ||
1002 | bool export_calls = false; | 1005 | bool export_calls = false; |
1006 | bool export_callchains = false; | ||
1003 | int ret; | 1007 | int ret; |
1004 | 1008 | ||
1005 | memset(tables, 0, sizeof(struct tables)); | 1009 | memset(tables, 0, sizeof(struct tables)); |
@@ -1016,6 +1020,7 @@ static void set_table_handlers(struct tables *tables) | |||
1016 | if (!ret) | 1020 | if (!ret) |
1017 | return; | 1021 | return; |
1018 | 1022 | ||
1023 | /* handle export calls */ | ||
1019 | tables->dbe.crp = NULL; | 1024 | tables->dbe.crp = NULL; |
1020 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | 1025 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); |
1021 | if (db_export_calls) { | 1026 | if (db_export_calls) { |
@@ -1033,6 +1038,33 @@ static void set_table_handlers(struct tables *tables) | |||
1033 | Py_FatalError("failed to create calls processor"); | 1038 | Py_FatalError("failed to create calls processor"); |
1034 | } | 1039 | } |
1035 | 1040 | ||
1041 | /* handle export callchains */ | ||
1042 | tables->dbe.cpr = NULL; | ||
1043 | db_export_callchains = PyDict_GetItemString(main_dict, | ||
1044 | perf_db_export_callchains); | ||
1045 | if (db_export_callchains) { | ||
1046 | ret = PyObject_IsTrue(db_export_callchains); | ||
1047 | if (ret == -1) | ||
1048 | handler_call_die(perf_db_export_callchains); | ||
1049 | export_callchains = !!ret; | ||
1050 | } | ||
1051 | |||
1052 | if (export_callchains) { | ||
1053 | /* | ||
1054 | * Attempt to use the call path root from the call return | ||
1055 | * processor, if the call return processor is in use. Otherwise, | ||
1056 | * we allocate a new call path root. This prevents exporting | ||
1057 | * duplicate call path ids when both are in use simultaniously. | ||
1058 | */ | ||
1059 | if (tables->dbe.crp) | ||
1060 | tables->dbe.cpr = tables->dbe.crp->cpr; | ||
1061 | else | ||
1062 | tables->dbe.cpr = call_path_root__new(); | ||
1063 | |||
1064 | if (!tables->dbe.cpr) | ||
1065 | Py_FatalError("failed to create calls processor"); | ||
1066 | } | ||
1067 | |||
1036 | tables->db_export_mode = true; | 1068 | tables->db_export_mode = true; |
1037 | /* | 1069 | /* |
1038 | * Reserve per symbol space for symbol->db_id via symbol__priv() | 1070 | * Reserve per symbol space for symbol->db_id via symbol__priv() |