aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2014-07-31 02:00:51 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-08-13 18:21:18 -0400
commitbf8e8f4b832972c76d64ab2e2837a48397144887 (patch)
tree55b1b99106fe3bbb4362ac1ec80666b3ab2fbb57 /tools/perf
parentf247fb8191aa7f10d3f6c987e8ef0853ae789a02 (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.c45
-rw-r--r--tools/perf/util/evsel.c31
-rw-r--r--tools/perf/util/evsel.h1
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
268static 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
268void perf_evlist__disable(struct perf_evlist *evlist) 277void 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)
695int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 695int 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
744int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 751int 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)
997static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1013static 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;