diff options
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r-- | tools/perf/builtin-stat.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 93b9011fa3e2..c247faca7127 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include "util/thread.h" | 57 | #include "util/thread.h" |
58 | #include "util/thread_map.h" | 58 | #include "util/thread_map.h" |
59 | 59 | ||
60 | #include <stdlib.h> | ||
60 | #include <sys/prctl.h> | 61 | #include <sys/prctl.h> |
61 | #include <locale.h> | 62 | #include <locale.h> |
62 | 63 | ||
@@ -83,6 +84,9 @@ static const char *csv_sep = NULL; | |||
83 | static bool csv_output = false; | 84 | static bool csv_output = false; |
84 | static bool group = false; | 85 | static bool group = false; |
85 | static FILE *output = NULL; | 86 | static FILE *output = NULL; |
87 | static const char *pre_cmd = NULL; | ||
88 | static const char *post_cmd = NULL; | ||
89 | static bool sync_run = false; | ||
86 | 90 | ||
87 | static volatile int done = 0; | 91 | static volatile int done = 0; |
88 | 92 | ||
@@ -125,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; | |||
125 | static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; | 129 | static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; |
126 | static struct stats walltime_nsecs_stats; | 130 | static struct stats walltime_nsecs_stats; |
127 | 131 | ||
128 | static int create_perf_stat_counter(struct perf_evsel *evsel, | 132 | static int create_perf_stat_counter(struct perf_evsel *evsel) |
129 | struct perf_evsel *first) | ||
130 | { | 133 | { |
131 | struct perf_event_attr *attr = &evsel->attr; | 134 | struct perf_event_attr *attr = &evsel->attr; |
132 | bool exclude_guest_missing = false; | 135 | bool exclude_guest_missing = false; |
@@ -149,7 +152,8 @@ retry: | |||
149 | return 0; | 152 | return 0; |
150 | } | 153 | } |
151 | 154 | ||
152 | if (!perf_target__has_task(&target) && (!group || evsel == first)) { | 155 | if (!perf_target__has_task(&target) && |
156 | !perf_evsel__is_group_member(evsel)) { | ||
153 | attr->disabled = 1; | 157 | attr->disabled = 1; |
154 | attr->enable_on_exec = 1; | 158 | attr->enable_on_exec = 1; |
155 | } | 159 | } |
@@ -265,10 +269,10 @@ static int read_counter(struct perf_evsel *counter) | |||
265 | return 0; | 269 | return 0; |
266 | } | 270 | } |
267 | 271 | ||
268 | static int run_perf_stat(int argc __maybe_unused, const char **argv) | 272 | static int __run_perf_stat(int argc __maybe_unused, const char **argv) |
269 | { | 273 | { |
270 | unsigned long long t0, t1; | 274 | unsigned long long t0, t1; |
271 | struct perf_evsel *counter, *first; | 275 | struct perf_evsel *counter; |
272 | int status = 0; | 276 | int status = 0; |
273 | int child_ready_pipe[2], go_pipe[2]; | 277 | int child_ready_pipe[2], go_pipe[2]; |
274 | const bool forks = (argc > 0); | 278 | const bool forks = (argc > 0); |
@@ -328,10 +332,8 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) | |||
328 | if (group) | 332 | if (group) |
329 | perf_evlist__set_leader(evsel_list); | 333 | perf_evlist__set_leader(evsel_list); |
330 | 334 | ||
331 | first = perf_evlist__first(evsel_list); | ||
332 | |||
333 | list_for_each_entry(counter, &evsel_list->entries, node) { | 335 | list_for_each_entry(counter, &evsel_list->entries, node) { |
334 | if (create_perf_stat_counter(counter, first) < 0) { | 336 | if (create_perf_stat_counter(counter) < 0) { |
335 | /* | 337 | /* |
336 | * PPC returns ENXIO for HW counters until 2.6.37 | 338 | * PPC returns ENXIO for HW counters until 2.6.37 |
337 | * (behavior changed with commit b0a873e). | 339 | * (behavior changed with commit b0a873e). |
@@ -405,6 +407,32 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) | |||
405 | return WEXITSTATUS(status); | 407 | return WEXITSTATUS(status); |
406 | } | 408 | } |
407 | 409 | ||
410 | static int run_perf_stat(int argc __maybe_unused, const char **argv) | ||
411 | { | ||
412 | int ret; | ||
413 | |||
414 | if (pre_cmd) { | ||
415 | ret = system(pre_cmd); | ||
416 | if (ret) | ||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | if (sync_run) | ||
421 | sync(); | ||
422 | |||
423 | ret = __run_perf_stat(argc, argv); | ||
424 | if (ret) | ||
425 | return ret; | ||
426 | |||
427 | if (post_cmd) { | ||
428 | ret = system(post_cmd); | ||
429 | if (ret) | ||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | return ret; | ||
434 | } | ||
435 | |||
408 | static void print_noise_pct(double total, double avg) | 436 | static void print_noise_pct(double total, double avg) |
409 | { | 437 | { |
410 | double pct = rel_stddev_stats(total, avg); | 438 | double pct = rel_stddev_stats(total, avg); |
@@ -1069,8 +1097,7 @@ static int add_default_attributes(void) | |||
1069 | 1097 | ||
1070 | int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | 1098 | int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) |
1071 | { | 1099 | { |
1072 | bool append_file = false, | 1100 | bool append_file = false; |
1073 | sync_run = false; | ||
1074 | int output_fd = 0; | 1101 | int output_fd = 0; |
1075 | const char *output_name = NULL; | 1102 | const char *output_name = NULL; |
1076 | const struct option options[] = { | 1103 | const struct option options[] = { |
@@ -1114,6 +1141,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1114 | OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), | 1141 | OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), |
1115 | OPT_INTEGER(0, "log-fd", &output_fd, | 1142 | OPT_INTEGER(0, "log-fd", &output_fd, |
1116 | "log output to fd, instead of stderr"), | 1143 | "log output to fd, instead of stderr"), |
1144 | OPT_STRING(0, "pre", &pre_cmd, "command", | ||
1145 | "command to run prior to the measured command"), | ||
1146 | OPT_STRING(0, "post", &post_cmd, "command", | ||
1147 | "command to run after to the measured command"), | ||
1117 | OPT_END() | 1148 | OPT_END() |
1118 | }; | 1149 | }; |
1119 | const char * const stat_usage[] = { | 1150 | const char * const stat_usage[] = { |
@@ -1238,9 +1269,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1238 | fprintf(output, "[ perf stat: executing run #%d ... ]\n", | 1269 | fprintf(output, "[ perf stat: executing run #%d ... ]\n", |
1239 | run_idx + 1); | 1270 | run_idx + 1); |
1240 | 1271 | ||
1241 | if (sync_run) | ||
1242 | sync(); | ||
1243 | |||
1244 | status = run_perf_stat(argc, argv); | 1272 | status = run_perf_stat(argc, argv); |
1245 | } | 1273 | } |
1246 | 1274 | ||