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 | 440 |
1 files changed, 406 insertions, 34 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 496f21cadd97..d808a328f4dc 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
| @@ -24,7 +24,9 @@ | |||
| 24 | #include <stdio.h> | 24 | #include <stdio.h> |
| 25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
| 26 | #include <string.h> | 26 | #include <string.h> |
| 27 | #include <stdbool.h> | ||
| 27 | #include <errno.h> | 28 | #include <errno.h> |
| 29 | #include <linux/bitmap.h> | ||
| 28 | 30 | ||
| 29 | #include "../../perf.h" | 31 | #include "../../perf.h" |
| 30 | #include "../debug.h" | 32 | #include "../debug.h" |
| @@ -33,6 +35,10 @@ | |||
| 33 | #include "../util.h" | 35 | #include "../util.h" |
| 34 | #include "../event.h" | 36 | #include "../event.h" |
| 35 | #include "../thread.h" | 37 | #include "../thread.h" |
| 38 | #include "../comm.h" | ||
| 39 | #include "../machine.h" | ||
| 40 | #include "../db-export.h" | ||
| 41 | #include "../thread-stack.h" | ||
| 36 | #include "../trace-event.h" | 42 | #include "../trace-event.h" |
| 37 | #include "../machine.h" | 43 | #include "../machine.h" |
| 38 | 44 | ||
| @@ -41,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void); | |||
| 41 | #define FTRACE_MAX_EVENT \ | 47 | #define FTRACE_MAX_EVENT \ |
| 42 | ((1 << (sizeof(unsigned short) * 8)) - 1) | 48 | ((1 << (sizeof(unsigned short) * 8)) - 1) |
| 43 | 49 | ||
| 44 | struct event_format *events[FTRACE_MAX_EVENT]; | 50 | static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT); |
| 45 | 51 | ||
| 46 | #define MAX_FIELDS 64 | 52 | #define MAX_FIELDS 64 |
| 47 | #define N_COMMON_FIELDS 7 | 53 | #define N_COMMON_FIELDS 7 |
| @@ -53,6 +59,24 @@ static int zero_flag_atom; | |||
| 53 | 59 | ||
| 54 | static PyObject *main_module, *main_dict; | 60 | static PyObject *main_module, *main_dict; |
| 55 | 61 | ||
| 62 | struct tables { | ||
| 63 | struct db_export dbe; | ||
| 64 | PyObject *evsel_handler; | ||
| 65 | PyObject *machine_handler; | ||
| 66 | PyObject *thread_handler; | ||
| 67 | PyObject *comm_handler; | ||
| 68 | PyObject *comm_thread_handler; | ||
| 69 | PyObject *dso_handler; | ||
| 70 | PyObject *symbol_handler; | ||
| 71 | PyObject *branch_type_handler; | ||
| 72 | PyObject *sample_handler; | ||
| 73 | PyObject *call_path_handler; | ||
| 74 | PyObject *call_return_handler; | ||
| 75 | bool db_export_mode; | ||
| 76 | }; | ||
| 77 | |||
| 78 | static struct tables tables_global; | ||
| 79 | |||
| 56 | static void handler_call_die(const char *handler_name) NORETURN; | 80 | static void handler_call_die(const char *handler_name) NORETURN; |
| 57 | static void handler_call_die(const char *handler_name) | 81 | static void handler_call_die(const char *handler_name) |
| 58 | { | 82 | { |
| @@ -232,31 +256,6 @@ static void define_event_symbols(struct event_format *event, | |||
| 232 | define_event_symbols(event, ev_name, args->next); | 256 | define_event_symbols(event, ev_name, args->next); |
| 233 | } | 257 | } |
| 234 | 258 | ||
| 235 | static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | ||
| 236 | { | ||
| 237 | static char ev_name[256]; | ||
| 238 | struct event_format *event; | ||
| 239 | int type = evsel->attr.config; | ||
| 240 | |||
| 241 | /* | ||
| 242 | * XXX: Do we really need to cache this since now we have evsel->tp_format | ||
| 243 | * cached already? Need to re-read this "cache" routine that as well calls | ||
| 244 | * define_event_symbols() :-\ | ||
| 245 | */ | ||
| 246 | if (events[type]) | ||
| 247 | return events[type]; | ||
| 248 | |||
| 249 | events[type] = event = evsel->tp_format; | ||
| 250 | if (!event) | ||
| 251 | return NULL; | ||
| 252 | |||
| 253 | sprintf(ev_name, "%s__%s", event->system, event->name); | ||
| 254 | |||
| 255 | define_event_symbols(event, ev_name, event->print_fmt.args); | ||
| 256 | |||
| 257 | return event; | ||
| 258 | } | ||
| 259 | |||
| 260 | static PyObject *get_field_numeric_entry(struct event_format *event, | 259 | static PyObject *get_field_numeric_entry(struct event_format *event, |
| 261 | struct format_field *field, void *data) | 260 | struct format_field *field, void *data) |
| 262 | { | 261 | { |
| @@ -312,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
| 312 | if (!symbol_conf.use_callchain || !sample->callchain) | 311 | if (!symbol_conf.use_callchain || !sample->callchain) |
| 313 | goto exit; | 312 | goto exit; |
| 314 | 313 | ||
| 315 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | 314 | if (thread__resolve_callchain(al->thread, evsel, |
| 316 | sample, NULL, NULL, | 315 | sample, NULL, NULL, |
| 317 | PERF_MAX_STACK_DEPTH) != 0) { | 316 | PERF_MAX_STACK_DEPTH) != 0) { |
| 318 | pr_err("Failed to resolve callchain. Skipping\n"); | 317 | pr_err("Failed to resolve callchain. Skipping\n"); |
| 319 | goto exit; | 318 | goto exit; |
| 320 | } | 319 | } |
| @@ -380,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 380 | struct thread *thread, | 379 | struct thread *thread, |
| 381 | struct addr_location *al) | 380 | struct addr_location *al) |
| 382 | { | 381 | { |
| 382 | struct event_format *event = evsel->tp_format; | ||
| 383 | PyObject *handler, *context, *t, *obj, *callchain; | 383 | PyObject *handler, *context, *t, *obj, *callchain; |
| 384 | PyObject *dict = NULL; | 384 | PyObject *dict = NULL; |
| 385 | static char handler_name[256]; | 385 | static char handler_name[256]; |
| 386 | struct format_field *field; | 386 | struct format_field *field; |
| 387 | unsigned long s, ns; | 387 | unsigned long s, ns; |
| 388 | struct event_format *event; | ||
| 389 | unsigned n = 0; | 388 | unsigned n = 0; |
| 390 | int pid; | 389 | int pid; |
| 391 | int cpu = sample->cpu; | 390 | int cpu = sample->cpu; |
| @@ -397,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 397 | if (!t) | 396 | if (!t) |
| 398 | Py_FatalError("couldn't create Python tuple"); | 397 | Py_FatalError("couldn't create Python tuple"); |
| 399 | 398 | ||
| 400 | event = find_cache_event(evsel); | ||
| 401 | if (!event) | 399 | if (!event) |
| 402 | 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); |
| 403 | 401 | ||
| @@ -405,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 405 | 403 | ||
| 406 | sprintf(handler_name, "%s__%s", event->system, event->name); | 404 | sprintf(handler_name, "%s__%s", event->system, event->name); |
| 407 | 405 | ||
| 406 | if (!test_and_set_bit(event->id, events_defined)) | ||
| 407 | define_event_symbols(event, handler_name, event->print_fmt.args); | ||
| 408 | |||
| 408 | handler = get_handler(handler_name); | 409 | handler = get_handler(handler_name); |
| 409 | if (!handler) { | 410 | if (!handler) { |
| 410 | dict = PyDict_New(); | 411 | dict = PyDict_New(); |
| @@ -475,6 +476,289 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
| 475 | Py_DECREF(t); | 476 | Py_DECREF(t); |
| 476 | } | 477 | } |
| 477 | 478 | ||
| 479 | static PyObject *tuple_new(unsigned int sz) | ||
| 480 | { | ||
| 481 | PyObject *t; | ||
| 482 | |||
| 483 | t = PyTuple_New(sz); | ||
| 484 | if (!t) | ||
| 485 | Py_FatalError("couldn't create Python tuple"); | ||
| 486 | return t; | ||
| 487 | } | ||
| 488 | |||
| 489 | static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) | ||
| 490 | { | ||
| 491 | #if BITS_PER_LONG == 64 | ||
| 492 | return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | ||
| 493 | #endif | ||
| 494 | #if BITS_PER_LONG == 32 | ||
| 495 | return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); | ||
| 496 | #endif | ||
| 497 | } | ||
| 498 | |||
| 499 | static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) | ||
| 500 | { | ||
| 501 | return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | ||
| 502 | } | ||
| 503 | |||
| 504 | static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) | ||
| 505 | { | ||
| 506 | return PyTuple_SetItem(t, pos, PyString_FromString(s)); | ||
| 507 | } | ||
| 508 | |||
| 509 | static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) | ||
| 510 | { | ||
| 511 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 512 | PyObject *t; | ||
| 513 | |||
| 514 | t = tuple_new(2); | ||
| 515 | |||
| 516 | tuple_set_u64(t, 0, evsel->db_id); | ||
| 517 | tuple_set_string(t, 1, perf_evsel__name(evsel)); | ||
| 518 | |||
| 519 | call_object(tables->evsel_handler, t, "evsel_table"); | ||
| 520 | |||
| 521 | Py_DECREF(t); | ||
| 522 | |||
| 523 | return 0; | ||
| 524 | } | ||
| 525 | |||
| 526 | static int python_export_machine(struct db_export *dbe, | ||
| 527 | struct machine *machine) | ||
| 528 | { | ||
| 529 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 530 | PyObject *t; | ||
| 531 | |||
| 532 | t = tuple_new(3); | ||
| 533 | |||
| 534 | tuple_set_u64(t, 0, machine->db_id); | ||
| 535 | tuple_set_s32(t, 1, machine->pid); | ||
| 536 | tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : ""); | ||
| 537 | |||
| 538 | call_object(tables->machine_handler, t, "machine_table"); | ||
| 539 | |||
| 540 | Py_DECREF(t); | ||
| 541 | |||
| 542 | return 0; | ||
| 543 | } | ||
| 544 | |||
| 545 | static int python_export_thread(struct db_export *dbe, struct thread *thread, | ||
| 546 | u64 main_thread_db_id, struct machine *machine) | ||
| 547 | { | ||
| 548 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 549 | PyObject *t; | ||
| 550 | |||
| 551 | t = tuple_new(5); | ||
| 552 | |||
| 553 | tuple_set_u64(t, 0, thread->db_id); | ||
| 554 | tuple_set_u64(t, 1, machine->db_id); | ||
| 555 | tuple_set_u64(t, 2, main_thread_db_id); | ||
| 556 | tuple_set_s32(t, 3, thread->pid_); | ||
| 557 | tuple_set_s32(t, 4, thread->tid); | ||
| 558 | |||
| 559 | call_object(tables->thread_handler, t, "thread_table"); | ||
| 560 | |||
| 561 | Py_DECREF(t); | ||
| 562 | |||
| 563 | return 0; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int python_export_comm(struct db_export *dbe, struct comm *comm) | ||
| 567 | { | ||
| 568 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 569 | PyObject *t; | ||
| 570 | |||
| 571 | t = tuple_new(2); | ||
| 572 | |||
| 573 | tuple_set_u64(t, 0, comm->db_id); | ||
| 574 | tuple_set_string(t, 1, comm__str(comm)); | ||
| 575 | |||
| 576 | call_object(tables->comm_handler, t, "comm_table"); | ||
| 577 | |||
| 578 | Py_DECREF(t); | ||
| 579 | |||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | static int python_export_comm_thread(struct db_export *dbe, u64 db_id, | ||
| 584 | struct comm *comm, struct thread *thread) | ||
| 585 | { | ||
| 586 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 587 | PyObject *t; | ||
| 588 | |||
| 589 | t = tuple_new(3); | ||
| 590 | |||
| 591 | tuple_set_u64(t, 0, db_id); | ||
| 592 | tuple_set_u64(t, 1, comm->db_id); | ||
| 593 | tuple_set_u64(t, 2, thread->db_id); | ||
| 594 | |||
| 595 | call_object(tables->comm_thread_handler, t, "comm_thread_table"); | ||
| 596 | |||
| 597 | Py_DECREF(t); | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int python_export_dso(struct db_export *dbe, struct dso *dso, | ||
| 603 | struct machine *machine) | ||
| 604 | { | ||
| 605 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 606 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
| 607 | PyObject *t; | ||
| 608 | |||
| 609 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | ||
| 610 | |||
| 611 | t = tuple_new(5); | ||
| 612 | |||
| 613 | tuple_set_u64(t, 0, dso->db_id); | ||
| 614 | tuple_set_u64(t, 1, machine->db_id); | ||
| 615 | tuple_set_string(t, 2, dso->short_name); | ||
| 616 | tuple_set_string(t, 3, dso->long_name); | ||
| 617 | tuple_set_string(t, 4, sbuild_id); | ||
| 618 | |||
| 619 | call_object(tables->dso_handler, t, "dso_table"); | ||
| 620 | |||
| 621 | Py_DECREF(t); | ||
| 622 | |||
| 623 | return 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | static int python_export_symbol(struct db_export *dbe, struct symbol *sym, | ||
| 627 | struct dso *dso) | ||
| 628 | { | ||
| 629 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 630 | u64 *sym_db_id = symbol__priv(sym); | ||
| 631 | PyObject *t; | ||
| 632 | |||
| 633 | t = tuple_new(6); | ||
| 634 | |||
| 635 | tuple_set_u64(t, 0, *sym_db_id); | ||
| 636 | tuple_set_u64(t, 1, dso->db_id); | ||
| 637 | tuple_set_u64(t, 2, sym->start); | ||
| 638 | tuple_set_u64(t, 3, sym->end); | ||
| 639 | tuple_set_s32(t, 4, sym->binding); | ||
| 640 | tuple_set_string(t, 5, sym->name); | ||
| 641 | |||
| 642 | call_object(tables->symbol_handler, t, "symbol_table"); | ||
| 643 | |||
| 644 | Py_DECREF(t); | ||
| 645 | |||
| 646 | return 0; | ||
| 647 | } | ||
| 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, | ||
| 668 | struct export_sample *es) | ||
| 669 | { | ||
| 670 | struct tables *tables = container_of(dbe, struct tables, dbe); | ||
| 671 | PyObject *t; | ||
| 672 | |||
| 673 | t = tuple_new(21); | ||
| 674 | |||
| 675 | tuple_set_u64(t, 0, es->db_id); | ||
| 676 | tuple_set_u64(t, 1, es->evsel->db_id); | ||
| 677 | tuple_set_u64(t, 2, es->al->machine->db_id); | ||
| 678 | tuple_set_u64(t, 3, es->thread->db_id); | ||
| 679 | tuple_set_u64(t, 4, es->comm_db_id); | ||
| 680 | tuple_set_u64(t, 5, es->dso_db_id); | ||
| 681 | tuple_set_u64(t, 6, es->sym_db_id); | ||
| 682 | tuple_set_u64(t, 7, es->offset); | ||
| 683 | tuple_set_u64(t, 8, es->sample->ip); | ||
| 684 | tuple_set_u64(t, 9, es->sample->time); | ||
| 685 | tuple_set_s32(t, 10, es->sample->cpu); | ||
| 686 | tuple_set_u64(t, 11, es->addr_dso_db_id); | ||
| 687 | tuple_set_u64(t, 12, es->addr_sym_db_id); | ||
| 688 | tuple_set_u64(t, 13, es->addr_offset); | ||
| 689 | tuple_set_u64(t, 14, es->sample->addr); | ||
| 690 | tuple_set_u64(t, 15, es->sample->period); | ||
| 691 | tuple_set_u64(t, 16, es->sample->weight); | ||
| 692 | tuple_set_u64(t, 17, es->sample->transaction); | ||
| 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)); | ||
| 696 | |||
| 697 | call_object(tables->sample_handler, t, "sample_table"); | ||
| 698 | |||
| 699 | Py_DECREF(t); | ||
| 700 | |||
| 701 | return 0; | ||
| 702 | } | ||
| 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 | |||
| 478 | static void python_process_general_event(struct perf_sample *sample, | 762 | static void python_process_general_event(struct perf_sample *sample, |
| 479 | struct perf_evsel *evsel, | 763 | struct perf_evsel *evsel, |
| 480 | struct thread *thread, | 764 | struct thread *thread, |
| @@ -551,19 +835,25 @@ exit: | |||
| 551 | Py_DECREF(t); | 835 | Py_DECREF(t); |
| 552 | } | 836 | } |
| 553 | 837 | ||
| 554 | static void python_process_event(union perf_event *event __maybe_unused, | 838 | static void python_process_event(union perf_event *event, |
| 555 | struct perf_sample *sample, | 839 | struct perf_sample *sample, |
| 556 | struct perf_evsel *evsel, | 840 | struct perf_evsel *evsel, |
| 557 | struct thread *thread, | 841 | struct thread *thread, |
| 558 | struct addr_location *al) | 842 | struct addr_location *al) |
| 559 | { | 843 | { |
| 844 | struct tables *tables = &tables_global; | ||
| 845 | |||
| 560 | switch (evsel->attr.type) { | 846 | switch (evsel->attr.type) { |
| 561 | case PERF_TYPE_TRACEPOINT: | 847 | case PERF_TYPE_TRACEPOINT: |
| 562 | python_process_tracepoint(sample, evsel, thread, al); | 848 | python_process_tracepoint(sample, evsel, thread, al); |
| 563 | break; | 849 | break; |
| 564 | /* Reserve for future process_hw/sw/raw APIs */ | 850 | /* Reserve for future process_hw/sw/raw APIs */ |
| 565 | default: | 851 | default: |
| 566 | python_process_general_event(sample, evsel, thread, al); | 852 | if (tables->db_export_mode) |
| 853 | db_export__sample(&tables->dbe, event, sample, evsel, | ||
| 854 | thread, al); | ||
| 855 | else | ||
| 856 | python_process_general_event(sample, evsel, thread, al); | ||
| 567 | } | 857 | } |
| 568 | } | 858 | } |
| 569 | 859 | ||
| @@ -589,11 +879,79 @@ error: | |||
| 589 | return -1; | 879 | return -1; |
| 590 | } | 880 | } |
| 591 | 881 | ||
| 882 | #define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \ | ||
| 883 | tables->handler_name = get_handler(#table_name); \ | ||
| 884 | if (tables->handler_name) \ | ||
| 885 | tables->dbe.export_ ## name = python_export_ ## name; \ | ||
| 886 | } while (0) | ||
| 887 | |||
| 888 | #define SET_TABLE_HANDLER(name) \ | ||
| 889 | SET_TABLE_HANDLER_(name, name ## _handler, name ## _table) | ||
| 890 | |||
| 891 | static void set_table_handlers(struct tables *tables) | ||
| 892 | { | ||
| 893 | const char *perf_db_export_mode = "perf_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; | ||
| 897 | int ret; | ||
| 898 | |||
| 899 | memset(tables, 0, sizeof(struct tables)); | ||
| 900 | if (db_export__init(&tables->dbe)) | ||
| 901 | Py_FatalError("failed to initialize export"); | ||
| 902 | |||
| 903 | db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode); | ||
| 904 | if (!db_export_mode) | ||
| 905 | return; | ||
| 906 | |||
| 907 | ret = PyObject_IsTrue(db_export_mode); | ||
| 908 | if (ret == -1) | ||
| 909 | handler_call_die(perf_db_export_mode); | ||
| 910 | if (!ret) | ||
| 911 | return; | ||
| 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 | |||
| 930 | tables->db_export_mode = true; | ||
| 931 | /* | ||
| 932 | * Reserve per symbol space for symbol->db_id via symbol__priv() | ||
| 933 | */ | ||
| 934 | symbol_conf.priv_size = sizeof(u64); | ||
| 935 | |||
| 936 | SET_TABLE_HANDLER(evsel); | ||
| 937 | SET_TABLE_HANDLER(machine); | ||
| 938 | SET_TABLE_HANDLER(thread); | ||
| 939 | SET_TABLE_HANDLER(comm); | ||
| 940 | SET_TABLE_HANDLER(comm_thread); | ||
| 941 | SET_TABLE_HANDLER(dso); | ||
| 942 | SET_TABLE_HANDLER(symbol); | ||
| 943 | SET_TABLE_HANDLER(branch_type); | ||
| 944 | SET_TABLE_HANDLER(sample); | ||
| 945 | SET_TABLE_HANDLER(call_path); | ||
| 946 | SET_TABLE_HANDLER(call_return); | ||
| 947 | } | ||
| 948 | |||
| 592 | /* | 949 | /* |
| 593 | * Start trace script | 950 | * Start trace script |
| 594 | */ | 951 | */ |
| 595 | static int python_start_script(const char *script, int argc, const char **argv) | 952 | static int python_start_script(const char *script, int argc, const char **argv) |
| 596 | { | 953 | { |
| 954 | struct tables *tables = &tables_global; | ||
| 597 | const char **command_line; | 955 | const char **command_line; |
| 598 | char buf[PATH_MAX]; | 956 | char buf[PATH_MAX]; |
| 599 | int i, err = 0; | 957 | int i, err = 0; |
| @@ -632,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv) | |||
| 632 | 990 | ||
| 633 | free(command_line); | 991 | free(command_line); |
| 634 | 992 | ||
| 993 | set_table_handlers(tables); | ||
| 994 | |||
| 995 | if (tables->db_export_mode) { | ||
| 996 | err = db_export__branch_types(&tables->dbe); | ||
| 997 | if (err) | ||
| 998 | goto error; | ||
| 999 | } | ||
| 1000 | |||
| 635 | return err; | 1001 | return err; |
| 636 | error: | 1002 | error: |
| 637 | Py_Finalize(); | 1003 | Py_Finalize(); |
| @@ -642,7 +1008,9 @@ error: | |||
| 642 | 1008 | ||
| 643 | static int python_flush_script(void) | 1009 | static int python_flush_script(void) |
| 644 | { | 1010 | { |
| 645 | return 0; | 1011 | struct tables *tables = &tables_global; |
| 1012 | |||
| 1013 | return db_export__flush(&tables->dbe); | ||
| 646 | } | 1014 | } |
| 647 | 1015 | ||
| 648 | /* | 1016 | /* |
| @@ -650,8 +1018,12 @@ static int python_flush_script(void) | |||
| 650 | */ | 1018 | */ |
| 651 | static int python_stop_script(void) | 1019 | static int python_stop_script(void) |
| 652 | { | 1020 | { |
| 1021 | struct tables *tables = &tables_global; | ||
| 1022 | |||
| 653 | try_call_object("trace_end", NULL); | 1023 | try_call_object("trace_end", NULL); |
| 654 | 1024 | ||
| 1025 | db_export__exit(&tables->dbe); | ||
| 1026 | |||
| 655 | Py_XDECREF(main_dict); | 1027 | Py_XDECREF(main_dict); |
| 656 | Py_XDECREF(main_module); | 1028 | Py_XDECREF(main_module); |
| 657 | Py_Finalize(); | 1029 | Py_Finalize(); |
