diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-12 17:03:24 -0200 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-22 19:56:29 -0200 |
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 2abf949259d0..6d4129214ee8 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 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); return evlist->pollfd != NULL ? 0 : -ENOMEM; } + +void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) +{ + fcntl(fd, F_SETFL, O_NONBLOCK); + evlist->pollfd[evlist->nr_fds].fd = fd; + evlist->pollfd[evlist->nr_fds].events = POLLIN; + evlist->nr_fds++; +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a7d7e122e3c6..16bbfcba8ca8 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); int perf_evlist__add_default(struct perf_evlist *evlist); int perf_evlist__alloc_pollfd(struct perf_evlist *evlist, int ncpus, int nthreads); +void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); #endif /* __PERF_EVLIST_H */ 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 @@ #include "evsel.h" +#include "evlist.h" #include "../perf.h" #include "util.h" #include "cpumap.h" #include "thread.h" +#include <unistd.h> +#include <sys/mman.h> + #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 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) } } +void perf_evsel__munmap(struct perf_evsel *evsel, int ncpus, int nthreads) +{ + struct perf_mmap *mm; + int cpu, thread; + + for (cpu = 0; cpu < ncpus; cpu++) + for (thread = 0; thread < nthreads; ++thread) { + mm = xyarray__entry(evsel->mmap, cpu, thread); + if (mm->base != NULL) { + munmap(mm->base, evsel->mmap_len); + mm->base = NULL; + } + } +} + +int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthreads) +{ + evsel->mmap = xyarray__new(ncpus, nthreads, sizeof(struct perf_mmap)); + return evsel->mmap != NULL ? 0 : -ENOMEM; +} + void perf_evsel__delete(struct perf_evsel *evsel) { assert(list_empty(&evsel->node)); xyarray__delete(evsel->fd); + xyarray__delete(evsel->mmap); free(evsel); } @@ -208,3 +234,48 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel, { return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); } + +int perf_evsel__mmap(struct perf_evsel *evsel, struct cpu_map *cpus, + struct thread_map *threads, int pages, + struct perf_evlist *evlist) +{ + unsigned int page_size = sysconf(_SC_PAGE_SIZE); + int mask = pages * page_size - 1, cpu; + struct perf_mmap *mm; + int thread; + + if (evsel->mmap == NULL && + perf_evsel__alloc_mmap(evsel, cpus->nr, threads->nr) < 0) + return -ENOMEM; + + evsel->mmap_len = (pages + 1) * page_size; + + for (cpu = 0; cpu < cpus->nr; cpu++) { + for (thread = 0; thread < threads->nr; thread++) { + mm = xyarray__entry(evsel->mmap, cpu, thread); + mm->prev = 0; + mm->mask = mask; + mm->base = mmap(NULL, evsel->mmap_len, PROT_READ, + MAP_SHARED, FD(evsel, cpu, thread), 0); + if (mm->base == MAP_FAILED) + goto out_unmap; + + if (evlist != NULL) + perf_evlist__add_pollfd(evlist, FD(evsel, cpu, thread)); + } + } + + return 0; + +out_unmap: + do { + while (--thread >= 0) { + mm = xyarray__entry(evsel->mmap, cpu, thread); + munmap(mm->base, evsel->mmap_len); + mm->base = NULL; + } + thread = threads->nr; + } while (--cpu >= 0); + + return -1; +} diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1594696bd127..c8fbef299436 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -29,19 +29,23 @@ struct perf_evsel { struct perf_event_attr attr; char *filter; struct xyarray *fd; + struct xyarray *mmap; struct perf_counts *counts; + size_t mmap_len; int idx; void *priv; }; struct cpu_map; struct thread_map; +struct perf_evlist; struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); void perf_evsel__delete(struct perf_evsel *evsel); int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); +int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__free_fd(struct perf_evsel *evsel); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); @@ -51,6 +55,10 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads, bool group, bool inherit); int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, struct thread_map *threads, bool group, bool inherit); +int perf_evsel__mmap(struct perf_evsel *evsel, struct cpu_map *cpus, + struct thread_map *threads, int pages, + struct perf_evlist *evlist); +void perf_evsel__munmap(struct perf_evsel *evsel, int ncpus, int nthreads); #define perf_evsel__match(evsel, t, c) \ (evsel->attr.type == PERF_TYPE_##t && \ |