diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-15 07:40:59 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-22 16:56:30 -0500 |
commit | 04391debc3e1195222a4dbb162ace6542dd89c1c (patch) | |
tree | 910f12bd4d1f08c37d2086b4c725f50a8dd3c682 /tools/perf/util | |
parent | 98d77b78504a423fca911a26a17bee00ef2fdda2 (diff) |
perf evlist: Steal mmap reading routine from 'perf top'
Will be used in the upcoming 'perf test' entry for the evlist mmap
routines.
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 | 62 | ||||
-rw-r--r-- | tools/perf/util/evlist.h | 4 |
2 files changed, 66 insertions, 0 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index deb82a4fc312..4b3b84cd71a1 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -95,3 +95,65 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) | |||
95 | return sid->evsel; | 95 | return sid->evsel; |
96 | return NULL; | 96 | return NULL; |
97 | } | 97 | } |
98 | |||
99 | event_t *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu) | ||
100 | { | ||
101 | /* XXX Move this to perf.c, making it generally available */ | ||
102 | unsigned int page_size = sysconf(_SC_PAGE_SIZE); | ||
103 | struct perf_mmap *md = &evlist->mmap[cpu]; | ||
104 | unsigned int head = perf_mmap__read_head(md); | ||
105 | unsigned int old = md->prev; | ||
106 | unsigned char *data = md->base + page_size; | ||
107 | event_t *event = NULL; | ||
108 | int diff; | ||
109 | |||
110 | /* | ||
111 | * If we're further behind than half the buffer, there's a chance | ||
112 | * the writer will bite our tail and mess up the samples under us. | ||
113 | * | ||
114 | * If we somehow ended up ahead of the head, we got messed up. | ||
115 | * | ||
116 | * In either case, truncate and restart at head. | ||
117 | */ | ||
118 | diff = head - old; | ||
119 | if (diff > md->mask / 2 || diff < 0) { | ||
120 | fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); | ||
121 | |||
122 | /* | ||
123 | * head points to a known good entry, start there. | ||
124 | */ | ||
125 | old = head; | ||
126 | } | ||
127 | |||
128 | if (old != head) { | ||
129 | size_t size; | ||
130 | |||
131 | event = (event_t *)&data[old & md->mask]; | ||
132 | size = event->header.size; | ||
133 | |||
134 | /* | ||
135 | * Event straddles the mmap boundary -- header should always | ||
136 | * be inside due to u64 alignment of output. | ||
137 | */ | ||
138 | if ((old & md->mask) + size != ((old + size) & md->mask)) { | ||
139 | unsigned int offset = old; | ||
140 | unsigned int len = min(sizeof(*event), size), cpy; | ||
141 | void *dst = &evlist->event_copy; | ||
142 | |||
143 | do { | ||
144 | cpy = min(md->mask + 1 - (offset & md->mask), len); | ||
145 | memcpy(dst, &data[offset & md->mask], cpy); | ||
146 | offset += cpy; | ||
147 | dst += cpy; | ||
148 | len -= cpy; | ||
149 | } while (len); | ||
150 | |||
151 | event = &evlist->event_copy; | ||
152 | } | ||
153 | |||
154 | old += size; | ||
155 | } | ||
156 | |||
157 | md->prev = old; | ||
158 | return event; | ||
159 | } | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index dbfcc79bb995..28712063db97 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include "../perf.h" | 5 | #include "../perf.h" |
6 | #include "event.h" | ||
6 | 7 | ||
7 | struct pollfd; | 8 | struct pollfd; |
8 | 9 | ||
@@ -15,6 +16,7 @@ struct perf_evlist { | |||
15 | int nr_entries; | 16 | int nr_entries; |
16 | int nr_fds; | 17 | int nr_fds; |
17 | int mmap_len; | 18 | int mmap_len; |
19 | event_t event_copy; | ||
18 | struct perf_mmap *mmap; | 20 | struct perf_mmap *mmap; |
19 | struct pollfd *pollfd; | 21 | struct pollfd *pollfd; |
20 | }; | 22 | }; |
@@ -32,4 +34,6 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); | |||
32 | 34 | ||
33 | struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); | 35 | struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); |
34 | 36 | ||
37 | event_t *perf_evlist__read_on_cpu(struct perf_evlist *self, int cpu); | ||
38 | |||
35 | #endif /* __PERF_EVLIST_H */ | 39 | #endif /* __PERF_EVLIST_H */ |