diff options
Diffstat (limited to 'tools/perf/util/evsel.c')
-rw-r--r-- | tools/perf/util/evsel.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 82a00536892a..f5006958f8da 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -1,9 +1,13 @@ | |||
1 | #include "evsel.h" | 1 | #include "evsel.h" |
2 | #include "evlist.h" | ||
2 | #include "../perf.h" | 3 | #include "../perf.h" |
3 | #include "util.h" | 4 | #include "util.h" |
4 | #include "cpumap.h" | 5 | #include "cpumap.h" |
5 | #include "thread.h" | 6 | #include "thread.h" |
6 | 7 | ||
8 | #include <unistd.h> | ||
9 | #include <sys/mman.h> | ||
10 | |||
7 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 11 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
8 | 12 | ||
9 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) | 13 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) |
@@ -49,10 +53,32 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
49 | } | 53 | } |
50 | } | 54 | } |
51 | 55 | ||
56 | void perf_evsel__munmap(struct perf_evsel *evsel, int ncpus, int nthreads) | ||
57 | { | ||
58 | struct perf_mmap *mm; | ||
59 | int cpu, thread; | ||
60 | |||
61 | for (cpu = 0; cpu < ncpus; cpu++) | ||
62 | for (thread = 0; thread < nthreads; ++thread) { | ||
63 | mm = xyarray__entry(evsel->mmap, cpu, thread); | ||
64 | if (mm->base != NULL) { | ||
65 | munmap(mm->base, evsel->mmap_len); | ||
66 | mm->base = NULL; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthreads) | ||
72 | { | ||
73 | evsel->mmap = xyarray__new(ncpus, nthreads, sizeof(struct perf_mmap)); | ||
74 | return evsel->mmap != NULL ? 0 : -ENOMEM; | ||
75 | } | ||
76 | |||
52 | void perf_evsel__delete(struct perf_evsel *evsel) | 77 | void perf_evsel__delete(struct perf_evsel *evsel) |
53 | { | 78 | { |
54 | assert(list_empty(&evsel->node)); | 79 | assert(list_empty(&evsel->node)); |
55 | xyarray__delete(evsel->fd); | 80 | xyarray__delete(evsel->fd); |
81 | xyarray__delete(evsel->mmap); | ||
56 | free(evsel); | 82 | free(evsel); |
57 | } | 83 | } |
58 | 84 | ||
@@ -208,3 +234,48 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel, | |||
208 | { | 234 | { |
209 | return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); | 235 | return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); |
210 | } | 236 | } |
237 | |||
238 | int perf_evsel__mmap(struct perf_evsel *evsel, struct cpu_map *cpus, | ||
239 | struct thread_map *threads, int pages, | ||
240 | struct perf_evlist *evlist) | ||
241 | { | ||
242 | unsigned int page_size = sysconf(_SC_PAGE_SIZE); | ||
243 | int mask = pages * page_size - 1, cpu; | ||
244 | struct perf_mmap *mm; | ||
245 | int thread; | ||
246 | |||
247 | if (evsel->mmap == NULL && | ||
248 | perf_evsel__alloc_mmap(evsel, cpus->nr, threads->nr) < 0) | ||
249 | return -ENOMEM; | ||
250 | |||
251 | evsel->mmap_len = (pages + 1) * page_size; | ||
252 | |||
253 | for (cpu = 0; cpu < cpus->nr; cpu++) { | ||
254 | for (thread = 0; thread < threads->nr; thread++) { | ||
255 | mm = xyarray__entry(evsel->mmap, cpu, thread); | ||
256 | mm->prev = 0; | ||
257 | mm->mask = mask; | ||
258 | mm->base = mmap(NULL, evsel->mmap_len, PROT_READ, | ||
259 | MAP_SHARED, FD(evsel, cpu, thread), 0); | ||
260 | if (mm->base == MAP_FAILED) | ||
261 | goto out_unmap; | ||
262 | |||
263 | if (evlist != NULL) | ||
264 | perf_evlist__add_pollfd(evlist, FD(evsel, cpu, thread)); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | return 0; | ||
269 | |||
270 | out_unmap: | ||
271 | do { | ||
272 | while (--thread >= 0) { | ||
273 | mm = xyarray__entry(evsel->mmap, cpu, thread); | ||
274 | munmap(mm->base, evsel->mmap_len); | ||
275 | mm->base = NULL; | ||
276 | } | ||
277 | thread = threads->nr; | ||
278 | } while (--cpu >= 0); | ||
279 | |||
280 | return -1; | ||
281 | } | ||