linux/tools/perf/builtin-c2c.c
Jiri Olsa 903a6f15b9 perf c2c: Add report subcommand
Adding c2c report subcommand. It reads the perf.data and displays shared
data analysis.

This patch adds report basic wirings. It gets fully implemented in
following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Joe Mario <jmario@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1474558645-19956-13-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2016-10-19 13:18:31 -03:00

202 lines
4.6 KiB
C

#include <linux/compiler.h>
#include <linux/kernel.h>
#include "util.h"
#include "debug.h"
#include "builtin.h"
#include <subcmd/parse-options.h>
#include "mem-events.h"
#include "session.h"
#include "hist.h"
#include "tool.h"
#include "data.h"
struct perf_c2c {
struct perf_tool tool;
};
static struct perf_c2c c2c;
static const char * const c2c_usage[] = {
"perf c2c {record|report}",
NULL
};
static const char * const __usage_report[] = {
"perf c2c report",
NULL
};
static const char * const *report_c2c_usage = __usage_report;
static int perf_c2c__report(int argc, const char **argv)
{
struct perf_session *session;
struct perf_data_file file = {
.mode = PERF_DATA_MODE_READ,
};
const struct option c2c_options[] = {
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_STRING('i', "input", &input_name, "file",
"the input file to process"),
OPT_END()
};
int err = 0;
argc = parse_options(argc, argv, c2c_options, report_c2c_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc)
usage_with_options(report_c2c_usage, c2c_options);
file.path = input_name;
session = perf_session__new(&file, 0, &c2c.tool);
if (session == NULL) {
pr_debug("No memory for session\n");
goto out;
}
if (symbol__init(&session->header.env) < 0)
goto out_session;
/* No pipe support at the moment. */
if (perf_data_file__is_pipe(session->file)) {
pr_debug("No pipe support at the moment.\n");
goto out_session;
}
out_session:
perf_session__delete(session);
out:
return err;
}
static int parse_record_events(const struct option *opt __maybe_unused,
const char *str, int unset __maybe_unused)
{
bool *event_set = (bool *) opt->value;
*event_set = true;
return perf_mem_events__parse(str);
}
static const char * const __usage_record[] = {
"perf c2c record [<options>] [<command>]",
"perf c2c record [<options>] -- <command> [<options>]",
NULL
};
static const char * const *record_mem_usage = __usage_record;
static int perf_c2c__record(int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
int ret;
bool all_user = false, all_kernel = false;
bool event_set = false;
struct option options[] = {
OPT_CALLBACK('e', "event", &event_set, "event",
"event selector. Use 'perf mem record -e list' to list available events",
parse_record_events),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"),
OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"),
OPT_END()
};
if (perf_mem_events__init()) {
pr_err("failed: memory events not supported\n");
return -1;
}
argc = parse_options(argc, argv, options, record_mem_usage,
PARSE_OPT_KEEP_UNKNOWN);
rec_argc = argc + 10; /* max number of arguments */
rec_argv = calloc(rec_argc + 1, sizeof(char *));
if (!rec_argv)
return -1;
rec_argv[i++] = "record";
if (!event_set) {
perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
}
if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
rec_argv[i++] = "-W";
rec_argv[i++] = "-d";
rec_argv[i++] = "--sample-cpu";
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
if (!perf_mem_events[j].record)
continue;
if (!perf_mem_events[j].supported) {
pr_err("failed: event '%s' not supported\n",
perf_mem_events[j].name);
return -1;
}
rec_argv[i++] = "-e";
rec_argv[i++] = perf_mem_events__name(j);
};
if (all_user)
rec_argv[i++] = "--all-user";
if (all_kernel)
rec_argv[i++] = "--all-kernel";
for (j = 0; j < argc; j++, i++)
rec_argv[i] = argv[j];
if (verbose > 0) {
pr_debug("calling: ");
j = 0;
while (rec_argv[j]) {
pr_debug("%s ", rec_argv[j]);
j++;
}
pr_debug("\n");
}
ret = cmd_record(i, rec_argv, NULL);
free(rec_argv);
return ret;
}
int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused)
{
const struct option c2c_options[] = {
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_END()
};
argc = parse_options(argc, argv, c2c_options, c2c_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc)
usage_with_options(c2c_usage, c2c_options);
if (!strncmp(argv[0], "rec", 3)) {
return perf_c2c__record(argc, argv);
} else if (!strncmp(argv[0], "rep", 3)) {
return perf_c2c__report(argc, argv);
} else {
usage_with_options(c2c_usage, c2c_options);
}
return 0;
}