diff options
Diffstat (limited to 'tools/perf/util/data_map.c')
-rw-r--r-- | tools/perf/util/data_map.c | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index 6d46dda53a29..b557b836de3d 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c | |||
@@ -1,20 +1,17 @@ | |||
1 | #include "data_map.h" | ||
2 | #include "symbol.h" | 1 | #include "symbol.h" |
3 | #include "util.h" | 2 | #include "util.h" |
4 | #include "debug.h" | 3 | #include "debug.h" |
4 | #include "thread.h" | ||
5 | #include "session.h" | ||
5 | 6 | ||
6 | 7 | static int process_event_stub(event_t *event __used, | |
7 | static struct perf_file_handler *curr_handler; | 8 | struct perf_session *session __used) |
8 | static unsigned long mmap_window = 32; | ||
9 | static char __cwd[PATH_MAX]; | ||
10 | |||
11 | static int process_event_stub(event_t *event __used) | ||
12 | { | 9 | { |
13 | dump_printf(": unhandled!\n"); | 10 | dump_printf(": unhandled!\n"); |
14 | return 0; | 11 | return 0; |
15 | } | 12 | } |
16 | 13 | ||
17 | void register_perf_file_handler(struct perf_file_handler *handler) | 14 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) |
18 | { | 15 | { |
19 | if (!handler->process_sample_event) | 16 | if (!handler->process_sample_event) |
20 | handler->process_sample_event = process_event_stub; | 17 | handler->process_sample_event = process_event_stub; |
@@ -34,8 +31,6 @@ void register_perf_file_handler(struct perf_file_handler *handler) | |||
34 | handler->process_throttle_event = process_event_stub; | 31 | handler->process_throttle_event = process_event_stub; |
35 | if (!handler->process_unthrottle_event) | 32 | if (!handler->process_unthrottle_event) |
36 | handler->process_unthrottle_event = process_event_stub; | 33 | handler->process_unthrottle_event = process_event_stub; |
37 | |||
38 | curr_handler = handler; | ||
39 | } | 34 | } |
40 | 35 | ||
41 | static const char *event__name[] = { | 36 | static const char *event__name[] = { |
@@ -61,8 +56,9 @@ void event__print_totals(void) | |||
61 | event__name[i], event__total[i]); | 56 | event__name[i], event__total[i]); |
62 | } | 57 | } |
63 | 58 | ||
64 | static int | 59 | static int process_event(event_t *event, struct perf_session *session, |
65 | process_event(event_t *event, unsigned long offset, unsigned long head) | 60 | struct perf_event_ops *ops, |
61 | unsigned long offset, unsigned long head) | ||
66 | { | 62 | { |
67 | trace_event(event); | 63 | trace_event(event); |
68 | 64 | ||
@@ -77,25 +73,25 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
77 | 73 | ||
78 | switch (event->header.type) { | 74 | switch (event->header.type) { |
79 | case PERF_RECORD_SAMPLE: | 75 | case PERF_RECORD_SAMPLE: |
80 | return curr_handler->process_sample_event(event); | 76 | return ops->process_sample_event(event, session); |
81 | case PERF_RECORD_MMAP: | 77 | case PERF_RECORD_MMAP: |
82 | return curr_handler->process_mmap_event(event); | 78 | return ops->process_mmap_event(event, session); |
83 | case PERF_RECORD_COMM: | 79 | case PERF_RECORD_COMM: |
84 | return curr_handler->process_comm_event(event); | 80 | return ops->process_comm_event(event, session); |
85 | case PERF_RECORD_FORK: | 81 | case PERF_RECORD_FORK: |
86 | return curr_handler->process_fork_event(event); | 82 | return ops->process_fork_event(event, session); |
87 | case PERF_RECORD_EXIT: | 83 | case PERF_RECORD_EXIT: |
88 | return curr_handler->process_exit_event(event); | 84 | return ops->process_exit_event(event, session); |
89 | case PERF_RECORD_LOST: | 85 | case PERF_RECORD_LOST: |
90 | return curr_handler->process_lost_event(event); | 86 | return ops->process_lost_event(event, session); |
91 | case PERF_RECORD_READ: | 87 | case PERF_RECORD_READ: |
92 | return curr_handler->process_read_event(event); | 88 | return ops->process_read_event(event, session); |
93 | case PERF_RECORD_THROTTLE: | 89 | case PERF_RECORD_THROTTLE: |
94 | return curr_handler->process_throttle_event(event); | 90 | return ops->process_throttle_event(event, session); |
95 | case PERF_RECORD_UNTHROTTLE: | 91 | case PERF_RECORD_UNTHROTTLE: |
96 | return curr_handler->process_unthrottle_event(event); | 92 | return ops->process_unthrottle_event(event, session); |
97 | default: | 93 | default: |
98 | curr_handler->total_unknown++; | 94 | ops->total_unknown++; |
99 | return -1; | 95 | return -1; |
100 | } | 96 | } |
101 | } | 97 | } |
@@ -129,44 +125,58 @@ out: | |||
129 | return err; | 125 | return err; |
130 | } | 126 | } |
131 | 127 | ||
128 | static struct thread *perf_session__register_idle_thread(struct perf_session *self) | ||
129 | { | ||
130 | struct thread *thread = perf_session__findnew(self, 0); | ||
131 | |||
132 | if (!thread || thread__set_comm(thread, "swapper")) { | ||
133 | pr_err("problem inserting idle task.\n"); | ||
134 | thread = NULL; | ||
135 | } | ||
136 | |||
137 | return thread; | ||
138 | } | ||
139 | |||
132 | int perf_session__process_events(struct perf_session *self, | 140 | int perf_session__process_events(struct perf_session *self, |
133 | int full_paths, int *cwdlen, char **cwd) | 141 | struct perf_event_ops *ops) |
134 | { | 142 | { |
135 | int err; | 143 | int err; |
136 | unsigned long head, shift; | 144 | unsigned long head, shift; |
137 | unsigned long offset = 0; | 145 | unsigned long offset = 0; |
138 | size_t page_size; | 146 | size_t page_size; |
139 | u64 sample_type; | ||
140 | event_t *event; | 147 | event_t *event; |
141 | uint32_t size; | 148 | uint32_t size; |
142 | char *buf; | 149 | char *buf; |
143 | 150 | ||
144 | if (curr_handler == NULL) { | 151 | if (perf_session__register_idle_thread(self) == NULL) |
145 | pr_debug("Forgot to register perf file handler\n"); | 152 | return -ENOMEM; |
146 | return -EINVAL; | 153 | |
147 | } | 154 | perf_event_ops__fill_defaults(ops); |
148 | 155 | ||
149 | page_size = getpagesize(); | 156 | page_size = getpagesize(); |
150 | 157 | ||
151 | head = self->header.data_offset; | 158 | head = self->header.data_offset; |
152 | sample_type = perf_header__sample_type(&self->header); | 159 | self->sample_type = perf_header__sample_type(&self->header); |
153 | 160 | ||
154 | err = -EINVAL; | 161 | err = -EINVAL; |
155 | if (curr_handler->sample_type_check && | 162 | if (ops->sample_type_check && ops->sample_type_check(self) < 0) |
156 | curr_handler->sample_type_check(sample_type) < 0) | ||
157 | goto out_err; | 163 | goto out_err; |
158 | 164 | ||
159 | if (!full_paths) { | 165 | if (!ops->full_paths) { |
160 | if (getcwd(__cwd, sizeof(__cwd)) == NULL) { | 166 | char bf[PATH_MAX]; |
161 | pr_err("failed to get the current directory\n"); | 167 | |
168 | if (getcwd(bf, sizeof(bf)) == NULL) { | ||
162 | err = -errno; | 169 | err = -errno; |
170 | out_getcwd_err: | ||
171 | pr_err("failed to get the current directory\n"); | ||
163 | goto out_err; | 172 | goto out_err; |
164 | } | 173 | } |
165 | *cwd = __cwd; | 174 | self->cwd = strdup(bf); |
166 | *cwdlen = strlen(*cwd); | 175 | if (self->cwd == NULL) { |
167 | } else { | 176 | err = -ENOMEM; |
168 | *cwd = NULL; | 177 | goto out_getcwd_err; |
169 | *cwdlen = 0; | 178 | } |
179 | self->cwdlen = strlen(self->cwd); | ||
170 | } | 180 | } |
171 | 181 | ||
172 | shift = page_size * (head / page_size); | 182 | shift = page_size * (head / page_size); |
@@ -174,7 +184,7 @@ int perf_session__process_events(struct perf_session *self, | |||
174 | head -= shift; | 184 | head -= shift; |
175 | 185 | ||
176 | remap: | 186 | remap: |
177 | buf = mmap(NULL, page_size * mmap_window, PROT_READ, | 187 | buf = mmap(NULL, page_size * self->mmap_window, PROT_READ, |
178 | MAP_SHARED, self->fd, offset); | 188 | MAP_SHARED, self->fd, offset); |
179 | if (buf == MAP_FAILED) { | 189 | if (buf == MAP_FAILED) { |
180 | pr_err("failed to mmap file\n"); | 190 | pr_err("failed to mmap file\n"); |
@@ -189,12 +199,12 @@ more: | |||
189 | if (!size) | 199 | if (!size) |
190 | size = 8; | 200 | size = 8; |
191 | 201 | ||
192 | if (head + event->header.size >= page_size * mmap_window) { | 202 | if (head + event->header.size >= page_size * self->mmap_window) { |
193 | int munmap_ret; | 203 | int munmap_ret; |
194 | 204 | ||
195 | shift = page_size * (head / page_size); | 205 | shift = page_size * (head / page_size); |
196 | 206 | ||
197 | munmap_ret = munmap(buf, page_size * mmap_window); | 207 | munmap_ret = munmap(buf, page_size * self->mmap_window); |
198 | assert(munmap_ret == 0); | 208 | assert(munmap_ret == 0); |
199 | 209 | ||
200 | offset += shift; | 210 | offset += shift; |
@@ -209,7 +219,7 @@ more: | |||
209 | (void *)(long)event->header.size, | 219 | (void *)(long)event->header.size, |
210 | event->header.type); | 220 | event->header.type); |
211 | 221 | ||
212 | if (!size || process_event(event, offset, head) < 0) { | 222 | if (!size || process_event(event, self, ops, offset, head) < 0) { |
213 | 223 | ||
214 | dump_printf("%p [%p]: skipping unknown header type: %d\n", | 224 | dump_printf("%p [%p]: skipping unknown header type: %d\n", |
215 | (void *)(offset + head), | 225 | (void *)(offset + head), |