diff options
Diffstat (limited to 'tools/perf/builtin-timechart.c')
| -rw-r--r-- | tools/perf/builtin-timechart.c | 102 |
1 files changed, 68 insertions, 34 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 6c629e7d370a..f8b49d69e9a5 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -24,7 +24,6 @@ #include "util/thread.h" #include "util/callchain.h" -#include "perf.h" #include "util/header.h" #include <subcmd/pager.h> #include <subcmd/parse-options.h> @@ -37,8 +36,9 @@ #include "util/debug.h" #include "util/string2.h" #include "util/tracepoint.h" +#include "util/util.h" #include <linux/err.h> -#include <traceevent/event-parse.h> +#include <event-parse.h> #ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE FILE *open_memstream(char **ptr, size_t *sizeloc); @@ -315,12 +315,12 @@ static void pid_put_sample(struct timechart *tchart, int pid, int type, #define MAX_CPUS 4096 -static u64 cpus_cstate_start_times[MAX_CPUS]; -static int cpus_cstate_state[MAX_CPUS]; -static u64 cpus_pstate_start_times[MAX_CPUS]; -static u64 cpus_pstate_state[MAX_CPUS]; +static u64 *cpus_cstate_start_times; +static int *cpus_cstate_state; +static u64 *cpus_pstate_start_times; +static u64 *cpus_pstate_state; -static int process_comm_event(struct perf_tool *tool, +static int process_comm_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) @@ -330,7 +330,7 @@ static int process_comm_event(struct perf_tool *tool, return 0; } -static int process_fork_event(struct perf_tool *tool, +static int process_fork_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) @@ -340,7 +340,7 @@ static int process_fork_event(struct perf_tool *tool, return 0; } -static int process_exit_event(struct perf_tool *tool, +static int process_exit_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) @@ -498,7 +498,6 @@ static const char *cat_backtrace(union perf_event *event, char *p = NULL; size_t p_len; u8 cpumode = PERF_RECORD_MISC_USER; - struct addr_location tal; struct ip_callchain *chain = sample->callchain; FILE *f = open_memstream(&p, &p_len); @@ -507,6 +506,7 @@ static const char *cat_backtrace(union perf_event *event, return NULL; } + addr_location__init(&al); if (!chain) goto exit; @@ -518,6 +518,7 @@ static const char *cat_backtrace(union perf_event *event, for (i = 0; i < chain->nr; i++) { u64 ip; + struct addr_location tal; if (callchain_param.order == ORDER_CALLEE) ip = chain->ips[i]; @@ -544,20 +545,22 @@ static const char *cat_backtrace(union perf_event *event, * Discard all. */ zfree(&p); - goto exit_put; + goto exit; } continue; } + addr_location__init(&tal); tal.filtered = 0; if (thread__find_symbol(al.thread, cpumode, ip, &tal)) fprintf(f, "..... %016" PRIx64 " %s\n", ip, tal.sym->name); else fprintf(f, "..... %016" PRIx64 "\n", ip); + + addr_location__exit(&tal); } -exit_put: - addr_location__put(&al); exit: + addr_location__exit(&al); fclose(f); return p; @@ -568,7 +571,7 @@ typedef int (*tracepoint_handler)(struct timechart *tchart, struct perf_sample *sample, const char *backtrace); -static int process_sample_event(struct perf_tool *tool, +static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct evsel *evsel, @@ -1155,7 +1158,6 @@ static void draw_io_bars(struct timechart *tchart) } svg_box(Y, c->start_time, c->end_time, "process3"); - sample = c->io_samples; for (sample = c->io_samples; sample; sample = sample->next) { double h = (double)sample->bytes / c->max_bytes; @@ -1603,14 +1605,20 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) .mode = PERF_DATA_MODE_READ, .force = tchart->force, }; - - struct perf_session *session = perf_session__new(&data, &tchart->tool); + struct perf_session *session; int ret = -EINVAL; + perf_tool__init(&tchart->tool, /*ordered_events=*/true); + tchart->tool.comm = process_comm_event; + tchart->tool.fork = process_fork_event; + tchart->tool.exit = process_exit_event; + tchart->tool.sample = process_sample_event; + + session = perf_session__new(&data, &tchart->tool); if (IS_ERR(session)) return PTR_ERR(session); - symbol__init(&session->header.env); + symbol__init(perf_session__env(session)); (void)perf_header__process_sections(&session->header, perf_data__fd(session->data), @@ -1643,7 +1651,7 @@ out_delete: return ret; } -static int timechart__io_record(int argc, const char **argv) +static int timechart__io_record(int argc, const char **argv, const char *output_data) { unsigned int rec_argc, i; const char **rec_argv; @@ -1651,7 +1659,7 @@ static int timechart__io_record(int argc, const char **argv) char *filter = NULL; const char * const common_args[] = { - "record", "-a", "-R", "-c", "1", + "record", "-a", "-R", "-c", "1", "-o", output_data, }; unsigned int common_args_nr = ARRAY_SIZE(common_args); @@ -1778,7 +1786,8 @@ static int timechart__io_record(int argc, const char **argv) } -static int timechart__record(struct timechart *tchart, int argc, const char **argv) +static int timechart__record(struct timechart *tchart, int argc, const char **argv, + const char *output_data) { unsigned int rec_argc, i, j; const char **rec_argv; @@ -1786,7 +1795,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar unsigned int record_elems; const char * const common_args[] = { - "record", "-a", "-R", "-c", "1", + "record", "-a", "-R", "-c", "1", "-o", output_data, }; unsigned int common_args_nr = ARRAY_SIZE(common_args); @@ -1921,18 +1930,12 @@ parse_time(const struct option *opt, const char *arg, int __maybe_unused unset) int cmd_timechart(int argc, const char **argv) { struct timechart tchart = { - .tool = { - .comm = process_comm_event, - .fork = process_fork_event, - .exit = process_exit_event, - .sample = process_sample_event, - .ordered_events = true, - }, .proc_num = 15, .min_time = NSEC_PER_MSEC, .merge_dist = 1000, }; const char *output_name = "output.svg"; + const char *output_record_data = "perf.data"; const struct option timechart_common_options[] = { OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, "output processes data only"), @@ -1975,18 +1978,41 @@ int cmd_timechart(int argc, const char **argv) OPT_BOOLEAN('I', "io-only", &tchart.io_only, "record only IO data"), OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), + OPT_STRING('o', "output", &output_record_data, "file", "output data file name"), OPT_PARENT(timechart_common_options), }; const char * const timechart_record_usage[] = { "perf timechart record [<options>]", NULL }; + int ret; + + cpus_cstate_start_times = calloc(MAX_CPUS, sizeof(*cpus_cstate_start_times)); + if (!cpus_cstate_start_times) + return -ENOMEM; + cpus_cstate_state = calloc(MAX_CPUS, sizeof(*cpus_cstate_state)); + if (!cpus_cstate_state) { + ret = -ENOMEM; + goto out; + } + cpus_pstate_start_times = calloc(MAX_CPUS, sizeof(*cpus_pstate_start_times)); + if (!cpus_pstate_start_times) { + ret = -ENOMEM; + goto out; + } + cpus_pstate_state = calloc(MAX_CPUS, sizeof(*cpus_pstate_state)); + if (!cpus_pstate_state) { + ret = -ENOMEM; + goto out; + } + argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands, timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (tchart.power_only && tchart.tasks_only) { pr_err("-P and -T options cannot be used at the same time.\n"); - return -1; + ret = -1; + goto out; } if (argc && strlen(argv[0]) > 2 && strstarts("record", argv[0])) { @@ -1996,17 +2022,25 @@ int cmd_timechart(int argc, const char **argv) if (tchart.power_only && tchart.tasks_only) { pr_err("-P and -T options cannot be used at the same time.\n"); - return -1; + ret = -1; + goto out; } if (tchart.io_only) - return timechart__io_record(argc, argv); + ret = timechart__io_record(argc, argv, output_record_data); else - return timechart__record(&tchart, argc, argv); + ret = timechart__record(&tchart, argc, argv, output_record_data); + goto out; } else if (argc) usage_with_options(timechart_usage, timechart_options); setup_pager(); - return __cmd_timechart(&tchart, output_name); + ret = __cmd_timechart(&tchart, output_name); +out: + zfree(&cpus_cstate_start_times); + zfree(&cpus_cstate_state); + zfree(&cpus_pstate_start_times); + zfree(&cpus_pstate_state); + return ret; } |
