aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/scripting-engines/trace-event-python.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-08-21 05:27:00 -0400
committerIngo Molnar <mingo@kernel.org>2012-08-21 05:27:00 -0400
commitbcada3d4b8c96b8792c2306f363992ca5ab9da42 (patch)
treee420679a5db6ea4e1694eef57f9abb6acac8d4d3 /tools/perf/util/scripting-engines/trace-event-python.c
parent26198c21d1b286a084fe5d514a30bc7e6c712a34 (diff)
parent000078bc3ee69efb1124b8478c7527389a826074 (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: * Fix include order for bison/flex-generated C files, from Ben Hutchings * Build fixes and documentation corrections from David Ahern * Group parsing support, from Jiri Olsa * UI/gtk refactorings and improvements from Namhyung Kim * NULL deref fix for perf script, from Namhyung Kim * Assorted cleanups from Robert Richter * Let O= makes handle relative paths, from Steven Rostedt * perf script python fixes, from Feng Tang. * Improve 'perf lock' error message when the needed tracepoints are not present, from David Ahern. * Initial bash completion support, from Frederic Weisbecker * Allow building without libelf, from Namhyung Kim. * Support DWARF CFI based unwind to have callchains when %bp based unwinding is not possible, from Jiri Olsa. * Symbol resolution fixes, while fixing support PPC64 files with an .opt ELF section was the end goal, several fixes for code that handles all architectures and cleanups are included, from Cody Schafer. * Add a description for the JIT interface, from Andi Kleen. * Assorted fixes for Documentation and build in 32 bit, from Robert Richter * Add support for non-tracepoint events in perf script python, from Feng Tang * Cache the libtraceevent event_format associated to each evsel early, so that we avoid relookups, i.e. calling pevent_find_event repeatedly when processing tracepoint events. [ This is to reduce the surface contact with libtraceevents and make clear what is that the perf tools needs from that lib: so far parsing the common and per event fields. ] 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.c109
1 files changed, 95 insertions, 14 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ce4d1b0c3862..afba09729183 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,10 +27,12 @@
27#include <errno.h> 27#include <errno.h>
28 28
29#include "../../perf.h" 29#include "../../perf.h"
30#include "../evsel.h"
30#include "../util.h" 31#include "../util.h"
31#include "../event.h" 32#include "../event.h"
32#include "../thread.h" 33#include "../thread.h"
33#include "../trace-event.h" 34#include "../trace-event.h"
35#include "../evsel.h"
34 36
35PyMODINIT_FUNC initperf_trace_context(void); 37PyMODINIT_FUNC initperf_trace_context(void);
36 38
@@ -194,16 +196,21 @@ static void define_event_symbols(struct event_format *event,
194 define_event_symbols(event, ev_name, args->next); 196 define_event_symbols(event, ev_name, args->next);
195} 197}
196 198
197static inline 199static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
198struct event_format *find_cache_event(struct pevent *pevent, int type)
199{ 200{
200 static char ev_name[256]; 201 static char ev_name[256];
201 struct event_format *event; 202 struct event_format *event;
203 int type = evsel->attr.config;
202 204
205 /*
206 * XXX: Do we really need to cache this since now we have evsel->tp_format
207 * cached already? Need to re-read this "cache" routine that as well calls
208 * define_event_symbols() :-\
209 */
203 if (events[type]) 210 if (events[type])
204 return events[type]; 211 return events[type];
205 212
206 events[type] = event = pevent_find_event(pevent, type); 213 events[type] = event = evsel->tp_format;
207 if (!event) 214 if (!event)
208 return NULL; 215 return NULL;
209 216
@@ -214,12 +221,11 @@ struct event_format *find_cache_event(struct pevent *pevent, int type)
214 return event; 221 return event;
215} 222}
216 223
217static void python_process_event(union perf_event *perf_event __unused, 224static void python_process_tracepoint(union perf_event *perf_event __unused,
218 struct pevent *pevent,
219 struct perf_sample *sample, 225 struct perf_sample *sample,
220 struct perf_evsel *evsel __unused, 226 struct perf_evsel *evsel,
221 struct machine *machine __unused, 227 struct machine *machine __unused,
222 struct thread *thread) 228 struct addr_location *al)
223{ 229{
224 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 230 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
225 static char handler_name[256]; 231 static char handler_name[256];
@@ -228,24 +234,22 @@ static void python_process_event(union perf_event *perf_event __unused,
228 unsigned long s, ns; 234 unsigned long s, ns;
229 struct event_format *event; 235 struct event_format *event;
230 unsigned n = 0; 236 unsigned n = 0;
231 int type;
232 int pid; 237 int pid;
233 int cpu = sample->cpu; 238 int cpu = sample->cpu;
234 void *data = sample->raw_data; 239 void *data = sample->raw_data;
235 unsigned long long nsecs = sample->time; 240 unsigned long long nsecs = sample->time;
241 struct thread *thread = al->thread;
236 char *comm = thread->comm; 242 char *comm = thread->comm;
237 243
238 t = PyTuple_New(MAX_FIELDS); 244 t = PyTuple_New(MAX_FIELDS);
239 if (!t) 245 if (!t)
240 Py_FatalError("couldn't create Python tuple"); 246 Py_FatalError("couldn't create Python tuple");
241 247
242 type = trace_parse_common_type(pevent, data); 248 event = find_cache_event(evsel);
243
244 event = find_cache_event(pevent, type);
245 if (!event) 249 if (!event)
246 die("ug! no event found for type %d", type); 250 die("ug! no event found for type %d", (int)evsel->attr.config);
247 251
248 pid = trace_parse_common_pid(pevent, data); 252 pid = raw_field_value(event, "common_pid", data);
249 253
250 sprintf(handler_name, "%s__%s", event->system, event->name); 254 sprintf(handler_name, "%s__%s", event->system, event->name);
251 255
@@ -290,7 +294,7 @@ static void python_process_event(union perf_event *perf_event __unused,
290 offset = field->offset; 294 offset = field->offset;
291 obj = PyString_FromString((char *)data + offset); 295 obj = PyString_FromString((char *)data + offset);
292 } else { /* FIELD_IS_NUMERIC */ 296 } else { /* FIELD_IS_NUMERIC */
293 val = read_size(pevent, data + field->offset, 297 val = read_size(event, data + field->offset,
294 field->size); 298 field->size);
295 if (field->flags & FIELD_IS_SIGNED) { 299 if (field->flags & FIELD_IS_SIGNED) {
296 if ((long long)val >= LONG_MIN && 300 if ((long long)val >= LONG_MIN &&
@@ -335,6 +339,83 @@ static void python_process_event(union perf_event *perf_event __unused,
335 Py_DECREF(t); 339 Py_DECREF(t);
336} 340}
337 341
342static void python_process_general_event(union perf_event *perf_event __unused,
343 struct perf_sample *sample,
344 struct perf_evsel *evsel,
345 struct machine *machine __unused,
346 struct addr_location *al)
347{
348 PyObject *handler, *retval, *t, *dict;
349 static char handler_name[64];
350 unsigned n = 0;
351 struct thread *thread = al->thread;
352
353 /*
354 * Use the MAX_FIELDS to make the function expandable, though
355 * currently there is only one item for the tuple.
356 */
357 t = PyTuple_New(MAX_FIELDS);
358 if (!t)
359 Py_FatalError("couldn't create Python tuple");
360
361 dict = PyDict_New();
362 if (!dict)
363 Py_FatalError("couldn't create Python dictionary");
364
365 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
366
367 handler = PyDict_GetItemString(main_dict, handler_name);
368 if (!handler || !PyCallable_Check(handler))
369 goto exit;
370
371 PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
372 PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize(
373 (const char *)&evsel->attr, sizeof(evsel->attr)));
374 PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize(
375 (const char *)sample, sizeof(*sample)));
376 PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize(
377 (const char *)sample->raw_data, sample->raw_size));
378 PyDict_SetItemString(dict, "comm",
379 PyString_FromString(thread->comm));
380 if (al->map) {
381 PyDict_SetItemString(dict, "dso",
382 PyString_FromString(al->map->dso->name));
383 }
384 if (al->sym) {
385 PyDict_SetItemString(dict, "symbol",
386 PyString_FromString(al->sym->name));
387 }
388
389 PyTuple_SetItem(t, n++, dict);
390 if (_PyTuple_Resize(&t, n) == -1)
391 Py_FatalError("error resizing Python tuple");
392
393 retval = PyObject_CallObject(handler, t);
394 if (retval == NULL)
395 handler_call_die(handler_name);
396exit:
397 Py_DECREF(dict);
398 Py_DECREF(t);
399}
400
401static void python_process_event(union perf_event *perf_event,
402 struct perf_sample *sample,
403 struct perf_evsel *evsel,
404 struct machine *machine,
405 struct addr_location *al)
406{
407 switch (evsel->attr.type) {
408 case PERF_TYPE_TRACEPOINT:
409 python_process_tracepoint(perf_event, sample, evsel,
410 machine, al);
411 break;
412 /* Reserve for future process_hw/sw/raw APIs */
413 default:
414 python_process_general_event(perf_event, sample, evsel,
415 machine, al);
416 }
417}
418
338static int run_start_sub(void) 419static int run_start_sub(void)
339{ 420{
340 PyObject *handler, *retval; 421 PyObject *handler, *retval;