summaryrefslogtreecommitdiff
path: root/tools/perf/builtin-stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r--tools/perf/builtin-stat.c124
1 files changed, 76 insertions, 48 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a04466ea3b0a..c50cf230f16e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -321,7 +321,7 @@ static int read_single_counter(struct evsel *counter, int cpu_map_idx, int threa
*/
static int read_counter_cpu(struct evsel *counter, int cpu_map_idx)
{
- int nthreads = perf_thread_map__nr(evsel_list->core.threads);
+ int nthreads = perf_thread_map__nr(evlist__core(evsel_list)->threads);
int thread;
if (!counter->supported)
@@ -628,11 +628,12 @@ static int dispatch_events(bool forks, int timeout, int interval, int *times)
time_to_sleep = sleep_time;
while (!done) {
- if (forks)
+ if (forks) {
child_exited = waitpid(child_pid, &status, WNOHANG);
- else
- child_exited = !is_target_alive(&target, evsel_list->core.threads) ? 1 : 0;
-
+ } else {
+ child_exited = !is_target_alive(&target,
+ evlist__core(evsel_list)->threads) ? 1 : 0;
+ }
if (child_exited)
break;
@@ -681,14 +682,15 @@ static enum counter_recovery stat_handle_error(struct evsel *counter, int err)
return COUNTER_RETRY;
}
if (target__has_per_thread(&target) && err != EOPNOTSUPP &&
- evsel_list->core.threads && evsel_list->core.threads->err_thread != -1) {
+ evlist__core(evsel_list)->threads &&
+ evlist__core(evsel_list)->threads->err_thread != -1) {
/*
* For global --per-thread case, skip current
* error thread.
*/
- if (!thread_map__remove(evsel_list->core.threads,
- evsel_list->core.threads->err_thread)) {
- evsel_list->core.threads->err_thread = -1;
+ if (!thread_map__remove(evlist__core(evsel_list)->threads,
+ evlist__core(evsel_list)->threads->err_thread)) {
+ evlist__core(evsel_list)->threads->err_thread = -1;
counter->supported = true;
return COUNTER_RETRY;
}
@@ -787,11 +789,12 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
bool second_pass = false, has_supported_counters;
if (forks) {
- if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {
+ if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
+ workload_exec_failed_signal) < 0) {
perror("failed to prepare workload");
return -1;
}
- child_pid = evsel_list->workload.pid;
+ child_pid = evlist__workload_pid(evsel_list);
}
evlist__for_each_entry(evsel_list, counter) {
@@ -1199,7 +1202,7 @@ static int parse_cputype(const struct option *opt,
const struct perf_pmu *pmu;
struct evlist *evlist = *(struct evlist **)opt->value;
- if (!list_empty(&evlist->core.entries)) {
+ if (!list_empty(&evlist__core(evlist)->entries)) {
fprintf(stderr, "Must define cputype before events/metrics\n");
return -1;
}
@@ -1210,6 +1213,7 @@ static int parse_cputype(const struct option *opt,
return -1;
}
parse_events_option_args.pmu_filter = pmu->name;
+ parse_events_option_args.cputype_filter = true;
return 0;
}
@@ -1220,12 +1224,13 @@ static int parse_pmu_filter(const struct option *opt,
{
struct evlist *evlist = *(struct evlist **)opt->value;
- if (!list_empty(&evlist->core.entries)) {
+ if (!list_empty(&evlist__core(evlist)->entries)) {
fprintf(stderr, "Must define pmu-filter before events/metrics\n");
return -1;
}
parse_events_option_args.pmu_filter = str;
+ parse_events_option_args.cputype_filter = false;
return 0;
}
@@ -1586,8 +1591,9 @@ static int perf_stat_init_aggr_mode(void)
if (get_id) {
bool needs_sort = stat_config.aggr_mode != AGGR_NONE;
- stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.user_requested_cpus,
- get_id, /*data=*/NULL, needs_sort);
+ stat_config.aggr_map = cpu_aggr_map__new(
+ evlist__core(evsel_list)->user_requested_cpus,
+ get_id, /*data=*/NULL, needs_sort);
if (!stat_config.aggr_map) {
pr_err("cannot build %s map\n", aggr_mode__string[stat_config.aggr_mode]);
return -1;
@@ -1596,7 +1602,7 @@ static int perf_stat_init_aggr_mode(void)
}
if (stat_config.aggr_mode == AGGR_THREAD) {
- nr = perf_thread_map__nr(evsel_list->core.threads);
+ nr = perf_thread_map__nr(evlist__core(evsel_list)->threads);
stat_config.aggr_map = cpu_aggr_map__empty_new(nr);
if (stat_config.aggr_map == NULL)
return -ENOMEM;
@@ -1615,7 +1621,7 @@ static int perf_stat_init_aggr_mode(void)
* taking the highest cpu number to be the size of
* the aggregation translate cpumap.
*/
- nr = perf_cpu_map__max(evsel_list->core.all_cpus).cpu + 1;
+ nr = perf_cpu_map__max(evlist__core(evsel_list)->all_cpus).cpu + 1;
stat_config.cpus_aggr_map = cpu_aggr_map__empty_new(nr);
return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
}
@@ -1902,7 +1908,7 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
bool needs_sort = stat_config.aggr_mode != AGGR_NONE;
if (stat_config.aggr_mode == AGGR_THREAD) {
- int nr = perf_thread_map__nr(evsel_list->core.threads);
+ int nr = perf_thread_map__nr(evlist__core(evsel_list)->threads);
stat_config.aggr_map = cpu_aggr_map__empty_new(nr);
if (stat_config.aggr_map == NULL)
@@ -1920,7 +1926,7 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
if (!get_id)
return 0;
- stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.user_requested_cpus,
+ stat_config.aggr_map = cpu_aggr_map__new(evlist__core(evsel_list)->user_requested_cpus,
get_id, env, needs_sort);
if (!stat_config.aggr_map) {
pr_err("cannot build %s map\n", aggr_mode__string[stat_config.aggr_mode]);
@@ -1999,7 +2005,9 @@ static int add_default_events(void)
ret = -1;
goto out;
}
- ret = metricgroup__parse_groups(evlist, pmu, "transaction",
+ ret = metricgroup__parse_groups(evlist, pmu,
+ parse_events_option_args.cputype_filter,
+ "transaction",
stat_config.metric_no_group,
stat_config.metric_no_merge,
stat_config.metric_no_threshold,
@@ -2036,7 +2044,9 @@ static int add_default_events(void)
if (!force_metric_only)
stat_config.metric_only = true;
- ret = metricgroup__parse_groups(evlist, pmu, "smi",
+ ret = metricgroup__parse_groups(evlist, pmu,
+ parse_events_option_args.cputype_filter,
+ "smi",
stat_config.metric_no_group,
stat_config.metric_no_merge,
stat_config.metric_no_threshold,
@@ -2073,7 +2083,7 @@ static int add_default_events(void)
}
str[8] = stat_config.topdown_level + '0';
if (metricgroup__parse_groups(evlist,
- pmu, str,
+ pmu, parse_events_option_args.cputype_filter, str,
/*metric_no_group=*/false,
/*metric_no_merge=*/false,
/*metric_no_threshold=*/true,
@@ -2088,7 +2098,7 @@ static int add_default_events(void)
if (!stat_config.topdown_level)
stat_config.topdown_level = 1;
- if (!evlist->core.nr_entries && !evsel_list->core.nr_entries) {
+ if (!evlist__nr_entries(evlist) && !evlist__nr_entries(evsel_list)) {
/*
* Add Default metrics. To minimize multiplexing, don't request
* threshold computation, but it will be computed if the events
@@ -2112,14 +2122,16 @@ static int add_default_events(void)
ret = -ENOMEM;
break;
}
- if (metricgroup__parse_groups(metric_evlist, pmu, default_metricgroup_names[i],
+ if (metricgroup__parse_groups(metric_evlist, pmu,
+ parse_events_option_args.cputype_filter,
+ default_metricgroup_names[i],
/*metric_no_group=*/false,
/*metric_no_merge=*/false,
/*metric_no_threshold=*/true,
stat_config.user_requested_cpu_list,
stat_config.system_wide,
stat_config.hardware_aware_grouping) < 0) {
- evlist__delete(metric_evlist);
+ evlist__put(metric_evlist);
ret = -1;
break;
}
@@ -2127,13 +2139,13 @@ static int add_default_events(void)
evlist__for_each_entry(metric_evlist, evsel)
evsel->default_metricgroup = true;
- evlist__splice_list_tail(evlist, &metric_evlist->core.entries);
+ evlist__splice_list_tail(evlist, &evlist__core(metric_evlist)->entries);
metricgroup__copy_metric_events(evlist, /*cgrp=*/NULL,
- &evlist->metric_events,
- &metric_evlist->metric_events);
- evlist__delete(metric_evlist);
+ evlist__metric_events(evlist),
+ evlist__metric_events(metric_evlist));
+ evlist__put(metric_evlist);
}
- list_sort(/*priv=*/NULL, &evlist->core.entries, default_evlist_evsel_cmp);
+ list_sort(/*priv=*/NULL, &evlist__core(evlist)->entries, default_evlist_evsel_cmp);
}
out:
@@ -2148,11 +2160,11 @@ out:
}
}
parse_events_error__exit(&err);
- evlist__splice_list_tail(evsel_list, &evlist->core.entries);
+ evlist__splice_list_tail(evsel_list, &evlist__core(evlist)->entries);
metricgroup__copy_metric_events(evsel_list, /*cgrp=*/NULL,
- &evsel_list->metric_events,
- &evlist->metric_events);
- evlist__delete(evlist);
+ evlist__metric_events(evsel_list),
+ evlist__metric_events(evlist));
+ evlist__put(evlist);
return ret;
}
@@ -2272,7 +2284,7 @@ static int set_maps(struct perf_stat *st)
if (WARN_ONCE(st->maps_allocated, "stats double allocation\n"))
return -EINVAL;
- perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);
+ perf_evlist__set_maps(evlist__core(evsel_list), st->cpus, st->threads);
if (evlist__alloc_stats(&stat_config, evsel_list, /*alloc_raw=*/true))
return -ENOMEM;
@@ -2387,7 +2399,7 @@ static int __cmd_report(int argc, const char **argv)
perf_stat.session = session;
stat_config.output = stderr;
- evlist__delete(evsel_list);
+ evlist__put(evsel_list);
evsel_list = session->evlist;
ret = perf_session__process_events(session);
@@ -2424,7 +2436,7 @@ static void setup_system_wide(int forks)
}
}
- if (evsel_list->core.nr_entries)
+ if (evlist__nr_entries(evsel_list))
target.system_wide = true;
}
}
@@ -2493,6 +2505,8 @@ int cmd_stat(int argc, const char **argv)
"display details about each run (only with -r option)"),
OPT_BOOLEAN('n', "null", &stat_config.null_run,
"null run - dont start any counters"),
+ OPT_BOOLEAN(0, "hide-zero-events", &stat_config.hide_zero,
+ "Do not show events with a zero count"),
OPT_INCR('d', "detailed", &detailed_run,
"detailed run - start a lot of events"),
OPT_BOOLEAN('S', "sync", &sync_run,
@@ -2643,6 +2657,13 @@ int cmd_stat(int argc, const char **argv)
stat_config.aggr_mode = opt_aggr_mode_to_aggr_mode(&opt_mode);
+ if (stat_config.csv_sep && stat_config.json_output) {
+ fprintf(stderr, "cannot use both --field-separator and --json-output\n");
+ parse_options_usage(stat_usage, stat_options, "x", 1);
+ parse_options_usage(NULL, stat_options, "j", 1);
+ goto out;
+ }
+
if (stat_config.csv_sep) {
stat_config.csv_output = true;
if (!strcmp(stat_config.csv_sep, "\\t"))
@@ -2651,7 +2672,7 @@ int cmd_stat(int argc, const char **argv)
stat_config.csv_sep = DEFAULT_SEPARATOR;
if (affinity_set)
- evsel_list->no_affinity = !affinity;
+ evlist__set_no_affinity(evsel_list, !affinity);
if (argc && strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
argc = __cmd_record(stat_options, &opt_mode, argc, argv);
@@ -2714,7 +2735,8 @@ int cmd_stat(int argc, const char **argv)
output = fopen(output_name, mode);
if (!output) {
perror("failed to create output file");
- return -1;
+ status = -1;
+ goto out;
}
if (!stat_config.json_output) {
clock_gettime(CLOCK_REALTIME, &tm);
@@ -2725,7 +2747,8 @@ int cmd_stat(int argc, const char **argv)
output = fdopen(output_fd, mode);
if (!output) {
perror("Failed opening logfd");
- return -errno;
+ status = -errno;
+ goto out;
}
}
@@ -2734,7 +2757,8 @@ int cmd_stat(int argc, const char **argv)
parse_options_usage(stat_usage, stat_options, "o", 1);
parse_options_usage(NULL, stat_options, "log-fd", 0);
parse_options_usage(NULL, stat_options, "interval-clear", 0);
- return -1;
+ status = -1;
+ goto out;
}
stat_config.output = output;
@@ -2818,7 +2842,7 @@ int cmd_stat(int argc, const char **argv)
}
if (stat_config.iostat_run) {
- status = iostat_prepare(evsel_list, &stat_config);
+ status = iostat_prepare(&evsel_list, &stat_config);
if (status)
goto out;
if (iostat_mode == IOSTAT_LIST) {
@@ -2848,7 +2872,9 @@ int cmd_stat(int argc, const char **argv)
*/
if (metrics) {
const char *pmu = parse_events_option_args.pmu_filter ?: "all";
- int ret = metricgroup__parse_groups(evsel_list, pmu, metrics,
+ int ret = metricgroup__parse_groups(evsel_list, pmu,
+ parse_events_option_args.cputype_filter,
+ metrics,
stat_config.metric_no_group,
stat_config.metric_no_merge,
stat_config.metric_no_threshold,
@@ -2874,7 +2900,8 @@ int cmd_stat(int argc, const char **argv)
goto out;
}
- if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list, true) < 0) {
+ if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list,
+ !target.use_bpf) < 0) {
parse_options_usage(stat_usage, stat_options,
"for-each-cgroup", 0);
goto out;
@@ -2882,9 +2909,10 @@ int cmd_stat(int argc, const char **argv)
}
#ifdef HAVE_BPF_SKEL
if (target.use_bpf && nr_cgroups &&
- (evsel_list->core.nr_entries / nr_cgroups) > BPERF_CGROUP__MAX_EVENTS) {
+ (evlist__nr_entries(evsel_list) / nr_cgroups) > BPERF_CGROUP__MAX_EVENTS) {
pr_warning("Disabling BPF counters due to more events (%d) than the max (%d)\n",
- evsel_list->core.nr_entries / nr_cgroups, BPERF_CGROUP__MAX_EVENTS);
+ evlist__nr_entries(evsel_list) / nr_cgroups,
+ BPERF_CGROUP__MAX_EVENTS);
target.use_bpf = false;
}
#endif // HAVE_BPF_SKEL
@@ -2922,7 +2950,7 @@ int cmd_stat(int argc, const char **argv)
* so we could print it out on output.
*/
if (stat_config.aggr_mode == AGGR_THREAD) {
- thread_map__read_comms(evsel_list->core.threads);
+ thread_map__read_comms(evlist__core(evsel_list)->threads);
}
if (stat_config.aggr_mode == AGGR_NODE)
@@ -3066,7 +3094,7 @@ out:
if (smi_cost && smi_reset)
sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
- evlist__delete(evsel_list);
+ evlist__put(evsel_list);
evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close);