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 | 113 |
1 files changed, 98 insertions, 15 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..730c6630cba5 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 | ||
| 35 | PyMODINIT_FUNC initperf_trace_context(void); | 37 | PyMODINIT_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 | ||
| 197 | static inline | 199 | static inline struct event_format *find_cache_event(struct perf_evsel *evsel) |
| 198 | struct 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,12 @@ struct event_format *find_cache_event(struct pevent *pevent, int type) | |||
| 214 | return event; | 221 | return event; |
| 215 | } | 222 | } |
| 216 | 223 | ||
| 217 | static void python_process_event(union perf_event *perf_event __unused, | 224 | static void python_process_tracepoint(union perf_event *perf_event |
| 218 | struct pevent *pevent, | 225 | __maybe_unused, |
| 219 | struct perf_sample *sample, | 226 | struct perf_sample *sample, |
| 220 | struct perf_evsel *evsel __unused, | 227 | struct perf_evsel *evsel, |
| 221 | struct machine *machine __unused, | 228 | struct machine *machine __maybe_unused, |
| 222 | struct thread *thread) | 229 | struct addr_location *al) |
| 223 | { | 230 | { |
| 224 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 231 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; |
| 225 | static char handler_name[256]; | 232 | static char handler_name[256]; |
| @@ -228,24 +235,22 @@ static void python_process_event(union perf_event *perf_event __unused, | |||
| 228 | unsigned long s, ns; | 235 | unsigned long s, ns; |
| 229 | struct event_format *event; | 236 | struct event_format *event; |
| 230 | unsigned n = 0; | 237 | unsigned n = 0; |
| 231 | int type; | ||
| 232 | int pid; | 238 | int pid; |
| 233 | int cpu = sample->cpu; | 239 | int cpu = sample->cpu; |
| 234 | void *data = sample->raw_data; | 240 | void *data = sample->raw_data; |
| 235 | unsigned long long nsecs = sample->time; | 241 | unsigned long long nsecs = sample->time; |
| 242 | struct thread *thread = al->thread; | ||
| 236 | char *comm = thread->comm; | 243 | char *comm = thread->comm; |
| 237 | 244 | ||
| 238 | t = PyTuple_New(MAX_FIELDS); | 245 | t = PyTuple_New(MAX_FIELDS); |
| 239 | if (!t) | 246 | if (!t) |
| 240 | Py_FatalError("couldn't create Python tuple"); | 247 | Py_FatalError("couldn't create Python tuple"); |
| 241 | 248 | ||
| 242 | type = trace_parse_common_type(pevent, data); | 249 | event = find_cache_event(evsel); |
| 243 | |||
| 244 | event = find_cache_event(pevent, type); | ||
| 245 | if (!event) | 250 | if (!event) |
| 246 | die("ug! no event found for type %d", type); | 251 | die("ug! no event found for type %d", (int)evsel->attr.config); |
| 247 | 252 | ||
| 248 | pid = trace_parse_common_pid(pevent, data); | 253 | pid = raw_field_value(event, "common_pid", data); |
| 249 | 254 | ||
| 250 | sprintf(handler_name, "%s__%s", event->system, event->name); | 255 | sprintf(handler_name, "%s__%s", event->system, event->name); |
| 251 | 256 | ||
| @@ -290,7 +295,7 @@ static void python_process_event(union perf_event *perf_event __unused, | |||
| 290 | offset = field->offset; | 295 | offset = field->offset; |
| 291 | obj = PyString_FromString((char *)data + offset); | 296 | obj = PyString_FromString((char *)data + offset); |
| 292 | } else { /* FIELD_IS_NUMERIC */ | 297 | } else { /* FIELD_IS_NUMERIC */ |
| 293 | val = read_size(pevent, data + field->offset, | 298 | val = read_size(event, data + field->offset, |
| 294 | field->size); | 299 | field->size); |
| 295 | if (field->flags & FIELD_IS_SIGNED) { | 300 | if (field->flags & FIELD_IS_SIGNED) { |
| 296 | if ((long long)val >= LONG_MIN && | 301 | if ((long long)val >= LONG_MIN && |
| @@ -335,6 +340,84 @@ static void python_process_event(union perf_event *perf_event __unused, | |||
| 335 | Py_DECREF(t); | 340 | Py_DECREF(t); |
| 336 | } | 341 | } |
| 337 | 342 | ||
| 343 | static void python_process_general_event(union perf_event *perf_event | ||
| 344 | __maybe_unused, | ||
| 345 | struct perf_sample *sample, | ||
| 346 | struct perf_evsel *evsel, | ||
| 347 | struct machine *machine __maybe_unused, | ||
| 348 | struct addr_location *al) | ||
| 349 | { | ||
| 350 | PyObject *handler, *retval, *t, *dict; | ||
| 351 | static char handler_name[64]; | ||
| 352 | unsigned n = 0; | ||
| 353 | struct thread *thread = al->thread; | ||
| 354 | |||
| 355 | /* | ||
| 356 | * Use the MAX_FIELDS to make the function expandable, though | ||
| 357 | * currently there is only one item for the tuple. | ||
| 358 | */ | ||
| 359 | t = PyTuple_New(MAX_FIELDS); | ||
| 360 | if (!t) | ||
| 361 | Py_FatalError("couldn't create Python tuple"); | ||
| 362 | |||
| 363 | dict = PyDict_New(); | ||
| 364 | if (!dict) | ||
| 365 | Py_FatalError("couldn't create Python dictionary"); | ||
| 366 | |||
| 367 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); | ||
| 368 | |||
| 369 | handler = PyDict_GetItemString(main_dict, handler_name); | ||
| 370 | if (!handler || !PyCallable_Check(handler)) | ||
| 371 | goto exit; | ||
| 372 | |||
| 373 | PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); | ||
| 374 | PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize( | ||
| 375 | (const char *)&evsel->attr, sizeof(evsel->attr))); | ||
| 376 | PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize( | ||
| 377 | (const char *)sample, sizeof(*sample))); | ||
| 378 | PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize( | ||
| 379 | (const char *)sample->raw_data, sample->raw_size)); | ||
| 380 | PyDict_SetItemString(dict, "comm", | ||
| 381 | PyString_FromString(thread->comm)); | ||
| 382 | if (al->map) { | ||
| 383 | PyDict_SetItemString(dict, "dso", | ||
| 384 | PyString_FromString(al->map->dso->name)); | ||
| 385 | } | ||
| 386 | if (al->sym) { | ||
| 387 | PyDict_SetItemString(dict, "symbol", | ||
| 388 | PyString_FromString(al->sym->name)); | ||
| 389 | } | ||
| 390 | |||
| 391 | PyTuple_SetItem(t, n++, dict); | ||
| 392 | if (_PyTuple_Resize(&t, n) == -1) | ||
| 393 | Py_FatalError("error resizing Python tuple"); | ||
| 394 | |||
| 395 | retval = PyObject_CallObject(handler, t); | ||
| 396 | if (retval == NULL) | ||
| 397 | handler_call_die(handler_name); | ||
| 398 | exit: | ||
| 399 | Py_DECREF(dict); | ||
| 400 | Py_DECREF(t); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void python_process_event(union perf_event *perf_event, | ||
| 404 | struct perf_sample *sample, | ||
| 405 | struct perf_evsel *evsel, | ||
| 406 | struct machine *machine, | ||
| 407 | struct addr_location *al) | ||
| 408 | { | ||
| 409 | switch (evsel->attr.type) { | ||
| 410 | case PERF_TYPE_TRACEPOINT: | ||
| 411 | python_process_tracepoint(perf_event, sample, evsel, | ||
| 412 | machine, al); | ||
| 413 | break; | ||
| 414 | /* Reserve for future process_hw/sw/raw APIs */ | ||
| 415 | default: | ||
| 416 | python_process_general_event(perf_event, sample, evsel, | ||
| 417 | machine, al); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 338 | static int run_start_sub(void) | 421 | static int run_start_sub(void) |
| 339 | { | 422 | { |
| 340 | PyObject *handler, *retval; | 423 | PyObject *handler, *retval; |
