diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-12 14:03:24 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-22 16:56:29 -0500 |
commit | 70082dd92c4b288bd723a77897e2b555f0e63113 (patch) | |
tree | 907a2d78fcaabc28cd4d034901e0eac800d1ed17 /tools/perf/util | |
parent | dd7927f4f8ee75b032ff15aeef4bda49719a443a (diff) |
perf evsel: Introduce mmap support
Out of the code in 'perf top'. Record is next in line.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/evlist.c | 8 | ||||
-rw-r--r-- | tools/perf/util/evlist.h | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 71 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 8 |
4 files changed, 88 insertions, 0 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 2abf949259d..6d4129214ee 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -60,3 +60,11 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist, int ncpus, int nthread | |||
60 | evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); | 60 | evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); |
61 | return evlist->pollfd != NULL ? 0 : -ENOMEM; | 61 | return evlist->pollfd != NULL ? 0 : -ENOMEM; |
62 | } | 62 | } |
63 | |||
64 | void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) | ||
65 | { | ||
66 | fcntl(fd, F_SETFL, O_NONBLOCK); | ||
67 | evlist->pollfd[evlist->nr_fds].fd = fd; | ||
68 | evlist->pollfd[evlist->nr_fds].events = POLLIN; | ||
69 | evlist->nr_fds++; | ||
70 | } | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a7d7e122e3c..16bbfcba8ca 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -21,5 +21,6 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); | |||
21 | int perf_evlist__add_default(struct perf_evlist *evlist); | 21 | int perf_evlist__add_default(struct perf_evlist *evlist); |
22 | 22 | ||
23 | int perf_evlist__alloc_pollfd(struct perf_evlist *evlist, int ncpus, int nthreads); | 23 | int perf_evlist__alloc_pollfd(struct perf_evlist *evlist, int ncpus, int nthreads); |
24 | void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); | ||
24 | 25 | ||
25 | #endif /* __PERF_EVLIST_H */ | 26 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 82a00536892..f5006958f8d 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 | } | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1594696bd12..c8fbef29943 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -29,19 +29,23 @@ struct perf_evsel { | |||
29 | struct perf_event_attr attr; | 29 | struct perf_event_attr attr; |
30 | char *filter; | 30 | char *filter; |
31 | struct xyarray *fd; | 31 | struct xyarray *fd; |
32 | struct xyarray *mmap; | ||
32 | struct perf_counts *counts; | 33 | struct perf_counts *counts; |
34 | size_t mmap_len; | ||
33 | int idx; | 35 | int idx; |
34 | void *priv; | 36 | void *priv; |
35 | }; | 37 | }; |
36 | 38 | ||
37 | struct cpu_map; | 39 | struct cpu_map; |
38 | struct thread_map; | 40 | struct thread_map; |
41 | struct perf_evlist; | ||
39 | 42 | ||
40 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); | 43 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); |
41 | void perf_evsel__delete(struct perf_evsel *evsel); | 44 | void perf_evsel__delete(struct perf_evsel *evsel); |
42 | 45 | ||
43 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | 46 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); |
44 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); | 47 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); |
48 | int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthreads); | ||
45 | void perf_evsel__free_fd(struct perf_evsel *evsel); | 49 | void perf_evsel__free_fd(struct perf_evsel *evsel); |
46 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | 50 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); |
47 | 51 | ||
@@ -51,6 +55,10 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel, | |||
51 | struct thread_map *threads, bool group, bool inherit); | 55 | struct thread_map *threads, bool group, bool inherit); |
52 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 56 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
53 | struct thread_map *threads, bool group, bool inherit); | 57 | struct thread_map *threads, bool group, bool inherit); |
58 | int perf_evsel__mmap(struct perf_evsel *evsel, struct cpu_map *cpus, | ||
59 | struct thread_map *threads, int pages, | ||
60 | struct perf_evlist *evlist); | ||
61 | void perf_evsel__munmap(struct perf_evsel *evsel, int ncpus, int nthreads); | ||
54 | 62 | ||
55 | #define perf_evsel__match(evsel, t, c) \ | 63 | #define perf_evsel__match(evsel, t, c) \ |
56 | (evsel->attr.type == PERF_TYPE_##t && \ | 64 | (evsel->attr.type == PERF_TYPE_##t && \ |