diff options
Diffstat (limited to 'tools/perf/builtin-trace.c')
| -rw-r--r-- | tools/perf/builtin-trace.c | 97 | 
1 files changed, 93 insertions, 4 deletions
| diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 407041d20de0..dddf3f01b5ab 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | static char const *script_name; | 12 | static char const *script_name; | 
| 13 | static char const *generate_script_lang; | 13 | static char const *generate_script_lang; | 
| 14 | static bool debug_ordering; | ||
| 15 | static u64 last_timestamp; | ||
| 14 | 16 | ||
| 15 | static int default_start_script(const char *script __unused, | 17 | static int default_start_script(const char *script __unused, | 
| 16 | int argc __unused, | 18 | int argc __unused, | 
| @@ -51,6 +53,8 @@ static void setup_scripting(void) | |||
| 51 | 53 | ||
| 52 | static int cleanup_scripting(void) | 54 | static int cleanup_scripting(void) | 
| 53 | { | 55 | { | 
| 56 | pr_debug("\nperf trace script stopped\n"); | ||
| 57 | |||
| 54 | return scripting_ops->stop_script(); | 58 | return scripting_ops->stop_script(); | 
| 55 | } | 59 | } | 
| 56 | 60 | ||
| @@ -87,6 +91,14 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
| 87 | } | 91 | } | 
| 88 | 92 | ||
| 89 | if (session->sample_type & PERF_SAMPLE_RAW) { | 93 | if (session->sample_type & PERF_SAMPLE_RAW) { | 
| 94 | if (debug_ordering) { | ||
| 95 | if (data.time < last_timestamp) { | ||
| 96 | pr_err("Samples misordered, previous: %llu " | ||
| 97 | "this: %llu\n", last_timestamp, | ||
| 98 | data.time); | ||
| 99 | } | ||
| 100 | last_timestamp = data.time; | ||
| 101 | } | ||
| 90 | /* | 102 | /* | 
| 91 | * FIXME: better resolve from pid from the struct trace_entry | 103 | * FIXME: better resolve from pid from the struct trace_entry | 
| 92 | * field, although it should be the same than this perf | 104 | * field, although it should be the same than this perf | 
| @@ -97,17 +109,31 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
| 97 | data.time, thread->comm); | 109 | data.time, thread->comm); | 
| 98 | } | 110 | } | 
| 99 | 111 | ||
| 100 | session->events_stats.total += data.period; | 112 | session->hists.stats.total_period += data.period; | 
| 101 | return 0; | 113 | return 0; | 
| 102 | } | 114 | } | 
| 103 | 115 | ||
| 104 | static struct perf_event_ops event_ops = { | 116 | static struct perf_event_ops event_ops = { | 
| 105 | .sample = process_sample_event, | 117 | .sample = process_sample_event, | 
| 106 | .comm = event__process_comm, | 118 | .comm = event__process_comm, | 
| 119 | .attr = event__process_attr, | ||
| 120 | .event_type = event__process_event_type, | ||
| 121 | .tracing_data = event__process_tracing_data, | ||
| 122 | .build_id = event__process_build_id, | ||
| 123 | .ordered_samples = true, | ||
| 107 | }; | 124 | }; | 
| 108 | 125 | ||
| 126 | extern volatile int session_done; | ||
| 127 | |||
| 128 | static void sig_handler(int sig __unused) | ||
| 129 | { | ||
| 130 | session_done = 1; | ||
| 131 | } | ||
| 132 | |||
| 109 | static int __cmd_trace(struct perf_session *session) | 133 | static int __cmd_trace(struct perf_session *session) | 
| 110 | { | 134 | { | 
| 135 | signal(SIGINT, sig_handler); | ||
| 136 | |||
| 111 | return perf_session__process_events(session, &event_ops); | 137 | return perf_session__process_events(session, &event_ops); | 
| 112 | } | 138 | } | 
| 113 | 139 | ||
| @@ -505,7 +531,7 @@ static const char * const trace_usage[] = { | |||
| 505 | static const struct option options[] = { | 531 | static const struct option options[] = { | 
| 506 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 532 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 
| 507 | "dump raw trace in ASCII"), | 533 | "dump raw trace in ASCII"), | 
| 508 | OPT_BOOLEAN('v', "verbose", &verbose, | 534 | OPT_INCR('v', "verbose", &verbose, | 
| 509 | "be more verbose (show symbol address, etc)"), | 535 | "be more verbose (show symbol address, etc)"), | 
| 510 | OPT_BOOLEAN('L', "Latency", &latency_format, | 536 | OPT_BOOLEAN('L', "Latency", &latency_format, | 
| 511 | "show latency attributes (irqs/preemption disabled, etc)"), | 537 | "show latency attributes (irqs/preemption disabled, etc)"), | 
| @@ -518,6 +544,8 @@ static const struct option options[] = { | |||
| 518 | "generate perf-trace.xx script in specified language"), | 544 | "generate perf-trace.xx script in specified language"), | 
| 519 | OPT_STRING('i', "input", &input_name, "file", | 545 | OPT_STRING('i', "input", &input_name, "file", | 
| 520 | "input file name"), | 546 | "input file name"), | 
| 547 | OPT_BOOLEAN('d', "debug-ordering", &debug_ordering, | ||
| 548 | "check that samples time ordering is monotonic"), | ||
| 521 | 549 | ||
| 522 | OPT_END() | 550 | OPT_END() | 
| 523 | }; | 551 | }; | 
| @@ -548,6 +576,65 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 548 | suffix = REPORT_SUFFIX; | 576 | suffix = REPORT_SUFFIX; | 
| 549 | } | 577 | } | 
| 550 | 578 | ||
| 579 | if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { | ||
| 580 | char *record_script_path, *report_script_path; | ||
| 581 | int live_pipe[2]; | ||
| 582 | pid_t pid; | ||
| 583 | |||
| 584 | record_script_path = get_script_path(argv[1], RECORD_SUFFIX); | ||
| 585 | if (!record_script_path) { | ||
| 586 | fprintf(stderr, "record script not found\n"); | ||
| 587 | return -1; | ||
| 588 | } | ||
| 589 | |||
| 590 | report_script_path = get_script_path(argv[1], REPORT_SUFFIX); | ||
| 591 | if (!report_script_path) { | ||
| 592 | fprintf(stderr, "report script not found\n"); | ||
| 593 | return -1; | ||
| 594 | } | ||
| 595 | |||
| 596 | if (pipe(live_pipe) < 0) { | ||
| 597 | perror("failed to create pipe"); | ||
| 598 | exit(-1); | ||
| 599 | } | ||
| 600 | |||
| 601 | pid = fork(); | ||
| 602 | if (pid < 0) { | ||
| 603 | perror("failed to fork"); | ||
| 604 | exit(-1); | ||
| 605 | } | ||
| 606 | |||
| 607 | if (!pid) { | ||
| 608 | dup2(live_pipe[1], 1); | ||
| 609 | close(live_pipe[0]); | ||
| 610 | |||
| 611 | __argv = malloc(5 * sizeof(const char *)); | ||
| 612 | __argv[0] = "/bin/sh"; | ||
| 613 | __argv[1] = record_script_path; | ||
| 614 | __argv[2] = "-o"; | ||
| 615 | __argv[3] = "-"; | ||
| 616 | __argv[4] = NULL; | ||
| 617 | |||
| 618 | execvp("/bin/sh", (char **)__argv); | ||
| 619 | exit(-1); | ||
| 620 | } | ||
| 621 | |||
| 622 | dup2(live_pipe[0], 0); | ||
| 623 | close(live_pipe[1]); | ||
| 624 | |||
| 625 | __argv = malloc((argc + 3) * sizeof(const char *)); | ||
| 626 | __argv[0] = "/bin/sh"; | ||
| 627 | __argv[1] = report_script_path; | ||
| 628 | for (i = 2; i < argc; i++) | ||
| 629 | __argv[i] = argv[i]; | ||
| 630 | __argv[i++] = "-i"; | ||
| 631 | __argv[i++] = "-"; | ||
| 632 | __argv[i++] = NULL; | ||
| 633 | |||
| 634 | execvp("/bin/sh", (char **)__argv); | ||
| 635 | exit(-1); | ||
| 636 | } | ||
| 637 | |||
| 551 | if (suffix) { | 638 | if (suffix) { | 
| 552 | script_path = get_script_path(argv[2], suffix); | 639 | script_path = get_script_path(argv[2], suffix); | 
| 553 | if (!script_path) { | 640 | if (!script_path) { | 
| @@ -576,11 +663,12 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 576 | if (!script_name) | 663 | if (!script_name) | 
| 577 | setup_pager(); | 664 | setup_pager(); | 
| 578 | 665 | ||
| 579 | session = perf_session__new(input_name, O_RDONLY, 0); | 666 | session = perf_session__new(input_name, O_RDONLY, 0, false); | 
| 580 | if (session == NULL) | 667 | if (session == NULL) | 
| 581 | return -ENOMEM; | 668 | return -ENOMEM; | 
| 582 | 669 | ||
| 583 | if (!perf_session__has_traces(session, "record -R")) | 670 | if (strcmp(input_name, "-") && | 
| 671 | !perf_session__has_traces(session, "record -R")) | ||
| 584 | return -EINVAL; | 672 | return -EINVAL; | 
| 585 | 673 | ||
| 586 | if (generate_script_lang) { | 674 | if (generate_script_lang) { | 
| @@ -617,6 +705,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 617 | err = scripting_ops->start_script(script_name, argc, argv); | 705 | err = scripting_ops->start_script(script_name, argc, argv); | 
| 618 | if (err) | 706 | if (err) | 
| 619 | goto out; | 707 | goto out; | 
| 708 | pr_debug("perf trace started with script %s\n\n", script_name); | ||
| 620 | } | 709 | } | 
| 621 | 710 | ||
| 622 | err = __cmd_trace(session); | 711 | err = __cmd_trace(session); | 
