diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-12-13 11:13:07 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-01-24 14:40:08 -0500 |
commit | 594ac61ad3be9c80c738a9fe3bb95c05d8d1bae1 (patch) | |
tree | 3fb2c1395bafd1799e34443d58adef6c4b65c7fe /tools | |
parent | ce90e3856ba55af4d3d9c9c1168cc624607f6c7c (diff) |
perf evsel: Do missing feature fallbacks in just one place
Instead of doing it in stat, top, record or any other tool that opens
event descriptors.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-vr8hzph83d5t2mdlkf565h84@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-record.c | 36 | ||||
-rw-r--r-- | tools/perf/builtin-stat.c | 30 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 20 | ||||
-rw-r--r-- | tools/perf/perf.h | 2 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 31 | ||||
-rw-r--r-- | tools/perf/util/top.h | 2 |
6 files changed, 31 insertions, 90 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 028de726b832..a4b97269cfc6 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -234,25 +234,6 @@ static int perf_record__open(struct perf_record *rec) | |||
234 | 234 | ||
235 | list_for_each_entry(pos, &evlist->entries, node) { | 235 | list_for_each_entry(pos, &evlist->entries, node) { |
236 | struct perf_event_attr *attr = &pos->attr; | 236 | struct perf_event_attr *attr = &pos->attr; |
237 | /* | ||
238 | * Check if parse_single_tracepoint_event has already asked for | ||
239 | * PERF_SAMPLE_TIME. | ||
240 | * | ||
241 | * XXX this is kludgy but short term fix for problems introduced by | ||
242 | * eac23d1c that broke 'perf script' by having different sample_types | ||
243 | * when using multiple tracepoint events when we use a perf binary | ||
244 | * that tries to use sample_id_all on an older kernel. | ||
245 | * | ||
246 | * We need to move counter creation to perf_session, support | ||
247 | * different sample_types, etc. | ||
248 | */ | ||
249 | bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; | ||
250 | |||
251 | fallback_missing_features: | ||
252 | if (opts->exclude_guest_missing) | ||
253 | attr->exclude_guest = attr->exclude_host = 0; | ||
254 | retry_sample_id: | ||
255 | attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; | ||
256 | try_again: | 237 | try_again: |
257 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { | 238 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { |
258 | int err = errno; | 239 | int err = errno; |
@@ -266,23 +247,6 @@ try_again: | |||
266 | " an out-of-range profile CPU?\n"); | 247 | " an out-of-range profile CPU?\n"); |
267 | rc = -err; | 248 | rc = -err; |
268 | goto out; | 249 | goto out; |
269 | } else if (err == EINVAL) { | ||
270 | if (!opts->exclude_guest_missing && | ||
271 | (attr->exclude_guest || attr->exclude_host)) { | ||
272 | pr_debug("Old kernel, cannot exclude " | ||
273 | "guest or host samples.\n"); | ||
274 | opts->exclude_guest_missing = true; | ||
275 | goto fallback_missing_features; | ||
276 | } else if (!opts->sample_id_all_missing) { | ||
277 | /* | ||
278 | * Old kernel, no attr->sample_id_type_all field | ||
279 | */ | ||
280 | opts->sample_id_all_missing = true; | ||
281 | if (!opts->sample_time && !opts->raw_samples && !time_needed) | ||
282 | perf_evsel__reset_sample_bit(pos, TIME); | ||
283 | |||
284 | goto retry_sample_id; | ||
285 | } | ||
286 | } | 250 | } |
287 | 251 | ||
288 | /* | 252 | /* |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c12655af2b88..ef067c193f93 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -132,8 +132,6 @@ static struct stats walltime_nsecs_stats; | |||
132 | static int create_perf_stat_counter(struct perf_evsel *evsel) | 132 | static int create_perf_stat_counter(struct perf_evsel *evsel) |
133 | { | 133 | { |
134 | struct perf_event_attr *attr = &evsel->attr; | 134 | struct perf_event_attr *attr = &evsel->attr; |
135 | bool exclude_guest_missing = false; | ||
136 | int ret; | ||
137 | 135 | ||
138 | if (scale) | 136 | if (scale) |
139 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | 137 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | |
@@ -141,16 +139,8 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) | |||
141 | 139 | ||
142 | attr->inherit = !no_inherit; | 140 | attr->inherit = !no_inherit; |
143 | 141 | ||
144 | retry: | 142 | if (perf_target__has_cpu(&target)) |
145 | if (exclude_guest_missing) | 143 | return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); |
146 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; | ||
147 | |||
148 | if (perf_target__has_cpu(&target)) { | ||
149 | ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); | ||
150 | if (ret) | ||
151 | goto check_ret; | ||
152 | return 0; | ||
153 | } | ||
154 | 144 | ||
155 | if (!perf_target__has_task(&target) && | 145 | if (!perf_target__has_task(&target) && |
156 | perf_evsel__is_group_leader(evsel)) { | 146 | perf_evsel__is_group_leader(evsel)) { |
@@ -158,21 +148,7 @@ retry: | |||
158 | attr->enable_on_exec = 1; | 148 | attr->enable_on_exec = 1; |
159 | } | 149 | } |
160 | 150 | ||
161 | ret = perf_evsel__open_per_thread(evsel, evsel_list->threads); | 151 | return perf_evsel__open_per_thread(evsel, evsel_list->threads); |
162 | if (!ret) | ||
163 | return 0; | ||
164 | /* fall through */ | ||
165 | check_ret: | ||
166 | if (ret && errno == EINVAL) { | ||
167 | if (!exclude_guest_missing && | ||
168 | (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { | ||
169 | pr_debug("Old kernel, cannot exclude " | ||
170 | "guest or host samples.\n"); | ||
171 | exclude_guest_missing = true; | ||
172 | goto retry; | ||
173 | } | ||
174 | } | ||
175 | return ret; | ||
176 | } | 152 | } |
177 | 153 | ||
178 | /* | 154 | /* |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b7d2ea62dbc6..74fca619fc4e 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -900,12 +900,6 @@ static void perf_top__start_counters(struct perf_top *top) | |||
900 | 900 | ||
901 | list_for_each_entry(counter, &evlist->entries, node) { | 901 | list_for_each_entry(counter, &evlist->entries, node) { |
902 | struct perf_event_attr *attr = &counter->attr; | 902 | struct perf_event_attr *attr = &counter->attr; |
903 | |||
904 | fallback_missing_features: | ||
905 | if (top->exclude_guest_missing) | ||
906 | attr->exclude_guest = attr->exclude_host = 0; | ||
907 | retry_sample_id: | ||
908 | attr->sample_id_all = top->sample_id_all_missing ? 0 : 1; | ||
909 | try_again: | 903 | try_again: |
910 | if (perf_evsel__open(counter, top->evlist->cpus, | 904 | if (perf_evsel__open(counter, top->evlist->cpus, |
911 | top->evlist->threads) < 0) { | 905 | top->evlist->threads) < 0) { |
@@ -914,20 +908,6 @@ try_again: | |||
914 | if (err == EPERM || err == EACCES) { | 908 | if (err == EPERM || err == EACCES) { |
915 | ui__error_paranoid(); | 909 | ui__error_paranoid(); |
916 | goto out_err; | 910 | goto out_err; |
917 | } else if (err == EINVAL) { | ||
918 | if (!top->exclude_guest_missing && | ||
919 | (attr->exclude_guest || attr->exclude_host)) { | ||
920 | pr_debug("Old kernel, cannot exclude " | ||
921 | "guest or host samples.\n"); | ||
922 | top->exclude_guest_missing = true; | ||
923 | goto fallback_missing_features; | ||
924 | } else if (!top->sample_id_all_missing) { | ||
925 | /* | ||
926 | * Old kernel, no attr->sample_id_type_all field | ||
927 | */ | ||
928 | top->sample_id_all_missing = true; | ||
929 | goto retry_sample_id; | ||
930 | } | ||
931 | } | 911 | } |
932 | /* | 912 | /* |
933 | * If it's cycles then fall back to hrtimer | 913 | * If it's cycles then fall back to hrtimer |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 2c340e7da458..7622f15bcfb7 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -237,8 +237,6 @@ struct perf_record_opts { | |||
237 | bool raw_samples; | 237 | bool raw_samples; |
238 | bool sample_address; | 238 | bool sample_address; |
239 | bool sample_time; | 239 | bool sample_time; |
240 | bool sample_id_all_missing; | ||
241 | bool exclude_guest_missing; | ||
242 | bool period; | 240 | bool period; |
243 | unsigned int freq; | 241 | unsigned int freq; |
244 | unsigned int mmap_pages; | 242 | unsigned int mmap_pages; |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7a2a3dc3ff03..ee6ee3f45c2a 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -22,6 +22,11 @@ | |||
22 | #include <linux/perf_event.h> | 22 | #include <linux/perf_event.h> |
23 | #include "perf_regs.h" | 23 | #include "perf_regs.h" |
24 | 24 | ||
25 | static struct { | ||
26 | bool sample_id_all; | ||
27 | bool exclude_guest; | ||
28 | } perf_missing_features; | ||
29 | |||
25 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 30 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
26 | 31 | ||
27 | static int __perf_evsel__sample_size(u64 sample_type) | 32 | static int __perf_evsel__sample_size(u64 sample_type) |
@@ -463,7 +468,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
463 | struct perf_event_attr *attr = &evsel->attr; | 468 | struct perf_event_attr *attr = &evsel->attr; |
464 | int track = !evsel->idx; /* only the first counter needs these */ | 469 | int track = !evsel->idx; /* only the first counter needs these */ |
465 | 470 | ||
466 | attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; | 471 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; |
467 | attr->inherit = !opts->no_inherit; | 472 | attr->inherit = !opts->no_inherit; |
468 | 473 | ||
469 | perf_evsel__set_sample_bit(evsel, IP); | 474 | perf_evsel__set_sample_bit(evsel, IP); |
@@ -513,7 +518,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
513 | if (opts->period) | 518 | if (opts->period) |
514 | perf_evsel__set_sample_bit(evsel, PERIOD); | 519 | perf_evsel__set_sample_bit(evsel, PERIOD); |
515 | 520 | ||
516 | if (!opts->sample_id_all_missing && | 521 | if (!perf_missing_features.sample_id_all && |
517 | (opts->sample_time || !opts->no_inherit || | 522 | (opts->sample_time || !opts->no_inherit || |
518 | perf_target__has_cpu(&opts->target))) | 523 | perf_target__has_cpu(&opts->target))) |
519 | perf_evsel__set_sample_bit(evsel, TIME); | 524 | perf_evsel__set_sample_bit(evsel, TIME); |
@@ -761,6 +766,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
761 | pid = evsel->cgrp->fd; | 766 | pid = evsel->cgrp->fd; |
762 | } | 767 | } |
763 | 768 | ||
769 | fallback_missing_features: | ||
770 | if (perf_missing_features.exclude_guest) | ||
771 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; | ||
772 | retry_sample_id: | ||
773 | if (perf_missing_features.sample_id_all) | ||
774 | evsel->attr.sample_id_all = 0; | ||
775 | |||
764 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 776 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
765 | 777 | ||
766 | for (thread = 0; thread < threads->nr; thread++) { | 778 | for (thread = 0; thread < threads->nr; thread++) { |
@@ -777,13 +789,26 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
777 | group_fd, flags); | 789 | group_fd, flags); |
778 | if (FD(evsel, cpu, thread) < 0) { | 790 | if (FD(evsel, cpu, thread) < 0) { |
779 | err = -errno; | 791 | err = -errno; |
780 | goto out_close; | 792 | goto try_fallback; |
781 | } | 793 | } |
782 | } | 794 | } |
783 | } | 795 | } |
784 | 796 | ||
785 | return 0; | 797 | return 0; |
786 | 798 | ||
799 | try_fallback: | ||
800 | if (err != -EINVAL || cpu > 0 || thread > 0) | ||
801 | goto out_close; | ||
802 | |||
803 | if (!perf_missing_features.exclude_guest && | ||
804 | (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { | ||
805 | perf_missing_features.exclude_guest = true; | ||
806 | goto fallback_missing_features; | ||
807 | } else if (!perf_missing_features.sample_id_all) { | ||
808 | perf_missing_features.sample_id_all = true; | ||
809 | goto retry_sample_id; | ||
810 | } | ||
811 | |||
787 | out_close: | 812 | out_close: |
788 | do { | 813 | do { |
789 | while (--thread >= 0) { | 814 | while (--thread >= 0) { |
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 927c229c2d9a..7ebf357dc9e1 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h | |||
@@ -29,8 +29,6 @@ struct perf_top { | |||
29 | bool sort_has_symbols; | 29 | bool sort_has_symbols; |
30 | bool kptr_restrict_warned; | 30 | bool kptr_restrict_warned; |
31 | bool vmlinux_warned; | 31 | bool vmlinux_warned; |
32 | bool sample_id_all_missing; | ||
33 | bool exclude_guest_missing; | ||
34 | bool dump_symtab; | 32 | bool dump_symtab; |
35 | struct hist_entry *sym_filter_entry; | 33 | struct hist_entry *sym_filter_entry; |
36 | struct perf_evsel *sym_evsel; | 34 | struct perf_evsel *sym_evsel; |