#include <dlfcn.h>
#include <linux/bitmap.h>
+#include <linux/stringify.h>
struct report {
struct perf_tool tool;
struct perf_session *session;
bool use_tui, use_gtk, use_stdio;
- bool dont_use_callchains;
bool show_full_info;
bool show_threads;
bool inverted_callchain;
return 0;
}
if (!strcmp(var, "report.percent-limit")) {
- rep->min_percent = strtof(value, NULL);
+ double pcnt = strtof(value, NULL);
+
+ rep->min_percent = pcnt;
+ callchain_param.min_percent = pcnt;
return 0;
}
if (!strcmp(var, "report.children")) {
return 0;
}
- return perf_default_config(var, value, cb);
+ return 0;
}
static int hist_iter__report_callback(struct hist_entry_iter *iter,
};
int ret = 0;
- if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
+ if (machine__resolve(machine, &al, sample) < 0) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
return -1;
sample_type |= PERF_SAMPLE_BRANCH_STACK;
if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
- if (sort__has_parent) {
+ if (perf_hpp_list.parent) {
ui__error("Selected --sort parent, but no "
"callchain data. Did you call "
"'perf record' without -g?\n");
"you call 'perf record' without -g?\n");
return -1;
}
- } else if (!rep->dont_use_callchains &&
+ } else if (!callchain_param.enabled &&
callchain_param.mode != CHAIN_NONE &&
!symbol_conf.use_callchain) {
symbol_conf.use_callchain = true;
return ret;
}
-static void report__collapse_hists(struct report *rep)
+static int report__collapse_hists(struct report *rep)
{
struct ui_progress prog;
struct perf_evsel *pos;
+ int ret = 0;
ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
hists->socket_filter = rep->socket_filter;
- hists__collapse_resort(hists, &prog);
+ ret = hists__collapse_resort(hists, &prog);
+ if (ret < 0)
+ break;
/* Non-group events are considered as leader */
if (symbol_conf.event_group &&
}
ui_progress__finish();
+ return ret;
}
static void report__output_resort(struct report *rep)
ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
evlist__for_each(rep->session->evlist, pos)
- hists__output_resort(evsel__hists(pos), &prog);
+ perf_evsel__output_resort(pos, &prog);
ui_progress__finish();
}
}
}
- report__collapse_hists(rep);
+ ret = report__collapse_hists(rep);
+ if (ret) {
+ ui__error("failed to process hist entry\n");
+ return ret;
+ }
if (session_done())
return 0;
static int
report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
{
- struct report *rep = (struct report *)opt->value;
+ struct callchain_param *callchain = opt->value;
+ callchain->enabled = !unset;
/*
* --no-call-graph
*/
if (unset) {
- rep->dont_use_callchains = true;
+ symbol_conf.use_callchain = false;
+ callchain->mode = CHAIN_NONE;
return 0;
}
int unset __maybe_unused)
{
struct report *rep = opt->value;
+ double pcnt = strtof(str, NULL);
- rep->min_percent = strtof(str, NULL);
+ rep->min_percent = pcnt;
+ callchain_param.min_percent = pcnt;
return 0;
}
.ordered_events = true,
.ordering_requires_timestamps = true,
},
- .max_stack = PERF_MAX_STACK_DEPTH,
+ .max_stack = sysctl_perf_event_max_stack,
.pretty_printing_style = "normal",
.socket_filter = -1,
};
"regex filter to identify parent, see: '--sort parent'"),
OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
"Only display entries with parent-match"),
- OPT_CALLBACK_DEFAULT('g', "call-graph", &report,
+ OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
"print_type,threshold[,print_limit],order,sort_key[,branch],value",
report_callchain_help, &report_parse_callchain_opt,
callchain_default_opt),
OPT_INTEGER(0, "max-stack", &report.max_stack,
"Set the maximum stack depth when parsing the callchain, "
"anything beyond the specified depth will be ignored. "
- "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
+ "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
"alias for inverted call graph"),
OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
"only show processor socket that match with this filter"),
OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
"Show raw trace event output (do not use print fmt or plugins)"),
+ OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
+ "Show entries in a hierarchy"),
OPT_END()
};
struct perf_data_file file = {
symbol_conf.cumulate_callchain = false;
}
- if (setup_sorting(session->evlist) < 0) {
- if (sort_order)
- parse_options_usage(report_usage, options, "s", 1);
- if (field_order)
- parse_options_usage(sort_order ? NULL : report_usage,
- options, "F", 1);
- goto error;
+ if (symbol_conf.report_hierarchy) {
+ /* disable incompatible options */
+ symbol_conf.event_group = false;
+ symbol_conf.cumulate_callchain = false;
+
+ if (field_order) {
+ pr_err("Error: --hierarchy and --fields options cannot be used together\n");
+ parse_options_usage(report_usage, options, "F", 1);
+ parse_options_usage(NULL, options, "hierarchy", 0);
+ goto error;
+ }
+
+ perf_hpp_list.need_collapse = true;
}
/* Force tty output for header output and per-thread stat. */
else
use_browser = 0;
+ if (setup_sorting(session->evlist) < 0) {
+ if (sort_order)
+ parse_options_usage(report_usage, options, "s", 1);
+ if (field_order)
+ parse_options_usage(sort_order ? NULL : report_usage,
+ options, "F", 1);
+ goto error;
+ }
+
if (report.header || report.header_only) {
perf_session__fprintf_info(session, stdout,
report.show_full_info);