From: Kan Liang <[email protected]>

In perf_evlist__mmap, leader's fd has to be mmaped before member's fd.
So evlist__for_each must be the outermost of the loop.
Since different event's cpu list could vary, we cannot rely on the index
to get group leader's fd. In get_group_fd, the cpu id is used to get
correct fd.

Signed-off-by: Kan Liang <[email protected]>
---
 tools/perf/util/evlist.c | 104 +++++++++++++++++++++++++++--------------------
 tools/perf/util/evsel.c  |  28 +++++++++----
 2 files changed, 80 insertions(+), 52 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 16319b4..637fcf4 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -834,51 +834,48 @@ static int __perf_evlist__mmap(struct perf_evlist 
*evlist, int idx,
        return 0;
 }
 
-static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-                                      struct mmap_params *mp, int cpu,
-                                      int thread, int *output)
+static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist,
+                                      struct perf_evsel *evsel,
+                                      int idx, struct mmap_params *mp,
+                                      int cpu, int thread, int *output)
 {
-       struct perf_evsel *evsel;
+       int fd;
 
-       evlist__for_each(evlist, evsel) {
-               int fd;
+       if (evsel->system_wide && thread)
+               return 0;
 
-               if (evsel->system_wide && thread)
-                       continue;
+       fd = FD(evsel, cpu, thread);
 
-               fd = FD(evsel, cpu, thread);
+       if (*output == -1) {
+               *output = fd;
+               if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
+                       return -1;
+       } else {
+               if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
+                       return -1;
 
-               if (*output == -1) {
-                       *output = fd;
-                       if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0)
-                               return -1;
-               } else {
-                       if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
-                               return -1;
+               perf_evlist__mmap_get(evlist, idx);
+       }
 
-                       perf_evlist__mmap_get(evlist, idx);
-               }
+       /*
+        * The system_wide flag causes a selected event to be opened
+        * always without a pid.  Consequently it will never get a
+        * POLLHUP, but it is used for tracking in combination with
+        * other events, so it should not need to be polled anyway.
+        * Therefore don't add it for polling.
+        */
+       if (!evsel->system_wide &&
+           __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
+               perf_evlist__mmap_put(evlist, idx);
+               return -1;
+       }
 
-               /*
-                * The system_wide flag causes a selected event to be opened
-                * always without a pid.  Consequently it will never get a
-                * POLLHUP, but it is used for tracking in combination with
-                * other events, so it should not need to be polled anyway.
-                * Therefore don't add it for polling.
-                */
-               if (!evsel->system_wide &&
-                   __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
-                       perf_evlist__mmap_put(evlist, idx);
+       if (evsel->attr.read_format & PERF_FORMAT_ID) {
+               if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
+                                          fd) < 0)
                        return -1;
-               }
-
-               if (evsel->attr.read_format & PERF_FORMAT_ID) {
-                       if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
-                                                  fd) < 0)
-                               return -1;
-                       perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
-                                                thread);
-               }
+               perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
+                                        thread);
        }
 
        return 0;
@@ -890,23 +887,37 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist 
*evlist,
        int cpu, thread;
        int nr_cpus = cpu_map__nr(evlist->cpus);
        int nr_threads = thread_map__nr(evlist->threads);
+       int *output = malloc(nr_cpus * sizeof(int));
+       int evlist_cpu;
+       struct perf_evsel *evsel;
 
        pr_debug2("perf event ring buffer mmapped per cpu\n");
-       for (cpu = 0; cpu < nr_cpus; cpu++) {
-               int output = -1;
 
-               for (thread = 0; thread < nr_threads; thread++) {
-                       if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
-                                                       thread, &output))
+       for (cpu = 0; cpu < nr_cpus; cpu++)
+               output[cpu] = -1;
+
+       evlist__for_each(evlist, evsel) {
+               for (cpu = 0; cpu < cpu_map__nr(evsel->cpus); cpu++) {
+                       evlist_cpu = 
perf_evsel__get_cpumap_index(evsel->cpus->map[cpu], evlist->cpus);
+                       if (evlist_cpu < 0)
                                goto out_unmap;
+
+                       for (thread = 0; thread < nr_threads; thread++) {
+                               if (perf_evlist__mmap_per_evsel(evlist, evsel, 
evlist_cpu,
+                                                               mp, cpu, thread,
+                                                               
&output[evlist_cpu]))
+                                       goto out_unmap;
+                       }
                }
        }
 
