diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-03 14:48:12 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-03 21:23:27 -0500 |
| commit | 48290609c0d265f5dac0fca6fd4e3c5732542f67 (patch) | |
| tree | 7fc8099ae02b78562cca245364cd44197d3ae9a3 | |
| parent | c52b12ed2511e6c031a0295fd903ea72b93701fb (diff) | |
perf evsel: Introduce per cpu and per thread open helpers
Abstracting away the loops needed to create the various event fd handlers.
The users have to pass a confiruged perf->evsel.attr field, which is already
usable after perf_evsel__new (constructor) time, using defaults.
Comes out of the ad-hoc routines in builtin-stat, that now uses it.
Fixed a small silly bug where we were die()ing before killing our
children, dysfunctional family this one 8-)
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/builtin-stat.c | 84 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 52 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 5 |
3 files changed, 83 insertions, 58 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a8b00b44b3c..065e79eb214 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 | /* |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3f5de519623..e62cc5e050a 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include "evsel.h" | 1 | #include "evsel.h" |
| 2 | #include "../perf.h" | ||
| 2 | #include "util.h" | 3 | #include "util.h" |
| 3 | 4 | ||
| 4 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 5 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
| @@ -121,3 +122,54 @@ int __perf_evsel__read(struct perf_evsel *evsel, | |||
| 121 | 122 | ||
| 122 | return 0; | 123 | return 0; |
| 123 | } | 124 | } |
| 125 | |||
| 126 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, int ncpus, int *cpu_map) | ||
| 127 | { | ||
| 128 | int cpu; | ||
| 129 | |||
| 130 | for (cpu = 0; cpu < ncpus; cpu++) { | ||
| 131 | FD(evsel, cpu, 0) = sys_perf_event_open(&evsel->attr, -1, | ||
| 132 | cpu_map[cpu], -1, 0); | ||
| 133 | if (FD(evsel, cpu, 0) < 0) | ||
| 134 | goto out_close; | ||
| 135 | } | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | |||
| 139 | out_close: | ||
| 140 | while (--cpu >= 0) { | ||
| 141 | close(FD(evsel, cpu, 0)); | ||
| 142 | FD(evsel, cpu, 0) = -1; | ||
| 143 | } | ||
| 144 | return -1; | ||
| 145 | } | ||
| 146 | |||
| 147 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, int nthreads, int *thread_map) | ||
| 148 | { | ||
| 149 | int thread; | ||
| 150 | |||
| 151 | for (thread = 0; thread < nthreads; thread++) { | ||
| 152 | FD(evsel, 0, thread) = sys_perf_event_open(&evsel->attr, | ||
| 153 | thread_map[thread], -1, -1, 0); | ||
| 154 | if (FD(evsel, 0, thread) < 0) | ||
| 155 | goto out_close; | ||
| 156 | } | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | |||
| 160 | out_close: | ||
| 161 | while (--thread >= 0) { | ||
| 162 | close(FD(evsel, 0, thread)); | ||
| 163 | FD(evsel, 0, thread) = -1; | ||
| 164 | } | ||
| 165 | return -1; | ||
| 166 | } | ||
| 167 | |||
| 168 | int perf_evsel__open(struct perf_evsel *evsel, int ncpus, int nthreads, | ||
| 169 | int *cpu_map, int *thread_map) | ||
| 170 | { | ||
| 171 | if (nthreads < 0) | ||
| 172 | return perf_evsel__open_per_cpu(evsel, ncpus, cpu_map); | ||
| 173 | |||
| 174 | return perf_evsel__open_per_thread(evsel, nthreads, thread_map); | ||
| 175 | } | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 8b48ef1e672..a62fb55cffa 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -42,6 +42,11 @@ int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); | |||
| 42 | void perf_evsel__free_fd(struct perf_evsel *evsel); | 42 | void perf_evsel__free_fd(struct perf_evsel *evsel); |
| 43 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | 43 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); |
| 44 | 44 | ||
| 45 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, int ncpus, int *cpu_map); | ||
| 46 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, int nthreads, int *thread_map); | ||
| 47 | int perf_evsel__open(struct perf_evsel *evsel, int ncpus, int nthreads, | ||
| 48 | int *cpu_map, int *thread_map); | ||
| 49 | |||
| 45 | #define perf_evsel__match(evsel, t, c) \ | 50 | #define perf_evsel__match(evsel, t, c) \ |
| 46 | (evsel->attr.type == PERF_TYPE_##t && \ | 51 | (evsel->attr.type == PERF_TYPE_##t && \ |
| 47 | evsel->attr.config == PERF_COUNT_##c) | 52 | evsel->attr.config == PERF_COUNT_##c) |
