diff options
author | Jiri Olsa <jolsa@redhat.com> | 2013-11-05 09:14:47 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-11-05 13:15:08 -0500 |
commit | 714647bdc516330e4405b39677d7f763e016c685 (patch) | |
tree | 13aaae6374601031ff2393d11ee8a28d37072a6d /tools/perf | |
parent | a9862418547e818aa5842840aecfa81d733b97e9 (diff) |
perf tools: Check maximum frequency rate for record/top
Adding the check for maximum allowed frequency rate defined in following
file:
/proc/sys/kernel/perf_event_max_sample_rate
When we cross the maximum value we fail and display detailed error
message with advise.
$ perf record -F 3000 ls
Maximum frequency rate (2000) reached.
Please use -F freq option with lower value or consider
tweaking /proc/sys/kernel/perf_event_max_sample_rate.
In case user does not specify the frequency and the default value cross
the maximum, we display warning and set the frequency value to the
current maximum.
$ perf record ls
Lowering default frequency rate to 2000.
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate.
Same messages are used for 'perf top'.
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1383660887-1734-4-git-send-email-jolsa@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-record.c | 15 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 15 | ||||
-rw-r--r-- | tools/perf/util/evlist.h | 1 | ||||
-rw-r--r-- | tools/perf/util/record.c | 71 |
4 files changed, 74 insertions, 28 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8b45fcead5f6..ea4c04f7437e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -958,20 +958,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
958 | if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) | 958 | if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) |
959 | usage_with_options(record_usage, record_options); | 959 | usage_with_options(record_usage, record_options); |
960 | 960 | ||
961 | if (rec->opts.user_interval != ULLONG_MAX) | 961 | if (perf_record_opts__config(&rec->opts)) { |
962 | rec->opts.default_interval = rec->opts.user_interval; | ||
963 | if (rec->opts.user_freq != UINT_MAX) | ||
964 | rec->opts.freq = rec->opts.user_freq; | ||
965 | |||
966 | /* | ||
967 | * User specified count overrides default frequency. | ||
968 | */ | ||
969 | if (rec->opts.default_interval) | ||
970 | rec->opts.freq = 0; | ||
971 | else if (rec->opts.freq) { | ||
972 | rec->opts.default_interval = rec->opts.freq; | ||
973 | } else { | ||
974 | ui__error("frequency and count are zero, aborting\n"); | ||
975 | err = -EINVAL; | 962 | err = -EINVAL; |
976 | goto out_free_fd; | 963 | goto out_free_fd; |
977 | } | 964 | } |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 21897f0ffcd3..9acca8856ccb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -1209,20 +1209,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1209 | if (top.delay_secs < 1) | 1209 | if (top.delay_secs < 1) |
1210 | top.delay_secs = 1; | 1210 | top.delay_secs = 1; |
1211 | 1211 | ||
1212 | if (opts->user_interval != ULLONG_MAX) | 1212 | if (perf_record_opts__config(opts)) { |
1213 | opts->default_interval = opts->user_interval; | ||
1214 | if (opts->user_freq != UINT_MAX) | ||
1215 | opts->freq = opts->user_freq; | ||
1216 | |||
1217 | /* | ||
1218 | * User specified count overrides default frequency. | ||
1219 | */ | ||
1220 | if (opts->default_interval) | ||
1221 | opts->freq = 0; | ||
1222 | else if (opts->freq) { | ||
1223 | opts->default_interval = opts->freq; | ||
1224 | } else { | ||
1225 | ui__error("frequency and count are zero, aborting\n"); | ||
1226 | status = -EINVAL; | 1213 | status = -EINVAL; |
1227 | goto out_delete_maps; | 1214 | goto out_delete_maps; |
1228 | } | 1215 | } |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 6e8acc9abe38..0617ce2a0679 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -99,6 +99,7 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist); | |||
99 | bool perf_can_sample_identifier(void); | 99 | bool perf_can_sample_identifier(void); |
100 | void perf_evlist__config(struct perf_evlist *evlist, | 100 | void perf_evlist__config(struct perf_evlist *evlist, |
101 | struct perf_record_opts *opts); | 101 | struct perf_record_opts *opts); |
102 | int perf_record_opts__config(struct perf_record_opts *opts); | ||
102 | 103 | ||
103 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, | 104 | int perf_evlist__prepare_workload(struct perf_evlist *evlist, |
104 | struct perf_target *target, | 105 | struct perf_target *target, |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 18d73aa2f0f8..c8845b107f60 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -2,6 +2,8 @@ | |||
2 | #include "evsel.h" | 2 | #include "evsel.h" |
3 | #include "cpumap.h" | 3 | #include "cpumap.h" |
4 | #include "parse-events.h" | 4 | #include "parse-events.h" |
5 | #include "fs.h" | ||
6 | #include "util.h" | ||
5 | 7 | ||
6 | typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); | 8 | typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); |
7 | 9 | ||
@@ -106,3 +108,72 @@ void perf_evlist__config(struct perf_evlist *evlist, | |||
106 | 108 | ||
107 | perf_evlist__set_id_pos(evlist); | 109 | perf_evlist__set_id_pos(evlist); |
108 | } | 110 | } |
111 | |||
112 | static int get_max_rate(unsigned int *rate) | ||
113 | { | ||
114 | char path[PATH_MAX]; | ||
115 | const char *procfs = procfs__mountpoint(); | ||
116 | |||
117 | if (!procfs) | ||
118 | return -1; | ||
119 | |||
120 | snprintf(path, PATH_MAX, | ||
121 | "%s/sys/kernel/perf_event_max_sample_rate", procfs); | ||
122 | |||
123 | return filename__read_int(path, (int *) rate); | ||
124 | } | ||
125 | |||
126 | static int perf_record_opts__config_freq(struct perf_record_opts *opts) | ||
127 | { | ||
128 | bool user_freq = opts->user_freq != UINT_MAX; | ||
129 | unsigned int max_rate; | ||
130 | |||
131 | if (opts->user_interval != ULLONG_MAX) | ||
132 | opts->default_interval = opts->user_interval; | ||
133 | if (user_freq) | ||
134 | opts->freq = opts->user_freq; | ||
135 | |||
136 | /* | ||
137 | * User specified count overrides default frequency. | ||
138 | */ | ||
139 | if (opts->default_interval) | ||
140 | opts->freq = 0; | ||
141 | else if (opts->freq) { | ||
142 | opts->default_interval = opts->freq; | ||
143 | } else { | ||
144 | pr_err("frequency and count are zero, aborting\n"); | ||
145 | return -1; | ||
146 | } | ||
147 | |||
148 | if (get_max_rate(&max_rate)) | ||
149 | return 0; | ||
150 | |||
151 | /* | ||
152 | * User specified frequency is over current maximum. | ||
153 | */ | ||
154 | if (user_freq && (max_rate < opts->freq)) { | ||
155 | pr_err("Maximum frequency rate (%u) reached.\n" | ||
156 | "Please use -F freq option with lower value or consider\n" | ||
157 | "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", | ||
158 | max_rate); | ||
159 | return -1; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Default frequency is over current maximum. | ||
164 | */ | ||
165 | if (max_rate < opts->freq) { | ||
166 | pr_warning("Lowering default frequency rate to %u.\n" | ||
167 | "Please consider tweaking " | ||
168 | "/proc/sys/kernel/perf_event_max_sample_rate.\n", | ||
169 | max_rate); | ||
170 | opts->freq = max_rate; | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | int perf_record_opts__config(struct perf_record_opts *opts) | ||
177 | { | ||
178 | return perf_record_opts__config_freq(opts); | ||
179 | } | ||