aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-10-25 08:42:19 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-10-26 08:25:02 -0400
commit727ab04edbc4767711a7aeff5e00249b267ed4c1 (patch)
tree9cebc2c392b9b3bcaf68f0a50144273ef52a04f1 /tools/perf/util
parentc752d04066a36ae30b29795f3fa3f536292c1f8c (diff)
perf evlist: Fix grouping of multiple events
The __perf_evsel__open routing was grouping just the threads for that specific events per cpu when we want to group all threads in all events to the first fd opened on that cpu. So pass the xyarray with the first event, where the other events will be able to get that first per cpu fd. At some point top and record will switch to using perf_evlist__open that takes care of this detail and probably will also handle the fallback from hw to soft counters, etc. Reported-by: Deng-Cheng Zhu <dczhu@mips.com> Tested-by: Deng-Cheng Zhu <dczhu@mips.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-ebm34rh098i9y9v4cytfdp0x@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/evlist.c30
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c43
-rw-r--r--tools/perf/util/evsel.h10
-rw-r--r--tools/perf/util/python.c31
5 files changed, 100 insertions, 16 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2f6bc89027da..fbb4b4ab9cc6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -539,3 +539,33 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
539{ 539{
540 evlist->selected = evsel; 540 evlist->selected = evsel;
541} 541}
542
543int perf_evlist__open(struct perf_evlist *evlist, bool group)
544{
545 struct perf_evsel *evsel, *first;
546 int err, ncpus, nthreads;
547
548 first = list_entry(evlist->entries.next, struct perf_evsel, node);
549
550 list_for_each_entry(evsel, &evlist->entries, node) {
551 struct xyarray *group_fd = NULL;
552
553 if (group && evsel != first)
554 group_fd = first->fd;
555
556 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
557 group, group_fd);
558 if (err < 0)
559 goto out_err;
560 }
561
562 return 0;
563out_err:
564 ncpus = evlist->cpus ? evlist->cpus->nr : 1;
565 nthreads = evlist->threads ? evlist->threads->nr : 1;
566
567 list_for_each_entry_reverse(evsel, &evlist->entries, node)
568 perf_evsel__close(evsel, ncpus, nthreads);
569
570 return err;
571}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 6be71fc57794..1779ffef7828 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -50,6 +50,8 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
50 50
51union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 51union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
52 52
53int perf_evlist__open(struct perf_evlist *evlist, bool group);
54
53int perf_evlist__alloc_mmap(struct perf_evlist *evlist); 55int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
54int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); 56int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
55void perf_evlist__munmap(struct perf_evlist *evlist); 57void perf_evlist__munmap(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b46f6e4bff3c..e42626422587 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -16,6 +16,7 @@
16#include "thread_map.h" 16#include "thread_map.h"
17 17
18#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 18#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
19#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
19 20
20int __perf_evsel__sample_size(u64 sample_type) 21int __perf_evsel__sample_size(u64 sample_type)
21{ 22{
@@ -204,15 +205,16 @@ int __perf_evsel__read(struct perf_evsel *evsel,
204} 205}
205 206
206static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 207static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
207 struct thread_map *threads, bool group) 208 struct thread_map *threads, bool group,
209 struct xyarray *group_fds)
208{ 210{
209 int cpu, thread; 211 int cpu, thread;
210 unsigned long flags = 0; 212 unsigned long flags = 0;
211 int pid = -1; 213 int pid = -1, err;
212 214
213 if (evsel->fd == NULL && 215 if (evsel->fd == NULL &&
214 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 216 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
215 return -1; 217 return -ENOMEM;
216 218
217 if (evsel->cgrp) { 219 if (evsel->cgrp) {
218 flags = PERF_FLAG_PID_CGROUP; 220 flags = PERF_FLAG_PID_CGROUP;
@@ -220,7 +222,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
220 } 222 }
221 223
222 for (cpu = 0; cpu < cpus->nr; cpu++) { 224 for (cpu = 0; cpu < cpus->nr; cpu++) {
223 int group_fd = -1; 225 int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
224 226
225 for (thread = 0; thread < threads->nr; thread++) { 227 for (thread = 0; thread < threads->nr; thread++) {
226 228
@@ -231,8 +233,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
231 pid, 233 pid,
232 cpus->map[cpu], 234 cpus->map[cpu],
233 group_fd, flags); 235 group_fd, flags);
234 if (FD(evsel, cpu, thread) < 0) 236 if (FD(evsel, cpu, thread) < 0) {
237 err = -errno;
235 goto out_close; 238 goto out_close;
239 }
236 240
237 if (group && group_fd == -1) 241 if (group && group_fd == -1)
238 group_fd = FD(evsel, cpu, thread); 242 group_fd = FD(evsel, cpu, thread);
@@ -249,7 +253,17 @@ out_close:
249 } 253 }
250 thread = threads->nr; 254 thread = threads->nr;
251 } while (--cpu >= 0); 255 } while (--cpu >= 0);
252 return -1; 256 return err;
257}
258
259void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
260{
261 if (evsel->fd == NULL)
262 return;
263
264 perf_evsel__close_fd(evsel, ncpus, nthreads);
265 perf_evsel__free_fd(evsel);
266 evsel->fd = NULL;
253} 267}
254 268
255static struct { 269static struct {
@@ -269,7 +283,8 @@ static struct {
269}; 283};
270 284
271int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 285int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
272 struct thread_map *threads, bool group) 286 struct thread_map *threads, bool group,
287 struct xyarray *group_fd)
273{ 288{
274 if (cpus == NULL) { 289 if (cpus == NULL) {
275 /* Work around old compiler warnings about strict aliasing */ 290 /* Work around old compiler warnings about strict aliasing */
@@ -279,19 +294,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
279 if (threads == NULL) 294 if (threads == NULL)
280 threads = &empty_thread_map.map; 295 threads = &empty_thread_map.map;
281 296
282 return __perf_evsel__open(evsel, cpus, threads, group); 297 return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
283} 298}
284 299
285int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 300int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
286 struct cpu_map *cpus, bool group) 301 struct cpu_map *cpus, bool group,
302 struct xyarray *group_fd)
287{ 303{
288 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group); 304 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
305 group_fd);
289} 306}
290 307
291int perf_evsel__open_per_thread(struct perf_evsel *evsel, 308int perf_evsel__open_per_thread(struct perf_evsel *evsel,
292 struct thread_map *threads, bool group) 309 struct thread_map *threads, bool group,
310 struct xyarray *group_fd)
293{ 311{
294 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group); 312 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
313 group_fd);
295} 314}
296 315
297static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 316static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e9a31554e265..b1d15e6f7ae3 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -82,11 +82,15 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
82void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 82void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
83 83
84int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 84int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
85 struct cpu_map *cpus, bool group); 85 struct cpu_map *cpus, bool group,
86 struct xyarray *group_fds);
86int perf_evsel__open_per_thread(struct perf_evsel *evsel, 87int perf_evsel__open_per_thread(struct perf_evsel *evsel,
87 struct thread_map *threads, bool group); 88 struct thread_map *threads, bool group,
89 struct xyarray *group_fds);
88int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 90int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
89 struct thread_map *threads, bool group); 91 struct thread_map *threads, bool group,
92 struct xyarray *group_fds);
93void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
90 94
91#define perf_evsel__match(evsel, t, c) \ 95#define perf_evsel__match(evsel, t, c) \
92 (evsel->attr.type == PERF_TYPE_##t && \ 96 (evsel->attr.type == PERF_TYPE_##t && \
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 7624324efad4..9dd47a4f2596 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -623,7 +623,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
623 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 623 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
624 624
625 evsel->attr.inherit = inherit; 625 evsel->attr.inherit = inherit;
626 if (perf_evsel__open(evsel, cpus, threads, group) < 0) { 626 /*
627 * This will group just the fds for this single evsel, to group
628 * multiple events, use evlist.open().
629 */
630 if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) {
627 PyErr_SetFromErrno(PyExc_OSError); 631 PyErr_SetFromErrno(PyExc_OSError);
628 return NULL; 632 return NULL;
629 } 633 }
@@ -814,6 +818,25 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
814 return Py_None; 818 return Py_None;
815} 819}
816 820
821static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
822 PyObject *args, PyObject *kwargs)
823{
824 struct perf_evlist *evlist = &pevlist->evlist;
825 int group = 0;
826 static char *kwlist[] = { "group", NULL };
827
828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
829 return NULL;
830
831 if (perf_evlist__open(evlist, group) < 0) {
832 PyErr_SetFromErrno(PyExc_OSError);
833 return NULL;
834 }
835
836 Py_INCREF(Py_None);
837 return Py_None;
838}
839
817static PyMethodDef pyrf_evlist__methods[] = { 840static PyMethodDef pyrf_evlist__methods[] = {
818 { 841 {
819 .ml_name = "mmap", 842 .ml_name = "mmap",
@@ -822,6 +845,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
822 .ml_doc = PyDoc_STR("mmap the file descriptor table.") 845 .ml_doc = PyDoc_STR("mmap the file descriptor table.")
823 }, 846 },
824 { 847 {
848 .ml_name = "open",
849 .ml_meth = (PyCFunction)pyrf_evlist__open,
850 .ml_flags = METH_VARARGS | METH_KEYWORDS,
851 .ml_doc = PyDoc_STR("open the file descriptors.")
852 },
853 {
825 .ml_name = "poll", 854 .ml_name = "poll",
826 .ml_meth = (PyCFunction)pyrf_evlist__poll, 855 .ml_meth = (PyCFunction)pyrf_evlist__poll,
827 .ml_flags = METH_VARARGS | METH_KEYWORDS, 856 .ml_flags = METH_VARARGS | METH_KEYWORDS,