diff options
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r-- | tools/perf/builtin-stat.c | 84 |
1 files changed, 26 insertions, 58 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a8b00b44b3cd..065e79eb2142 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -53,8 +53,6 @@ | |||
53 | #include <math.h> | 53 | #include <math.h> |
54 | #include <locale.h> | 54 | #include <locale.h> |
55 | 55 | ||
56 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | ||
57 | |||
58 | #define DEFAULT_SEPARATOR " " | 56 | #define DEFAULT_SEPARATOR " " |
59 | 57 | ||
60 | static struct perf_event_attr default_attrs[] = { | 58 | static struct perf_event_attr default_attrs[] = { |
@@ -160,56 +158,24 @@ struct stats runtime_cycles_stats[MAX_NR_CPUS]; | |||
160 | struct stats runtime_branches_stats[MAX_NR_CPUS]; | 158 | struct stats runtime_branches_stats[MAX_NR_CPUS]; |
161 | struct stats walltime_nsecs_stats; | 159 | struct stats walltime_nsecs_stats; |
162 | 160 | ||
163 | #define ERR_PERF_OPEN \ | 161 | static int create_perf_stat_counter(struct perf_evsel *evsel) |
164 | "counter %d, sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information." | ||
165 | |||
166 | static int create_perf_stat_counter(struct perf_evsel *evsel, bool *perm_err) | ||
167 | { | 162 | { |
168 | struct perf_event_attr *attr = &evsel->attr; | 163 | struct perf_event_attr *attr = &evsel->attr; |
169 | int thread; | ||
170 | int ncreated = 0; | ||
171 | 164 | ||
172 | if (scale) | 165 | if (scale) |
173 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | 166 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | |
174 | PERF_FORMAT_TOTAL_TIME_RUNNING; | 167 | PERF_FORMAT_TOTAL_TIME_RUNNING; |
175 | 168 | ||
176 | if (system_wide) { | 169 | if (system_wide) |
177 | int cpu; | 170 | return perf_evsel__open_per_cpu(evsel, nr_cpus, cpumap); |
178 | 171 | ||
179 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 172 | attr->inherit = !no_inherit; |
180 | FD(evsel, cpu, 0) = sys_perf_event_open(attr, | 173 | if (target_pid == -1 && target_tid == -1) { |
181 | -1, cpumap[cpu], -1, 0); | 174 | attr->disabled = 1; |
182 | if (FD(evsel, cpu, 0) < 0) { | 175 | attr->enable_on_exec = 1; |
183 | if (errno == EPERM || errno == EACCES) | ||
184 | *perm_err = true; | ||
185 | error(ERR_PERF_OPEN, evsel->idx, | ||
186 | FD(evsel, cpu, 0), strerror(errno)); | ||
187 | } else { | ||
188 | ++ncreated; | ||
189 | } | ||
190 | } | ||
191 | } else { | ||
192 | attr->inherit = !no_inherit; | ||
193 | if (target_pid == -1 && target_tid == -1) { | ||
194 | attr->disabled = 1; | ||
195 | attr->enable_on_exec = 1; | ||
196 | } | ||
197 | for (thread = 0; thread < thread_num; thread++) { | ||
198 | FD(evsel, 0, thread) = sys_perf_event_open(attr, | ||
199 | all_tids[thread], -1, -1, 0); | ||
200 | if (FD(evsel, 0, thread) < 0) { | ||
201 | if (errno == EPERM || errno == EACCES) | ||
202 | *perm_err = true; | ||
203 | error(ERR_PERF_OPEN, evsel->idx, | ||
204 | FD(evsel, 0, thread), | ||
205 | strerror(errno)); | ||
206 | } else { | ||
207 | ++ncreated; | ||
208 | } | ||
209 | } | ||
210 | } | 176 | } |
211 | 177 | ||
212 | return ncreated; | 178 | return perf_evsel__open_per_thread(evsel, thread_num, all_tids); |
213 | } | 179 | } |
214 | 180 | ||
215 | /* | 181 | /* |
@@ -289,9 +255,7 @@ static int run_perf_stat(int argc __used, const char **argv) | |||
289 | unsigned long long t0, t1; | 255 | unsigned long long t0, t1; |
290 | struct perf_evsel *counter; | 256 | struct perf_evsel *counter; |
291 | int status = 0; | 257 | int status = 0; |
292 | int ncreated = 0; | ||
293 | int child_ready_pipe[2], go_pipe[2]; | 258 | int child_ready_pipe[2], go_pipe[2]; |
294 | bool perm_err = false; | ||
295 | const bool forks = (argc > 0); | 259 | const bool forks = (argc > 0); |
296 | char buf; | 260 | char buf; |
297 | 261 | ||
@@ -349,19 +313,23 @@ static int run_perf_stat(int argc __used, const char **argv) | |||
349 | close(child_ready_pipe[0]); | 313 | close(child_ready_pipe[0]); |
350 | } | 314 | } |
351 | 315 | ||
352 | list_for_each_entry(counter, &evsel_list, node) | 316 | list_for_each_entry(counter, &evsel_list, node) { |
353 | ncreated += create_perf_stat_counter(counter, &perm_err); | 317 | if (create_perf_stat_counter(counter) < 0) { |
354 | 318 | if (errno == -EPERM || errno == -EACCES) { | |
355 | if (ncreated < nr_counters) { | 319 | error("You may not have permission to collect %sstats.\n" |
356 | if (perm_err) | 320 | "\t Consider tweaking" |
357 | error("You may not have permission to collect %sstats.\n" | 321 | " /proc/sys/kernel/perf_event_paranoid or running as root.", |
358 | "\t Consider tweaking" | 322 | system_wide ? "system-wide " : ""); |
359 | " /proc/sys/kernel/perf_event_paranoid or running as root.", | 323 | } else { |
360 | system_wide ? "system-wide " : ""); | 324 | error("open_counter returned with %d (%s). " |
361 | die("Not all events could be opened.\n"); | 325 | "/bin/dmesg may provide additional information.\n", |
362 | if (child_pid != -1) | 326 | errno, strerror(errno)); |
363 | kill(child_pid, SIGTERM); | 327 | } |
364 | return -1; | 328 | if (child_pid != -1) |
329 | kill(child_pid, SIGTERM); | ||
330 | die("Not all events could be opened.\n"); | ||
331 | return -1; | ||
332 | } | ||
365 | } | 333 | } |
366 | 334 | ||
367 | /* | 335 | /* |