From fcf65bf149afa91b875ffde4455967cb63ee0be9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 7 Aug 2012 09:58:03 -0300 Subject: perf evsel: Cache associated event_format We already lookup the associated event_format when reading the perf.data header, so that we can cache the tracepoint name in evsel->name, so do it a little further and save the event_format itself, so that we can avoid relookups in tools that need to access it. Change the tools to take the most obvious advantage, when they were using pevent_find_event directly. More work is needed for further removing the need of a pointer to pevent, such as when asking for event field values ("common_pid" and the other common fields and per event_format fields). This is something that was planned but only got actually done when Andrey Wagin needed to do this lookup at perf_tool->sample() time, when we don't have access to pevent (session->pevent) to use with pevent_find_event(). Cc: Andrey Wagin Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/n/tip-txkvew2ckko0b594ae8fbnyk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- .../util/scripting-engines/trace-event-python.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index ce4d1b0c386..8006978d839 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -27,6 +27,7 @@ #include #include "../../perf.h" +#include "../evsel.h" #include "../util.h" #include "../event.h" #include "../thread.h" @@ -194,16 +195,21 @@ static void define_event_symbols(struct event_format *event, define_event_symbols(event, ev_name, args->next); } -static inline -struct event_format *find_cache_event(struct pevent *pevent, int type) +static inline struct event_format *find_cache_event(struct perf_evsel *evsel) { static char ev_name[256]; struct event_format *event; + int type = evsel->attr.config; + /* + * XXX: Do we really need to cache this since now we have evsel->tp_format + * cached already? Need to re-read this "cache" routine that as well calls + * define_event_symbols() :-\ + */ if (events[type]) return events[type]; - events[type] = event = pevent_find_event(pevent, type); + events[type] = event = evsel->tp_format; if (!event) return NULL; @@ -217,7 +223,7 @@ struct event_format *find_cache_event(struct pevent *pevent, int type) static void python_process_event(union perf_event *perf_event __unused, struct pevent *pevent, struct perf_sample *sample, - struct perf_evsel *evsel __unused, + struct perf_evsel *evsel, struct machine *machine __unused, struct thread *thread) { @@ -228,7 +234,6 @@ static void python_process_event(union perf_event *perf_event __unused, unsigned long s, ns; struct event_format *event; unsigned n = 0; - int type; int pid; int cpu = sample->cpu; void *data = sample->raw_data; @@ -239,11 +244,9 @@ static void python_process_event(union perf_event *perf_event __unused, if (!t) Py_FatalError("couldn't create Python tuple"); - type = trace_parse_common_type(pevent, data); - - event = find_cache_event(pevent, type); + event = find_cache_event(evsel); if (!event) - die("ug! no event found for type %d", type); + die("ug! no event found for type %d", (int)evsel->attr.config); pid = trace_parse_common_pid(pevent, data); -- cgit v1.2.3-18-g5258 From 9782243353ec135327a80c76c63464e592949cd1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 7 Aug 2012 23:50:21 -0300 Subject: perf script: Stop using pevent directly We can get all that is needed using just event_format, that is available via evsel->tp_format now. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-2hsr1686epa9f0vx4yg7z2zj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-python.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 8006978d839..df7d33d1de0 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -221,7 +221,6 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) } static void python_process_event(union perf_event *perf_event __unused, - struct pevent *pevent, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __unused, @@ -248,7 +247,7 @@ static void python_process_event(union perf_event *perf_event __unused, if (!event) die("ug! no event found for type %d", (int)evsel->attr.config); - pid = trace_parse_common_pid(pevent, data); + pid = raw_field_value(event, "common_pid", data); sprintf(handler_name, "%s__%s", event->system, event->name); @@ -293,7 +292,7 @@ static void python_process_event(union perf_event *perf_event __unused, offset = field->offset; obj = PyString_FromString((char *)data + offset); } else { /* FIELD_IS_NUMERIC */ - val = read_size(pevent, data + field->offset, + val = read_size(event, data + field->offset, field->size); if (field->flags & FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && -- cgit v1.2.3-18-g5258 From 6a6daec2ae9f097703c1da4925367f1c198c9492 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 8 Aug 2012 17:57:51 +0800 Subject: perf script: Add general python handler to process non-tracepoint events This patch just follows Robert Richter's idea and the commit 37a058ea0 "perf script: Add generic perl handler to process events" to similarly add a python handler for general events other than tracepoints. For non-tracepoint events, this patch will try to find a function named "process_event" in the python script, and pass the event attribute, perf_sample, raw_data in format of raw string. And the python script can use "struct" module's unpack function to disasemble the needed info and process. Signed-off-by: Feng Tang Cc: Andi Kleen Cc: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1344419875-21665-2-git-send-email-feng.tang@intel.com [ committer note: Fixed up wrt da37896, i.e. pevent parm in script event handlers ] Signed-off-by: Arnaldo Carvalho de Melo --- .../util/scripting-engines/trace-event-python.c | 59 +++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index df7d33d1de0..b9010d878b4 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -32,6 +32,7 @@ #include "../event.h" #include "../thread.h" #include "../trace-event.h" +#include "../evsel.h" PyMODINIT_FUNC initperf_trace_context(void); @@ -220,7 +221,7 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void python_process_event(union perf_event *perf_event __unused, +static void python_process_tracepoint(union perf_event *perf_event __unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __unused, @@ -337,6 +338,62 @@ static void python_process_event(union perf_event *perf_event __unused, Py_DECREF(t); } +static void python_process_general_event(union perf_event *perf_event __unused, + struct perf_sample *sample, + struct perf_evsel *evsel, + struct machine *machine __unused, + struct thread *thread __unused) +{ + PyObject *handler, *retval, *t; + static char handler_name[64]; + unsigned n = 0; + void *data = sample->raw_data; + + t = PyTuple_New(MAX_FIELDS); + if (!t) + Py_FatalError("couldn't create Python tuple"); + + snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); + + handler = PyDict_GetItemString(main_dict, handler_name); + if (handler && !PyCallable_Check(handler)) { + handler = NULL; + goto exit; + } + + /* Pass 3 parameters: event_attr, perf_sample, raw data */ + PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)&evsel->attr, sizeof(evsel->attr))); + PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)sample, sizeof(*sample))); + PyTuple_SetItem(t, n++, PyString_FromStringAndSize(data, sample->raw_size)); + + if (_PyTuple_Resize(&t, n) == -1) + Py_FatalError("error resizing Python tuple"); + + retval = PyObject_CallObject(handler, t); + if (retval == NULL) + handler_call_die(handler_name); +exit: + Py_DECREF(t); +} + +static void python_process_event(union perf_event *perf_event, + struct perf_sample *sample, + struct perf_evsel *evsel, + struct machine *machine, + struct thread *thread) +{ + switch (evsel->attr.type) { + case PERF_TYPE_TRACEPOINT: + python_process_tracepoint(perf_event, sample, evsel, + machine, thread); + break; + /* Reserve for future process_hw/sw/raw APIs */ + default: + python_process_general_event(perf_event, sample, evsel, + machine, thread); + } +} + static int run_start_sub(void) { PyObject *handler, *retval; -- cgit v1.2.3-18-g5258 From 73994dc158a24df4af77d0a76c9702f120f7a6ad Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 8 Aug 2012 17:57:52 +0800 Subject: perf script: Replace "struct thread" with "struct addr_location" as a parameter for "process_event()" Both perl and python script start processing events other than trace points, and it's useful to pass the resolved symbol and the dso info to the event handler in script for better analysis and statistics. Struct thread is already a member of struct addr_location, using addr_location will keep the thread info, while providing additional symbol and dso info if exist, so that the script itself doesn't need to bother to do the symbol resolving and dso searching work. Tested-by: David Ahern Signed-off-by: Feng Tang Acked-by: David Ahern Cc: Andi Kleen Cc: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1344419875-21665-3-git-send-email-feng.tang@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-python.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index b9010d878b4..24711b3536d 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -225,7 +225,7 @@ static void python_process_tracepoint(union perf_event *perf_event __unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __unused, - struct thread *thread) + struct addr_location *al) { PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; static char handler_name[256]; @@ -238,6 +238,7 @@ static void python_process_tracepoint(union perf_event *perf_event __unused, int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; + struct thread *thread = al->thread; char *comm = thread->comm; t = PyTuple_New(MAX_FIELDS); @@ -342,7 +343,7 @@ static void python_process_general_event(union perf_event *perf_event __unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __unused, - struct thread *thread __unused) + struct addr_location *al __unused) { PyObject *handler, *retval, *t; static char handler_name[64]; @@ -361,7 +362,7 @@ static void python_process_general_event(union perf_event *perf_event __unused, goto exit; } - /* Pass 3 parameters: event_attr, perf_sample, raw data */ + /* Pass 4 parameters: event_attr, perf_sample, raw data, thread name */ PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)&evsel->attr, sizeof(evsel->attr))); PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)sample, sizeof(*sample))); PyTuple_SetItem(t, n++, PyString_FromStringAndSize(data, sample->raw_size)); @@ -380,17 +381,17 @@ static void python_process_event(union perf_event *perf_event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, - struct thread *thread) + struct addr_location *al) { switch (evsel->attr.type) { case PERF_TYPE_TRACEPOINT: python_process_tracepoint(perf_event, sample, evsel, - machine, thread); + machine, al); break; /* Reserve for future process_hw/sw/raw APIs */ default: python_process_general_event(perf_event, sample, evsel, - machine, thread); + machine, al); } } -- cgit v1.2.3-18-g5258 From fd6b858a1e110c76e701cd9972a284ed2a7bcc33 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 8 Aug 2012 17:57:53 +0800 Subject: perf scripts python: Pass event/thread/dso name and symbol info to event handler in python Also as suggested by Arnaldo, pack all these parameters to a dictionary, which is more expandable for adding new parameters while keeping the compatibility for old scripts. Signed-off-by: Feng Tang Cc: Andi Kleen Cc: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1344419875-21665-4-git-send-email-feng.tang@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- .../util/scripting-engines/trace-event-python.c | 35 ++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 24711b3536d..7e3f57656c5 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -345,15 +345,23 @@ static void python_process_general_event(union perf_event *perf_event __unused, struct machine *machine __unused, struct addr_location *al __unused) { - PyObject *handler, *retval, *t; + PyObject *handler, *retval, *t, *dict; static char handler_name[64]; unsigned n = 0; - void *data = sample->raw_data; + struct thread *thread = al->thread; + /* + * Use the MAX_FIELDS to make the function expandable, though + * currently there is only one itme for the tuple. + */ t = PyTuple_New(MAX_FIELDS); if (!t) Py_FatalError("couldn't create Python tuple"); + dict = PyDict_New(); + if (!dict) + Py_FatalError("couldn't create Python dictionary"); + snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); handler = PyDict_GetItemString(main_dict, handler_name); @@ -362,11 +370,25 @@ static void python_process_general_event(union perf_event *perf_event __unused, goto exit; } - /* Pass 4 parameters: event_attr, perf_sample, raw data, thread name */ - PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)&evsel->attr, sizeof(evsel->attr))); - PyTuple_SetItem(t, n++, PyString_FromStringAndSize((void *)sample, sizeof(*sample))); - PyTuple_SetItem(t, n++, PyString_FromStringAndSize(data, sample->raw_size)); + PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); + PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize( + (const char *)&evsel->attr, sizeof(evsel->attr))); + PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize( + (const char *)sample, sizeof(*sample))); + PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize( + (const char *)sample->raw_data, sample->raw_size)); + PyDict_SetItemString(dict, "comm", + PyString_FromString(thread->comm)); + if (al->map) { + PyDict_SetItemString(dict, "dso", + PyString_FromString(al->map->dso->name)); + } + if (al->sym) { + PyDict_SetItemString(dict, "symbol", + PyString_FromString(al->sym->name)); + } + PyTuple_SetItem(t, n++, dict); if (_PyTuple_Resize(&t, n) == -1) Py_FatalError("error resizing Python tuple"); @@ -374,6 +396,7 @@ static void python_process_general_event(union perf_event *perf_event __unused, if (retval == NULL) handler_call_die(handler_name); exit: + Py_DECREF(dict); Py_DECREF(t); } -- cgit v1.2.3-18-g5258 From 87b6a3ad40ba304ec468b972e979e7e410852476 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 9 Aug 2012 13:46:13 +0800 Subject: perf script python: Correct handler check and spelling errors Correct the checking for handler returned by PyDict_GetItemString(), also fix some spelling error and remove some data code in event_analyzing_sample.py, as suggested by Namhyung Kim. v2: restore back the wrongly removed trace_unhandled() func Signed-off-by: Feng Tang Acked-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Ingo Molnar Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20120809134613.067104c4@feng-i7 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-python.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 7e3f57656c5..afba0972918 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -343,7 +343,7 @@ static void python_process_general_event(union perf_event *perf_event __unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __unused, - struct addr_location *al __unused) + struct addr_location *al) { PyObject *handler, *retval, *t, *dict; static char handler_name[64]; @@ -352,7 +352,7 @@ static void python_process_general_event(union perf_event *perf_event __unused, /* * Use the MAX_FIELDS to make the function expandable, though - * currently there is only one itme for the tuple. + * currently there is only one item for the tuple. */ t = PyTuple_New(MAX_FIELDS); if (!t) @@ -365,10 +365,8 @@ static void python_process_general_event(union perf_event *perf_event __unused, snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); handler = PyDict_GetItemString(main_dict, handler_name); - if (handler && !PyCallable_Check(handler)) { - handler = NULL; + if (!handler || !PyCallable_Check(handler)) goto exit; - } PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize( -- cgit v1.2.3-18-g5258 From 1d037ca1648b775277fc96401ec2aa233724906c Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 11 Sep 2012 01:15:03 +0300 Subject: perf tools: Use __maybe_used for unused variables perf defines both __used and __unused variables to use for marking unused variables. The variable __used is defined to __attribute__((__unused__)), which contradicts the kernel definition to __attribute__((__used__)) for new gcc versions. On Android, __used is also defined in system headers and this leads to warnings like: warning: '__used__' attribute ignored __unused is not defined in the kernel and is not a standard definition. If __unused is included everywhere instead of __used, this leads to conflicts with glibc headers, since glibc has a variables with this name in its headers. The best approach is to use __maybe_unused, the definition used in the kernel for __attribute__((unused)). In this way there is only one definition in perf sources (instead of 2 definitions that point to the same thing: __used and __unused) and it works on both Linux and Android. This patch simply replaces all instances of __used and __unused with __maybe_unused. Signed-off-by: Irina Tirdea Acked-by: Pekka Enberg Cc: David Ahern Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1347315303-29906-7-git-send-email-irina.tirdea@intel.com [ committer note: fixed up conflict with a116e05 in builtin-sched.c ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/scripting-engines/trace-event-python.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools/perf/util/scripting-engines/trace-event-python.c') diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index afba0972918..730c6630cba 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -221,10 +221,11 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) return event; } -static void python_process_tracepoint(union perf_event *perf_event __unused, +static void python_process_tracepoint(union perf_event *perf_event + __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __unused, + struct machine *machine __maybe_unused, struct addr_location *al) { PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; @@ -339,10 +340,11 @@ static void python_process_tracepoint(union perf_event *perf_event __unused, Py_DECREF(t); } -static void python_process_general_event(union perf_event *perf_event __unused, +static void python_process_general_event(union perf_event *perf_event + __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, - struct machine *machine __unused, + struct machine *machine __maybe_unused, struct addr_location *al) { PyObject *handler, *retval, *t, *dict; -- cgit v1.2.3-18-g5258