perf: Set filters before mmaping events
authorFrederic Weisbecker <fweisbec@gmail.com>
Sat, 26 Feb 2011 03:51:54 +0000 (04:51 +0100)
committerFrederic Weisbecker <fweisbec@gmail.com>
Wed, 2 Mar 2011 15:05:51 +0000 (16:05 +0100)
We currently set the filters after we mmap the events, this is a
race that let undesired events record themselves in the buffer before
we had the time to set the filters.

So set the filters before they can be recorded. That also librarizes
the filters setting so that filtering can be done more easily
from other tools than perf record later.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
tools/perf/builtin-record.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h

index db4cd1e7b51a69a009d05c1bb531f2da9610275b..d40a81e8cc569ffc6a6ac0557f3d5dfcae7c79b4 100644 (file)
@@ -180,12 +180,10 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
 
 static void create_counter(struct perf_evsel *evsel, int cpu)
 {
-       char *filter = evsel->filter;
        struct perf_event_attr *attr = &evsel->attr;
        struct perf_header_attr *h_attr;
        struct perf_sample_id *sid;
        int thread_index;
-       int ret;
 
        for (thread_index = 0; thread_index < evsel_list->threads->nr; thread_index++) {
                h_attr = get_header_attr(attr, evsel->idx);
@@ -204,16 +202,6 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
                        pr_warning("Not enough memory to add id\n");
                        exit(-1);
                }
-
-               if (filter != NULL) {
-                       ret = ioctl(FD(evsel, cpu, thread_index),
-                                   PERF_EVENT_IOC_SET_FILTER, filter);
-                       if (ret) {
-                               error("failed to set filter with %d (%s)\n", errno,
-                                               strerror(errno));
-                               exit(-1);
-                       }
-               }
        }
 
        if (!sample_type)
@@ -367,6 +355,12 @@ try_again:
                }
        }
 
+       if (perf_evlist__set_filters(evlist)) {
+               error("failed to set filter with %d (%s)\n", errno,
+                       strerror(errno));
+               exit(-1);
+       }
+
        if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
                die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 
index 95b21fece2cefe1ac7c513a7351f37dbb0abd4be..030ae7f05e03e14914de465dc3e451b74dfd8bd3 100644 (file)
@@ -348,3 +348,31 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist)
        evlist->cpus    = NULL;
        evlist->threads = NULL;
 }
+
+int perf_evlist__set_filters(struct perf_evlist *evlist)
+{
+       const struct thread_map *threads = evlist->threads;
+       const struct cpu_map *cpus = evlist->cpus;
+       struct perf_evsel *evsel;
+       char *filter;
+       int thread;
+       int cpu;
+       int err;
+       int fd;
+
+       list_for_each_entry(evsel, &evlist->entries, node) {
+               filter = evsel->filter;
+               if (!filter)
+                       continue;
+               for (cpu = 0; cpu < cpus->nr; cpu++) {
+                       for (thread = 0; thread < threads->nr; thread++) {
+                               fd = FD(evsel, cpu, thread);
+                               err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
+                               if (err)
+                                       return err;
+                       }
+               }
+       }
+
+       return 0;
+}
index c9884056097c1bf617c15772a1e3f76266330727..b75805aeb7e4dc3dbd5d6eec24bd1d5eed26871f 100644 (file)
@@ -60,5 +60,6 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
 int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
                             pid_t target_tid, const char *cpu_list);
 void perf_evlist__delete_maps(struct perf_evlist *evlist);
+int perf_evlist__set_filters(struct perf_evlist *evlist);
 
 #endif /* __PERF_EVLIST_H */