+       free(output);
        return 0;
 
 out_unmap:
        for (cpu = 0; cpu < nr_cpus; cpu++)
                __perf_evlist__munmap(evlist, cpu);
+       free(output);
        return -1;
 }
 
@@ -915,14 +926,17 @@ static int perf_evlist__mmap_per_thread(struct 
perf_evlist *evlist,
 {
        int thread;
        int nr_threads = thread_map__nr(evlist->threads);
+       struct perf_evsel *evsel;
 
        pr_debug2("perf event ring buffer mmapped per thread\n");
        for (thread = 0; thread < nr_threads; thread++) {
                int output = -1;
 
-               if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
-                                               &output))
-                       goto out_unmap;
+               evlist__for_each(evlist, evsel) {
+                       if (perf_evlist__mmap_per_evsel(evlist, evsel, thread,
+                                                       mp, 0, thread, &output))
+                               goto out_unmap;
+               }
        }
 
        return 0;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e177f43..44a663c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1008,7 +1008,7 @@ int perf_evsel__get_cpumap_index(int cpu, struct cpu_map 
*evsel_cpus)
 static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
 {
        struct perf_evsel *leader = evsel->leader;
-       int fd;
+       int fd, leader_cpu;
 
        if (perf_evsel__is_group_leader(evsel))
                return -1;
@@ -1019,7 +1019,15 @@ static int get_group_fd(struct perf_evsel *evsel, int 
cpu, int thread)
         */
        BUG_ON(!leader->fd);
 
-       fd = FD(leader, cpu, thread);
+       if (cpu < 0)
+               fd = FD(leader, 0, thread);
+       else {
+               leader_cpu = perf_evsel__get_cpumap_index(cpu, leader->cpus);
+               if (leader_cpu >= 0)
+                       fd = FD(leader, leader_cpu, thread);
+               else
+                       return -1;
+       }
        BUG_ON(fd == -1);
 
        return fd;
@@ -1151,15 +1159,21 @@ static int __perf_evsel__open(struct perf_evsel *evsel, 
struct cpu_map *cpus,
        int cpu, thread, nthreads;
        unsigned long flags = PERF_FLAG_FD_CLOEXEC;
        int pid = -1, err;
+       struct cpu_map *cpumap;
        enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
 
+       if (evsel->cpus)
+               cpumap = evsel->cpus;
+       else
+               cpumap = cpus;
+
        if (evsel->system_wide)
                nthreads = 1;
        else
                nthreads = threads->nr;
 
        if (evsel->fd == NULL &&
-           perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
+           perf_evsel__alloc_fd(evsel, cpumap->nr, nthreads) < 0)
                return -ENOMEM;
 
        if (evsel->cgrp) {
@@ -1191,7 +1205,7 @@ retry_sample_id:
                fprintf(stderr, "%.60s\n", graph_dotted_line);
        }
 
-       for (cpu = 0; cpu < cpus->nr; cpu++) {
+       for (cpu = 0; cpu < cpumap->nr; cpu++) {
 
                for (thread = 0; thread < nthreads; thread++) {
                        int group_fd;
@@ -1199,14 +1213,14 @@ retry_sample_id:
                        if (!evsel->cgrp && !evsel->system_wide)
                                pid = threads->map[thread];
 
-                       group_fd = get_group_fd(evsel, cpu, thread);
+                       group_fd = get_group_fd(evsel, cpumap->map[cpu], 
thread);
 retry_open:
                        pr_debug2("sys_perf_event_open: pid %d  cpu %d  
group_fd %d  flags %#lx\n",
-                                 pid, cpus->map[cpu], group_fd, flags);
+                                 pid, cpumap->map[cpu], group_fd, flags);
 
                        FD(evsel, cpu, thread) = 
sys_perf_event_open(&evsel->attr,
                                                                     pid,
-                                                                    
cpus->map[cpu],
+                                                                    
cpumap->map[cpu],
                                                                     group_fd, 
flags);
                        if (FD(evsel, cpu, thread) < 0) {
                                err = -errno;
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to