perf evsel: Introduce mmap support
Commit-ID: 70082dd92c4b288bd723a77897e2b555f0e63113 Gitweb: http://git.kernel.org/tip/70082dd92c4b288bd723a77897e2b555f0e63113 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Wed, 12 Jan 2011 17:03:24 -0200 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Sat, 22 Jan 2011 19:56:29 -0200
perf evsel: Introduce mmap support
Out of the code in 'perf top'. Record is next in line.
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Tom Zanussi <[email protected]>
LKML-Reference: <new-submission>
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>
--- tools/perf/builtin-top.c | 71 +++------------------------------------------ tools/perf/perf.h | 14 +++++++++ tools/perf/util/evlist.c | 8 +++++ tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 8 +++++ 6 files changed, 107 insertions(+), 66 deletions(-)
tools/perf/builtin-top.c +5 -66
@@ -1095,43 +1095,12 @@ static void event__process_sample(const event_t *self, } } -struct mmap_data { -void *base; -int mask; -unsigned int prev; -}; - -static int perf_evsel__alloc_mmap_per_thread (struct perf_evsel *evsel, -int ncpus,int nthreads) -{ - evsel->priv =xyarray__new (ncpus, nthreads,sizeof (struct mmap_data )); -return evsel->priv !=NULL ?0 : -ENOMEM ; -} - -static void perf_evsel__free_mmap (struct perf_evsel *evsel) -{ -xyarray__delete (evsel->priv); - evsel->priv =NULL ; -} - -static unsigned int mmap_read_head (struct mmap_data *md) -{ -struct perf_event_mmap_page *pc = md->base; -int head; - - head = pc->data_head; -rmb (); - -return head; -} -static void perf_session__mmap_read_counter (struct perf_session *self,struct perf_evsel *evsel,int cpu,int thread_idx) { -struct xyarray *mmap_array = evsel->priv; -struct mmap_data *md =xyarray__entry (mmap_array, cpu, thread_idx); -unsigned int head =mmap_read_head (md); +struct perf_mmap *md =xyarray__entry (evsel->mmap, cpu, thread_idx); +unsigned int head =perf_mmap__read_head (md);unsigned int old = md->prev;unsigned char *data = md->base + page_size;struct sample_data sample;
@@ -1210,35 +1179,9 @@ static void perf_session__mmap_read(struct perf_session *self) } } -static void start_counter (int i,struct perf_evlist *evlist, -struct perf_evsel *evsel) -{ -struct xyarray *mmap_array = evsel->priv; -struct mmap_data *mm; -int thread_index; - -for (thread_index =0 ; thread_index < threads->nr; thread_index++) { -assert (FD (evsel, i, thread_index) >=0 ); -fcntl (FD (evsel, i, thread_index),F_SETFL ,O_NONBLOCK ); - - evlist->pollfd[evlist->nr_fds].fd =FD (evsel, i, thread_index); - evlist->pollfd[evlist->nr_fds].events =POLLIN ; - evlist->nr_fds++; - - mm =xyarray__entry (mmap_array, i, thread_index); - mm->prev =0 ; - mm->mask = mmap_pages*page_size -1 ; - mm->base =mmap (NULL , (mmap_pages+1 )*page_size, -PROT_READ ,MAP_SHARED ,FD (evsel, i, thread_index),0 ); -if (mm->base ==MAP_FAILED ) -die ("failed to mmap with %d (%s)\n" , errno,strerror (errno)); - } -} -static void start_counters (struct perf_evlist *evlist) {struct perf_evsel *counter; -int i;list_for_each_entry (counter, &evlist->entries, node) {struct perf_event_attr *attr = &counter->attr;
@@ -1282,11 +1225,9 @@ try_again:die ("No CONFIG_PERF_EVENTS=y kernel support configured?\n" );exit (-1 ); } - } -for (i =0 ; i < cpus->nr; i++) { -list_for_each_entry (counter, &evlist->entries, node) -start_counter (i, evsel_list, counter); +if (perf_evsel__mmap (counter, cpus, threads, mmap_pages, evlist) <0 ) +die ("failed to mmap with %d (%s)\n" , errno,strerror (errno)); } }
@@ -1453,7 +1394,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)usage_with_options (top_usage, options);list_for_each_entry (pos, &evsel_list->entries, node) { -if (perf_evsel__alloc_mmap_per_thread (pos, cpus->nr, threads->nr) <0 || +if (perf_evsel__alloc_mmap (pos, cpus->nr, threads->nr) <0 ||perf_evsel__alloc_fd (pos, cpus->nr, threads->nr) <0 ) goto out_free_fd;/*
@@ -1485,8 +1426,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) status =__cmd_top (); out_free_fd: -list_for_each_entry (pos, &evsel_list->entries, node) -perf_evsel__free_mmap (pos);perf_evlist__delete (evsel_list);return status;
tools/perf/perf.h +14 -0
@@ -94,6 +94,20 @@ void get_term_dimensions(struct winsize *ws);#include "util/types.h" #include <stdbool.h> +struct perf_mmap { +void *base; +int mask; +unsigned int prev; +}; + +static inline unsigned int perf_mmap__read_head (struct perf_mmap *mm) +{ +struct perf_event_mmap_page *pc = mm->base; +int head = pc->data_head; +rmb (); +return head; +} +/* * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all * counters in the current task.
tools/perf/util/evlist.c +8 -0
@@ -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++; +}
tools/perf/util/evlist.h +1 -0
@@ -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 */
tools/perf/util/evsel.c +71 -0
93 lines not on this page · raw message
tools/perf/util/evsel.h +8 -0
@@ -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 && \