diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-11-07 00:21:46 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-11-07 00:21:46 -0500 |
commit | 322cd21fc196575d922e5e8bd8d5730a91c2b73d (patch) | |
tree | 9bfe532ec54a13c0f2290b0e5c0fedf1246038c0 /tools/perf/util/scripting-engines/trace-event-python.c | |
parent | 05b2537e8dc778bb00284f8fc86b83797b8f1d37 (diff) | |
parent | daa01794a4a36a1da1b09a529adec0c8c0b94ab2 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
Infrastructure changes:
- Add gzip decompression support for kernel modules (Namhyung Kim)
- More prep patches for Intel PT, including a a thread stack and
more stuff made available via the database export mechanism (Adrian Hunter)
- Optimize checking that tracepoint events are defined in perf script perl/python (Jiri Olsa)
- Do not free pevent when deleting tracepoint evsel (Jiri Olsa)
- Fix build-id matching for vmlinux (Namhyung Kim)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 152 |
1 files changed, 121 insertions, 31 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 2fd7ee8f18c7..d808a328f4dc 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <stdbool.h> | 27 | #include <stdbool.h> |
28 | #include <errno.h> | 28 | #include <errno.h> |
29 | #include <linux/bitmap.h> | ||
29 | 30 | ||
30 | #include "../../perf.h" | 31 | #include "../../perf.h" |
31 | #include "../debug.h" | 32 | #include "../debug.h" |
@@ -37,6 +38,7 @@ | |||
37 | #include "../comm.h" | 38 | #include "../comm.h" |
38 | #include "../machine.h" | 39 | #include "../machine.h" |
39 | #include "../db-export.h" | 40 | #include "../db-export.h" |
41 | #include "../thread-stack.h" | ||
40 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
41 | #include "../machine.h" | 43 | #include "../machine.h" |
42 | 44 | ||
@@ -45,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void); | |||
45 | #define FTRACE_MAX_EVENT \ | 47 | #define FTRACE_MAX_EVENT \ |
46 | ((1 << (sizeof(unsigned short) * 8)) - 1) | 48 | ((1 << (sizeof(unsigned short) * 8)) - 1) |
47 | 49 | ||
48 | struct event_format *events[FTRACE_MAX_EVENT]; | 50 | static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT); |
49 | 51 | ||
50 | #define MAX_FIELDS 64 | 52 | #define MAX_FIELDS 64 |
51 | #define N_COMMON_FIELDS 7 | 53 | #define N_COMMON_FIELDS 7 |
@@ -66,7 +68,10 @@ struct tables { | |||
66 | PyObject *comm_thread_handler; | 68 | PyObject *comm_thread_handler; |
67 | PyObject *dso_handler; | 69 | PyObject *dso_handler; |
68 | PyObject *symbol_handler; | 70 | PyObject *symbol_handler; |
71 | PyObject *branch_type_handler; | ||
69 | PyObject *sample_handler; | 72 | PyObject *sample_handler; |
73 | PyObject *call_path_handler; | ||
74 | PyObject *call_return_handler; | ||
70 | bool db_export_mode; | 75 | bool db_export_mode; |
71 | }; | 76 | }; |
72 | 77 | ||
@@ -251,31 +256,6 @@ static void define_event_symbols(struct event_format *event, | |||
251 | define_event_symbols(event, ev_name, args->next); | 256 | define_event_symbols(event, ev_name, args->next); |
252 | } | 257 | } |
253 | 258 | ||
254 | static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | ||
255 | { | ||
256 | static char ev_name[256]; | ||
257 | struct event_format *event; | ||
258 | int type = evsel->attr.config; | ||
259 | |||
260 | /* | ||
261 | * XXX: Do we really need to cache this since now we have evsel->tp_format | ||
262 | * cached already? Need to re-read this "cache" routine that as well calls | ||
263 | * define_event_symbols() :-\ | ||
264 | */ | ||
265 | if (events[type]) | ||
266 | return events[type]; | ||
267 | |||
268 | events[type] = event = evsel->tp_format; | ||
269 | if (!event) | ||
270 | return NULL; | ||
271 | |||
272 | sprintf(ev_name, "%s__%s", event->system, event->name); | ||
273 | |||
274 | define_event_symbols(event, ev_name, event->print_fmt.args); | ||
275 | |||
276 | return event; | ||
277 | } | ||
278 | |||
279 | static PyObject *get_field_numeric_entry(struct event_format *event, | 259 | static PyObject *get_field_numeric_entry(struct event_format *event, |
280 | struct format_field *field, void *data) | 260 | struct format_field *field, void *data) |
281 | { | 261 | { |
@@ -399,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
399 | struct thread *thread, | 379 | struct thread *thread, |
400 | struct addr_location *al) | 380 | struct addr_location *al) |
401 | { | 381 | { |
382 | struct event_format *event = evsel->tp_format; | ||
402 | PyObject *handler, *context, *t, *obj, *callchain; | 383 | PyObject *handler, *context, *t, *obj, *callchain; |
403 | PyObject *dict = NULL; | 384 | PyObject *dict = NULL; |
404 | static char handler_name[256]; | 385 | static char handler_name[256]; |
405 | struct format_field *field; | 386 | struct format_field *field; |
406 | unsigned long s, ns; | 387 | unsigned long s, ns; |
407 | struct event_format *event; | ||
408 | unsigned n = 0; | 388 | unsigned n = 0; |
409 | int pid; | 389 | int pid; |
410 | int cpu = sample->cpu; | 390 | int cpu = sample->cpu; |
@@ -416,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
416 | if (!t) | 396 | if (!t) |
417 | Py_FatalError("couldn't create Python tuple"); | 397 | Py_FatalError("couldn't create Python tuple"); |
418 | 398 | ||
419 | event = find_cache_event(evsel); | ||
420 | if (!event) | 399 | if (!event) |
421 | die("ug! no event found for type %d", (int)evsel->attr.config); | 400 | die("ug! no event found for type %d", (int)evsel->attr.config); |
422 | 401 | ||
@@ -424,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
424 | 403 | ||
425 | sprintf(handler_name, "%s__%s", event->system, event->name); | 404 | sprintf(handler_name, "%s__%s", event->system, event->name); |
426 | 405 | ||
406 | if (!test_and_set_bit(event->id, events_defined)) | ||
407 | define_event_symbols(event, handler_name, event->print_fmt.args); | ||
408 | |||
427 | handler = get_handler(handler_name); | 409 | handler = get_handler(handler_name); |
428 | if (!handler) { | 410 | if (!handler) { |
429 | dict = PyDict_New(); | 411 | dict = PyDict_New(); |
@@ -664,13 +646,31 @@ static int python_export_symbol(struct db_export *dbe, struct symbol *sym, | |||
664 | return 0; | 646 | return 0; |
665 | } | 647 | } |
666 | 648 | ||
649 | static int python_export_branch_type(struct db_export *dbe, u32 branch_type, | ||
650 | const char *name) | ||
651 | { | ||
652 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
653 | PyObject *t; | ||
654 | |||
655 | t = tuple_new(2); | ||
656 | |||
657 | tuple_set_s32(t, 0, branch_type); | ||
658 | tuple_set_string(t, 1, name); | ||
659 | |||
660 | call_object(tables->branch_type_handler, t, "branch_type_table"); | ||
661 | |||
662 | Py_DECREF(t); | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int python_export_sample(struct db_export *dbe, | 667 | static int python_export_sample(struct db_export *dbe, |
668 | struct export_sample *es) | 668 | struct export_sample *es) |
669 | { | 669 | { |
670 | struct tables *tables = container_of(dbe, struct tables, dbe); | 670 | struct tables *tables = container_of(dbe, struct tables, dbe); |
671 | PyObject *t; | 671 | PyObject *t; |
672 | 672 | ||
673 | t = tuple_new(19); | 673 | t = tuple_new(21); |
674 | 674 | ||
675 | tuple_set_u64(t, 0, es->db_id); | 675 | tuple_set_u64(t, 0, es->db_id); |
676 | tuple_set_u64(t, 1, es->evsel->db_id); | 676 | tuple_set_u64(t, 1, es->evsel->db_id); |
@@ -691,6 +691,8 @@ static int python_export_sample(struct db_export *dbe, | |||
691 | tuple_set_u64(t, 16, es->sample->weight); | 691 | tuple_set_u64(t, 16, es->sample->weight); |
692 | tuple_set_u64(t, 17, es->sample->transaction); | 692 | tuple_set_u64(t, 17, es->sample->transaction); |
693 | tuple_set_u64(t, 18, es->sample->data_src); | 693 | tuple_set_u64(t, 18, es->sample->data_src); |
694 | tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); | ||
695 | tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | ||
694 | 696 | ||
695 | call_object(tables->sample_handler, t, "sample_table"); | 697 | call_object(tables->sample_handler, t, "sample_table"); |
696 | 698 | ||
@@ -699,6 +701,64 @@ static int python_export_sample(struct db_export *dbe, | |||
699 | return 0; | 701 | return 0; |
700 | } | 702 | } |
701 | 703 | ||
704 | static int python_export_call_path(struct db_export *dbe, struct call_path *cp) | ||
705 | { | ||
706 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
707 | PyObject *t; | ||
708 | u64 parent_db_id, sym_db_id; | ||
709 | |||
710 | parent_db_id = cp->parent ? cp->parent->db_id : 0; | ||
711 | sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0; | ||
712 | |||
713 | t = tuple_new(4); | ||
714 | |||
715 | tuple_set_u64(t, 0, cp->db_id); | ||
716 | tuple_set_u64(t, 1, parent_db_id); | ||
717 | tuple_set_u64(t, 2, sym_db_id); | ||
718 | tuple_set_u64(t, 3, cp->ip); | ||
719 | |||
720 | call_object(tables->call_path_handler, t, "call_path_table"); | ||
721 | |||
722 | Py_DECREF(t); | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static int python_export_call_return(struct db_export *dbe, | ||
728 | struct call_return *cr) | ||
729 | { | ||
730 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
731 | u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; | ||
732 | PyObject *t; | ||
733 | |||
734 | t = tuple_new(11); | ||
735 | |||
736 | tuple_set_u64(t, 0, cr->db_id); | ||
737 | tuple_set_u64(t, 1, cr->thread->db_id); | ||
738 | tuple_set_u64(t, 2, comm_db_id); | ||
739 | tuple_set_u64(t, 3, cr->cp->db_id); | ||
740 | tuple_set_u64(t, 4, cr->call_time); | ||
741 | tuple_set_u64(t, 5, cr->return_time); | ||
742 | tuple_set_u64(t, 6, cr->branch_count); | ||
743 | tuple_set_u64(t, 7, cr->call_ref); | ||
744 | tuple_set_u64(t, 8, cr->return_ref); | ||
745 | tuple_set_u64(t, 9, cr->cp->parent->db_id); | ||
746 | tuple_set_s32(t, 10, cr->flags); | ||
747 | |||
748 | call_object(tables->call_return_handler, t, "call_return_table"); | ||
749 | |||
750 | Py_DECREF(t); | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int python_process_call_return(struct call_return *cr, void *data) | ||
756 | { | ||
757 | struct db_export *dbe = data; | ||
758 | |||
759 | return db_export__call_return(dbe, cr); | ||
760 | } | ||
761 | |||
702 | static void python_process_general_event(struct perf_sample *sample, | 762 | static void python_process_general_event(struct perf_sample *sample, |
703 | struct perf_evsel *evsel, | 763 | struct perf_evsel *evsel, |
704 | struct thread *thread, | 764 | struct thread *thread, |
@@ -831,7 +891,9 @@ error: | |||
831 | static void set_table_handlers(struct tables *tables) | 891 | static void set_table_handlers(struct tables *tables) |
832 | { | 892 | { |
833 | const char *perf_db_export_mode = "perf_db_export_mode"; | 893 | const char *perf_db_export_mode = "perf_db_export_mode"; |
834 | PyObject *db_export_mode; | 894 | const char *perf_db_export_calls = "perf_db_export_calls"; |
895 | PyObject *db_export_mode, *db_export_calls; | ||
896 | bool export_calls = false; | ||
835 | int ret; | 897 | int ret; |
836 | 898 | ||
837 | memset(tables, 0, sizeof(struct tables)); | 899 | memset(tables, 0, sizeof(struct tables)); |
@@ -848,6 +910,23 @@ static void set_table_handlers(struct tables *tables) | |||
848 | if (!ret) | 910 | if (!ret) |
849 | return; | 911 | return; |
850 | 912 | ||
913 | tables->dbe.crp = NULL; | ||
914 | db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | ||
915 | if (db_export_calls) { | ||
916 | ret = PyObject_IsTrue(db_export_calls); | ||
917 | if (ret == -1) | ||
918 | handler_call_die(perf_db_export_calls); | ||
919 | export_calls = !!ret; | ||
920 | } | ||
921 | |||
922 | if (export_calls) { | ||
923 | tables->dbe.crp = | ||
924 | call_return_processor__new(python_process_call_return, | ||
925 | &tables->dbe); | ||
926 | if (!tables->dbe.crp) | ||
927 | Py_FatalError("failed to create calls processor"); | ||
928 | } | ||
929 | |||
851 | tables->db_export_mode = true; | 930 | tables->db_export_mode = true; |
852 | /* | 931 | /* |
853 | * Reserve per symbol space for symbol->db_id via symbol__priv() | 932 | * Reserve per symbol space for symbol->db_id via symbol__priv() |
@@ -861,7 +940,10 @@ static void set_table_handlers(struct tables *tables) | |||
861 | SET_TABLE_HANDLER(comm_thread); | 940 | SET_TABLE_HANDLER(comm_thread); |
862 | SET_TABLE_HANDLER(dso); | 941 | SET_TABLE_HANDLER(dso); |
863 | SET_TABLE_HANDLER(symbol); | 942 | SET_TABLE_HANDLER(symbol); |
943 | SET_TABLE_HANDLER(branch_type); | ||
864 | SET_TABLE_HANDLER(sample); | 944 | SET_TABLE_HANDLER(sample); |
945 | SET_TABLE_HANDLER(call_path); | ||
946 | SET_TABLE_HANDLER(call_return); | ||
865 | } | 947 | } |
866 | 948 | ||
867 | /* | 949 | /* |
@@ -910,6 +992,12 @@ static int python_start_script(const char *script, int argc, const char **argv) | |||
910 | 992 | ||
911 | set_table_handlers(tables); | 993 | set_table_handlers(tables); |
912 | 994 | ||
995 | if (tables->db_export_mode) { | ||
996 | err = db_export__branch_types(&tables->dbe); | ||
997 | if (err) | ||
998 | goto error; | ||
999 | } | ||
1000 | |||
913 | return err; | 1001 | return err; |
914 | error: | 1002 | error: |
915 | Py_Finalize(); | 1003 | Py_Finalize(); |
@@ -920,7 +1008,9 @@ error: | |||
920 | 1008 | ||
921 | static int python_flush_script(void) | 1009 | static int python_flush_script(void) |
922 | { | 1010 | { |
923 | return 0; | 1011 | struct tables *tables = &tables_global; |
1012 | |||
1013 | return db_export__flush(&tables->dbe); | ||
924 | } | 1014 | } |
925 | 1015 | ||
926 | /* | 1016 | /* |