diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-01-14 17:25:12 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-01-14 17:25:12 +0100 |
commit | 197749981e539c1eb5863f417de6dd4e2c02b76c (patch) | |
tree | d7c81373a9ea1b833163e9c36d727b1b6ddab067 /tools/perf/builtin-stat.c | |
parent | 1341f3e4c0276aae3de6d902c9202265d89fe438 (diff) | |
parent | 26f7f9877234e6b9ed87eff4ca450631bafe0182 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf tooling updates from Arnaldo Carvalho de Melo:
New features:
* perf record: Add --initial-delay option (Andi Kleen)
* Column colouring improvements in 'diff' (Ramkumar Ramachandra)
Fixes:
* Don't show counter information when workload fails (Arnaldo Carvalho de Melo)
* Fixup leak on error path in parse events test. (Arnaldo Carvalho de Melo)
* Fix --delay option in 'stat' man page (Andi Kleen)
* Use the DWARF unwind info only if loaded (Jean Pihet):
Developer stuff:
* Improve forked workload error reporting by sending the errno in the signal
data queueing integer field, using sigqueue and by doing the signal setup in
the evlist methods, removing open coded equivalents in various tools. (Arnaldo Carvalho de Melo)
* Do more auto exit cleanup shores in the 'evlist' destructor, so that the tools
don't have to all do that sequence. (Arnaldo Carvalho de Melo)
* Pack 'struct perf_session_env' and 'struct trace' (Arnaldo Carvalho de Melo)
* Include tools/lib/api/ in MANIFEST, fixing detached tarballs (Arnaldo Carvalho de Melo)
* Add test for building detached source tarballs (Arnaldo Carvalho de Melo)
* Shut up libtracevent plugins make message (Jiri Olsa)
* Fix installation tests path setup (Jiri Olsa)
* Fix id_hdr_size initialization (Jiri Olsa)
* Move some header files from tools/perf/ to tools/include/ to make them available to
other tools/ dwelling codebases (Namhyung Kim)
* Fix 'probe' build when DWARF support libraries not present (Arnaldo Carvalho de Melo)
Refactorings:
* Move logic to warn about kptr_restrict'ed kernels to separate
function in 'report' (Arnaldo Carvalho de Melo)
* Move hist browser selection code to separate function (Arnaldo Carvalho de Melo)
* Move histogram entries collapsing to separate function (Arnaldo Carvalho de Melo)
* Introduce evlist__for_each() & friends (Arnaldo Carvalho de Melo)
* Automate setup of FEATURE_CHECK_(C|LD)FLAGS-all variables (Jiri Olsa)
* Move arch setup into seprate Makefile (Jiri Olsa)
Trivial stuff:
* Remove misplaced __maybe_unused in 'stat' (Arnaldo Carvalho de Melo)
* Remove old evsel_list usage in 'record' (Arnaldo Carvalho de Melo)
* Comment typo fix (Cody P Schafer)
* Remove unused test-volatile-register-var.c (Yann Droneaud)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r-- | tools/perf/builtin-stat.c | 66 |
1 files changed, 42 insertions, 24 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 106a5e5b7842..8b0e1c9234d9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -214,7 +214,7 @@ static void perf_evlist__free_stats(struct perf_evlist *evlist) { struct perf_evsel *evsel; - list_for_each_entry(evsel, &evlist->entries, node) { + evlist__for_each(evlist, evsel) { perf_evsel__free_stat_priv(evsel); perf_evsel__free_counts(evsel); perf_evsel__free_prev_raw_counts(evsel); @@ -225,7 +225,7 @@ static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) { struct perf_evsel *evsel; - list_for_each_entry(evsel, &evlist->entries, node) { + evlist__for_each(evlist, evsel) { if (perf_evsel__alloc_stat_priv(evsel) < 0 || perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 || (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0)) @@ -259,7 +259,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist) { struct perf_evsel *evsel; - list_for_each_entry(evsel, &evlist->entries, node) { + evlist__for_each(evlist, evsel) { perf_evsel__reset_stat_priv(evsel); perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel)); } @@ -326,13 +326,13 @@ static struct perf_evsel *nth_evsel(int n) /* Assumes this only called when evsel_list does not change anymore. */ if (!array) { - list_for_each_entry(ev, &evsel_list->entries, node) + evlist__for_each(evsel_list, ev) array_len++; array = malloc(array_len * sizeof(void *)); if (!array) exit(ENOMEM); j = 0; - list_for_each_entry(ev, &evsel_list->entries, node) + evlist__for_each(evsel_list, ev) array[j++] = ev; } if (n < array_len) @@ -440,13 +440,13 @@ static void print_interval(void) char prefix[64]; if (aggr_mode == AGGR_GLOBAL) { - list_for_each_entry(counter, &evsel_list->entries, node) { + evlist__for_each(evsel_list, counter) { ps = counter->priv; memset(ps->res_stats, 0, sizeof(ps->res_stats)); read_counter_aggr(counter); } } else { - list_for_each_entry(counter, &evsel_list->entries, node) { + evlist__for_each(evsel_list, counter) { ps = counter->priv; memset(ps->res_stats, 0, sizeof(ps->res_stats)); read_counter(counter); @@ -483,12 +483,12 @@ static void print_interval(void) print_aggr(prefix); break; case AGGR_NONE: - list_for_each_entry(counter, &evsel_list->entries, node) + evlist__for_each(evsel_list, counter) print_counter(counter, prefix); break; case AGGR_GLOBAL: default: - list_for_each_entry(counter, &evsel_list->entries, node) + evlist__for_each(evsel_list, counter) print_counter_aggr(counter, prefix); } @@ -504,11 +504,24 @@ static void handle_initial_delay(void) nthreads = thread_map__nr(evsel_list->threads); usleep(initial_delay * 1000); - list_for_each_entry(counter, &evsel_list->entries, node) + evlist__for_each(evsel_list, counter) perf_evsel__enable(counter, ncpus, nthreads); } } +static volatile int workload_exec_errno; + +/* + * perf_evlist__prepare_workload will send a SIGUSR1 + * if the fork fails, since we asked by setting its + * want_signal to true. + */ +static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, + void *ucontext __maybe_unused) +{ + workload_exec_errno = info->si_value.sival_int; +} + static int __run_perf_stat(int argc, const char **argv) { char msg[512]; @@ -528,8 +541,8 @@ static int __run_perf_stat(int argc, const char **argv) } if (forks) { - if (perf_evlist__prepare_workload(evsel_list, &target, argv, - false, false) < 0) { + if (perf_evlist__prepare_workload(evsel_list, &target, argv, false, + workload_exec_failed_signal) < 0) { perror("failed to prepare workload"); return -1; } @@ -539,7 +552,7 @@ static int __run_perf_stat(int argc, const char **argv) if (group) perf_evlist__set_leader(evsel_list); - list_for_each_entry(counter, &evsel_list->entries, node) { + evlist__for_each(evsel_list, counter) { if (create_perf_stat_counter(counter) < 0) { /* * PPC returns ENXIO for HW counters until 2.6.37 @@ -594,6 +607,13 @@ static int __run_perf_stat(int argc, const char **argv) } } wait(&status); + + if (workload_exec_errno) { + const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); + pr_err("Workload failed: %s\n", emsg); + return -1; + } + if (WIFSIGNALED(status)) psignal(WTERMSIG(status), argv[0]); } else { @@ -610,13 +630,13 @@ static int __run_perf_stat(int argc, const char **argv) update_stats(&walltime_nsecs_stats, t1 - t0); if (aggr_mode == AGGR_GLOBAL) { - list_for_each_entry(counter, &evsel_list->entries, node) { + evlist__for_each(evsel_list, counter) { read_counter_aggr(counter); perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), thread_map__nr(evsel_list->threads)); } } else { - list_for_each_entry(counter, &evsel_list->entries, node) { + evlist__for_each(evsel_list, counter) { read_counter(counter); perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); } @@ -625,7 +645,7 @@ static int __run_perf_stat(int argc, const char **argv) return WEXITSTATUS(status); } -static int run_perf_stat(int argc __maybe_unused, const char **argv) +static int run_perf_stat(int argc, const char **argv) { int ret; @@ -1097,7 +1117,7 @@ static void print_aggr(char *prefix) for (s = 0; s < aggr_map->nr; s++) { id = aggr_map->map[s]; - list_for_each_entry(counter, &evsel_list->entries, node) { + evlist__for_each(evsel_list, counter) { val = ena = run = 0; nr = 0; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { @@ -1308,11 +1328,11 @@ static void print_stat(int argc, const char **argv) print_aggr(NULL); break; case AGGR_GLOBAL: - list_for_each_entry(counter, &evsel_list->entries, node) + evlist__for_each(evsel_list, counter) print_counter_aggr(counter, NULL); break; case AGGR_NONE: - list_for_each_entry(counter, &evsel_list->entries, node) + evlist__for_each(evsel_list, counter) print_counter(counter, NULL); break; default: @@ -1762,14 +1782,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) if (interval && interval < 100) { pr_err("print interval must be >= 100ms\n"); parse_options_usage(stat_usage, options, "I", 1); - goto out_free_maps; + goto out; } if (perf_evlist__alloc_stats(evsel_list, interval)) - goto out_free_maps; + goto out; if (perf_stat_init_aggr_mode()) - goto out_free_maps; + goto out; /* * We dont want to block the signals - that would cause @@ -1801,8 +1821,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) print_stat(argc, argv); perf_evlist__free_stats(evsel_list); -out_free_maps: - perf_evlist__delete_maps(evsel_list); out: perf_evlist__delete(evsel_list); return status; |