Merge tag 'microblaze-v5.6-rc1' of git://git.monstr.eu/linux-2.6-microblaze
[linux-2.6-microblaze.git] / tools / perf / util / evlist.c
index fdce590..1548237 100644 (file)
@@ -18,6 +18,7 @@
 #include "debug.h"
 #include "units.h"
 #include <internal/lib.h> // page_size
+#include "affinity.h"
 #include "../perf.h"
 #include "asm/bug.h"
 #include "bpf-event.h"
@@ -342,14 +343,63 @@ static int perf_evlist__nr_threads(struct evlist *evlist,
                return perf_thread_map__nr(evlist->core.threads);
 }
 
+void evlist__cpu_iter_start(struct evlist *evlist)
+{
+       struct evsel *pos;
+
+       /*
+        * Reset the per evsel cpu_iter. This is needed because
+        * each evsel's cpumap may have a different index space,
+        * and some operations need the index to modify
+        * the FD xyarray (e.g. open, close)
+        */
+       evlist__for_each_entry(evlist, pos)
+               pos->cpu_iter = 0;
+}
+
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu)
+{
+       if (ev->cpu_iter >= ev->core.cpus->nr)
+               return true;
+       if (cpu >= 0 && ev->core.cpus->map[ev->cpu_iter] != cpu)
+               return true;
+       return false;
+}
+
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
+{
+       if (!evsel__cpu_iter_skip_no_inc(ev, cpu)) {
+               ev->cpu_iter++;
+               return false;
+       }
+       return true;
+}
+
 void evlist__disable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__disable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
-               if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+               if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__disable(pos);
+               pos->disabled = true;
        }
 
        evlist->enabled = false;
@@ -358,11 +408,28 @@ void evlist__disable(struct evlist *evlist)
 void evlist__enable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__enable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
                if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__enable(pos);
+               pos->disabled = false;
        }
 
        evlist->enabled = true;
@@ -1137,9 +1204,35 @@ void perf_evlist__set_selected(struct evlist *evlist,
 void evlist__close(struct evlist *evlist)
 {
        struct evsel *evsel;
+       struct affinity affinity;
+       int cpu, i;
 
-       evlist__for_each_entry_reverse(evlist, evsel)
-               evsel__close(evsel);
+       /*
+        * With perf record core.cpus is usually NULL.
+        * Use the old method to handle this for now.
+        */
+       if (!evlist->core.cpus) {
+               evlist__for_each_entry_reverse(evlist, evsel)
+                       evsel__close(evsel);
+               return;
+       }
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry_reverse(evlist, evsel) {
+                       if (evsel__cpu_iter_skip(evsel, cpu))
+                           continue;
+                       perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
+       evlist__for_each_entry_reverse(evlist, evsel) {
+               perf_evsel__free_fd(&evsel->core);
+               perf_evsel__free_id(&evsel->core);
+       }
 }
 
 static int perf_evlist__create_syswide_maps(struct evlist *evlist)
@@ -1577,7 +1670,8 @@ void perf_evlist__force_leader(struct evlist *evlist)
 }
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
-                                                struct evsel *evsel)
+                                                struct evsel *evsel,
+                                               bool close)
 {
        struct evsel *c2, *leader;
        bool is_open = true;
@@ -1594,10 +1688,15 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
                if (c2 == evsel)
                        is_open = false;
                if (c2->leader == leader) {
-                       if (is_open)
+                       if (is_open && close)
                                perf_evsel__close(&c2->core);
                        c2->leader = c2;
                        c2->core.nr_members = 0;
+                       /*
+                        * Set this for all former members of the group
+                        * to indicate they get reopened.
+                        */
+                       c2->reset_group = true;
                }
        }
        return leader;