diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2014-07-31 02:00:51 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-08-13 18:21:18 -0400 |
commit | bf8e8f4b832972c76d64ab2e2837a48397144887 (patch) | |
tree | 55b1b99106fe3bbb4362ac1ec80666b3ab2fbb57 /tools/perf | |
parent | f247fb8191aa7f10d3f6c987e8ef0853ae789a02 (diff) |
perf evlist: Add 'system_wide' option
Add an option to cause a selected event to be opened always without a
pid when configured by perf_evsel__config().
This is needed when using the sched_switch tracepoint to follow object
code execution.
sched_switch occurs before the task switch and so it cannot record it in
a context limited to that task. Note that also means that sched_switch
is useless when capturing data per-thread, as is the 'context-switches'
software event for the same reason.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
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/r/1406786474-9306-9-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/evlist.c | 45 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 31 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 1 |
3 files changed, 64 insertions, 13 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3b366c085021..c74d8ecc9c70 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -265,17 +265,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, | |||
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
268 | static int perf_evlist__nr_threads(struct perf_evlist *evlist, | ||
269 | struct perf_evsel *evsel) | ||
270 | { | ||
271 | if (evsel->system_wide) | ||
272 | return 1; | ||
273 | else | ||
274 | return thread_map__nr(evlist->threads); | ||
275 | } | ||
276 | |||
268 | void perf_evlist__disable(struct perf_evlist *evlist) | 277 | void perf_evlist__disable(struct perf_evlist *evlist) |
269 | { | 278 | { |
270 | int cpu, thread; | 279 | int cpu, thread; |
271 | struct perf_evsel *pos; | 280 | struct perf_evsel *pos; |
272 | int nr_cpus = cpu_map__nr(evlist->cpus); | 281 | int nr_cpus = cpu_map__nr(evlist->cpus); |
273 | int nr_threads = thread_map__nr(evlist->threads); | 282 | int nr_threads; |
274 | 283 | ||
275 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 284 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
276 | evlist__for_each(evlist, pos) { | 285 | evlist__for_each(evlist, pos) { |
277 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 286 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
278 | continue; | 287 | continue; |
288 | nr_threads = perf_evlist__nr_threads(evlist, pos); | ||
279 | for (thread = 0; thread < nr_threads; thread++) | 289 | for (thread = 0; thread < nr_threads; thread++) |
280 | ioctl(FD(pos, cpu, thread), | 290 | ioctl(FD(pos, cpu, thread), |
281 | PERF_EVENT_IOC_DISABLE, 0); | 291 | PERF_EVENT_IOC_DISABLE, 0); |
@@ -288,12 +298,13 @@ void perf_evlist__enable(struct perf_evlist *evlist) | |||
288 | int cpu, thread; | 298 | int cpu, thread; |
289 | struct perf_evsel *pos; | 299 | struct perf_evsel *pos; |
290 | int nr_cpus = cpu_map__nr(evlist->cpus); | 300 | int nr_cpus = cpu_map__nr(evlist->cpus); |
291 | int nr_threads = thread_map__nr(evlist->threads); | 301 | int nr_threads; |
292 | 302 | ||
293 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 303 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
294 | evlist__for_each(evlist, pos) { | 304 | evlist__for_each(evlist, pos) { |
295 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 305 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
296 | continue; | 306 | continue; |
307 | nr_threads = perf_evlist__nr_threads(evlist, pos); | ||
297 | for (thread = 0; thread < nr_threads; thread++) | 308 | for (thread = 0; thread < nr_threads; thread++) |
298 | ioctl(FD(pos, cpu, thread), | 309 | ioctl(FD(pos, cpu, thread), |
299 | PERF_EVENT_IOC_ENABLE, 0); | 310 | PERF_EVENT_IOC_ENABLE, 0); |
@@ -305,12 +316,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist, | |||
305 | struct perf_evsel *evsel) | 316 | struct perf_evsel *evsel) |
306 | { | 317 | { |
307 | int cpu, thread, err; | 318 | int cpu, thread, err; |
319 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
320 | int nr_threads = perf_evlist__nr_threads(evlist, evsel); | ||
308 | 321 | ||
309 | if (!evsel->fd) | 322 | if (!evsel->fd) |
310 | return 0; | 323 | return 0; |
311 | 324 | ||
312 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { | 325 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
313 | for (thread = 0; thread < evlist->threads->nr; thread++) { | 326 | for (thread = 0; thread < nr_threads; thread++) { |
314 | err = ioctl(FD(evsel, cpu, thread), | 327 | err = ioctl(FD(evsel, cpu, thread), |
315 | PERF_EVENT_IOC_DISABLE, 0); | 328 | PERF_EVENT_IOC_DISABLE, 0); |
316 | if (err) | 329 | if (err) |
@@ -324,12 +337,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist, | |||
324 | struct perf_evsel *evsel) | 337 | struct perf_evsel *evsel) |
325 | { | 338 | { |
326 | int cpu, thread, err; | 339 | int cpu, thread, err; |
340 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
341 | int nr_threads = perf_evlist__nr_threads(evlist, evsel); | ||
327 | 342 | ||
328 | if (!evsel->fd) | 343 | if (!evsel->fd) |
329 | return -EINVAL; | 344 | return -EINVAL; |
330 | 345 | ||
331 | for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { | 346 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
332 | for (thread = 0; thread < evlist->threads->nr; thread++) { | 347 | for (thread = 0; thread < nr_threads; thread++) { |
333 | err = ioctl(FD(evsel, cpu, thread), | 348 | err = ioctl(FD(evsel, cpu, thread), |
334 | PERF_EVENT_IOC_ENABLE, 0); | 349 | PERF_EVENT_IOC_ENABLE, 0); |
335 | if (err) | 350 | if (err) |
@@ -343,7 +358,16 @@ static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | |||
343 | { | 358 | { |
344 | int nr_cpus = cpu_map__nr(evlist->cpus); | 359 | int nr_cpus = cpu_map__nr(evlist->cpus); |
345 | int nr_threads = thread_map__nr(evlist->threads); | 360 | int nr_threads = thread_map__nr(evlist->threads); |
346 | int nfds = nr_cpus * nr_threads * evlist->nr_entries; | 361 | int nfds = 0; |
362 | struct perf_evsel *evsel; | ||
363 | |||
364 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
365 | if (evsel->system_wide) | ||
366 | nfds += nr_cpus; | ||
367 | else | ||
368 | nfds += nr_cpus * nr_threads; | ||
369 | } | ||
370 | |||
347 | evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); | 371 | evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); |
348 | return evlist->pollfd != NULL ? 0 : -ENOMEM; | 372 | return evlist->pollfd != NULL ? 0 : -ENOMEM; |
349 | } | 373 | } |
@@ -636,7 +660,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
636 | struct perf_evsel *evsel; | 660 | struct perf_evsel *evsel; |
637 | 661 | ||
638 | evlist__for_each(evlist, evsel) { | 662 | evlist__for_each(evlist, evsel) { |
639 | int fd = FD(evsel, cpu, thread); | 663 | int fd; |
664 | |||
665 | if (evsel->system_wide && thread) | ||
666 | continue; | ||
667 | |||
668 | fd = FD(evsel, cpu, thread); | ||
640 | 669 | ||
641 | if (*output == -1) { | 670 | if (*output == -1) { |
642 | *output = fd; | 671 | *output = fd; |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0c8919decac8..66de9a708163 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -695,6 +695,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
695 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 695 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
696 | { | 696 | { |
697 | int cpu, thread; | 697 | int cpu, thread; |
698 | |||
699 | if (evsel->system_wide) | ||
700 | nthreads = 1; | ||
701 | |||
698 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); | 702 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); |
699 | 703 | ||
700 | if (evsel->fd) { | 704 | if (evsel->fd) { |
@@ -713,6 +717,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea | |||
713 | { | 717 | { |
714 | int cpu, thread; | 718 | int cpu, thread; |
715 | 719 | ||
720 | if (evsel->system_wide) | ||
721 | nthreads = 1; | ||
722 | |||
716 | for (cpu = 0; cpu < ncpus; cpu++) { | 723 | for (cpu = 0; cpu < ncpus; cpu++) { |
717 | for (thread = 0; thread < nthreads; thread++) { | 724 | for (thread = 0; thread < nthreads; thread++) { |
718 | int fd = FD(evsel, cpu, thread), | 725 | int fd = FD(evsel, cpu, thread), |
@@ -743,6 +750,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
743 | 750 | ||
744 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) | 751 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) |
745 | { | 752 | { |
753 | if (evsel->system_wide) | ||
754 | nthreads = 1; | ||
755 | |||
746 | evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); | 756 | evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); |
747 | if (evsel->sample_id == NULL) | 757 | if (evsel->sample_id == NULL) |
748 | return -ENOMEM; | 758 | return -ENOMEM; |
@@ -787,6 +797,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
787 | { | 797 | { |
788 | int cpu, thread; | 798 | int cpu, thread; |
789 | 799 | ||
800 | if (evsel->system_wide) | ||
801 | nthreads = 1; | ||
802 | |||
790 | for (cpu = 0; cpu < ncpus; cpu++) | 803 | for (cpu = 0; cpu < ncpus; cpu++) |
791 | for (thread = 0; thread < nthreads; ++thread) { | 804 | for (thread = 0; thread < nthreads; ++thread) { |
792 | close(FD(evsel, cpu, thread)); | 805 | close(FD(evsel, cpu, thread)); |
@@ -875,6 +888,9 @@ int __perf_evsel__read(struct perf_evsel *evsel, | |||
875 | int cpu, thread; | 888 | int cpu, thread; |
876 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; | 889 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; |
877 | 890 | ||
891 | if (evsel->system_wide) | ||
892 | nthreads = 1; | ||
893 | |||
878 | aggr->val = aggr->ena = aggr->run = 0; | 894 | aggr->val = aggr->ena = aggr->run = 0; |
879 | 895 | ||
880 | for (cpu = 0; cpu < ncpus; cpu++) { | 896 | for (cpu = 0; cpu < ncpus; cpu++) { |
@@ -997,13 +1013,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) | |||
997 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 1013 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
998 | struct thread_map *threads) | 1014 | struct thread_map *threads) |
999 | { | 1015 | { |
1000 | int cpu, thread; | 1016 | int cpu, thread, nthreads; |
1001 | unsigned long flags = PERF_FLAG_FD_CLOEXEC; | 1017 | unsigned long flags = PERF_FLAG_FD_CLOEXEC; |
1002 | int pid = -1, err; | 1018 | int pid = -1, err; |
1003 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; | 1019 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; |
1004 | 1020 | ||
1021 | if (evsel->system_wide) | ||
1022 | nthreads = 1; | ||
1023 | else | ||
1024 | nthreads = threads->nr; | ||
1025 | |||
1005 | if (evsel->fd == NULL && | 1026 | if (evsel->fd == NULL && |
1006 | perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) | 1027 | perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0) |
1007 | return -ENOMEM; | 1028 | return -ENOMEM; |
1008 | 1029 | ||
1009 | if (evsel->cgrp) { | 1030 | if (evsel->cgrp) { |
@@ -1027,10 +1048,10 @@ retry_sample_id: | |||
1027 | 1048 | ||
1028 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 1049 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
1029 | 1050 | ||
1030 | for (thread = 0; thread < threads->nr; thread++) { | 1051 | for (thread = 0; thread < nthreads; thread++) { |
1031 | int group_fd; | 1052 | int group_fd; |
1032 | 1053 | ||
1033 | if (!evsel->cgrp) | 1054 | if (!evsel->cgrp && !evsel->system_wide) |
1034 | pid = threads->map[thread]; | 1055 | pid = threads->map[thread]; |
1035 | 1056 | ||
1036 | group_fd = get_group_fd(evsel, cpu, thread); | 1057 | group_fd = get_group_fd(evsel, cpu, thread); |
@@ -1103,7 +1124,7 @@ out_close: | |||
1103 | close(FD(evsel, cpu, thread)); | 1124 | close(FD(evsel, cpu, thread)); |
1104 | FD(evsel, cpu, thread) = -1; | 1125 | FD(evsel, cpu, thread) = -1; |
1105 | } | 1126 | } |
1106 | thread = threads->nr; | 1127 | thread = nthreads; |
1107 | } while (--cpu >= 0); | 1128 | } while (--cpu >= 0); |
1108 | return err; | 1129 | return err; |
1109 | } | 1130 | } |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index d7f93ce0ebc1..dbb2a0d20907 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -85,6 +85,7 @@ struct perf_evsel { | |||
85 | bool needs_swap; | 85 | bool needs_swap; |
86 | bool no_aux_samples; | 86 | bool no_aux_samples; |
87 | bool immediate; | 87 | bool immediate; |
88 | bool system_wide; | ||
88 | /* parse modifier helper */ | 89 | /* parse modifier helper */ |
89 | int exclude_GH; | 90 | int exclude_GH; |
90 | int nr_members; | 91 | int nr_members; |