diff options
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r-- | tools/perf/util/event.c | 358 |
1 files changed, 237 insertions, 121 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index dab9e754a281..2302ec051bb4 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include "strlist.h" | 7 | #include "strlist.h" |
8 | #include "thread.h" | 8 | #include "thread.h" |
9 | 9 | ||
10 | const char *event__name[] = { | 10 | static const char *event__name[] = { |
11 | [0] = "TOTAL", | 11 | [0] = "TOTAL", |
12 | [PERF_RECORD_MMAP] = "MMAP", | 12 | [PERF_RECORD_MMAP] = "MMAP", |
13 | [PERF_RECORD_LOST] = "LOST", | 13 | [PERF_RECORD_LOST] = "LOST", |
@@ -22,13 +22,31 @@ const char *event__name[] = { | |||
22 | [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", | 22 | [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", |
23 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", | 23 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", |
24 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", | 24 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", |
25 | [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", | ||
25 | }; | 26 | }; |
26 | 27 | ||
27 | static pid_t event__synthesize_comm(pid_t pid, int full, | 28 | const char *event__get_event_name(unsigned int id) |
29 | { | ||
30 | if (id >= ARRAY_SIZE(event__name)) | ||
31 | return "INVALID"; | ||
32 | if (!event__name[id]) | ||
33 | return "UNKNOWN"; | ||
34 | return event__name[id]; | ||
35 | } | ||
36 | |||
37 | static struct sample_data synth_sample = { | ||
38 | .pid = -1, | ||
39 | .tid = -1, | ||
40 | .time = -1, | ||
41 | .stream_id = -1, | ||
42 | .cpu = -1, | ||
43 | .period = 1, | ||
44 | }; | ||
45 | |||
46 | static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full, | ||
28 | event__handler_t process, | 47 | event__handler_t process, |
29 | struct perf_session *session) | 48 | struct perf_session *session) |
30 | { | 49 | { |
31 | event_t ev; | ||
32 | char filename[PATH_MAX]; | 50 | char filename[PATH_MAX]; |
33 | char bf[BUFSIZ]; | 51 | char bf[BUFSIZ]; |
34 | FILE *fp; | 52 | FILE *fp; |
@@ -49,34 +67,39 @@ out_race: | |||
49 | return 0; | 67 | return 0; |
50 | } | 68 | } |
51 | 69 | ||
52 | memset(&ev.comm, 0, sizeof(ev.comm)); | 70 | memset(&event->comm, 0, sizeof(event->comm)); |
53 | while (!ev.comm.comm[0] || !ev.comm.pid) { | 71 | |
54 | if (fgets(bf, sizeof(bf), fp) == NULL) | 72 | while (!event->comm.comm[0] || !event->comm.pid) { |
55 | goto out_failure; | 73 | if (fgets(bf, sizeof(bf), fp) == NULL) { |
74 | pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); | ||
75 | goto out; | ||
76 | } | ||
56 | 77 | ||
57 | if (memcmp(bf, "Name:", 5) == 0) { | 78 | if (memcmp(bf, "Name:", 5) == 0) { |
58 | char *name = bf + 5; | 79 | char *name = bf + 5; |
59 | while (*name && isspace(*name)) | 80 | while (*name && isspace(*name)) |
60 | ++name; | 81 | ++name; |
61 | size = strlen(name) - 1; | 82 | size = strlen(name) - 1; |
62 | memcpy(ev.comm.comm, name, size++); | 83 | memcpy(event->comm.comm, name, size++); |
63 | } else if (memcmp(bf, "Tgid:", 5) == 0) { | 84 | } else if (memcmp(bf, "Tgid:", 5) == 0) { |
64 | char *tgids = bf + 5; | 85 | char *tgids = bf + 5; |
65 | while (*tgids && isspace(*tgids)) | 86 | while (*tgids && isspace(*tgids)) |
66 | ++tgids; | 87 | ++tgids; |
67 | tgid = ev.comm.pid = atoi(tgids); | 88 | tgid = event->comm.pid = atoi(tgids); |
68 | } | 89 | } |
69 | } | 90 | } |
70 | 91 | ||
71 | ev.comm.header.type = PERF_RECORD_COMM; | 92 | event->comm.header.type = PERF_RECORD_COMM; |
72 | size = ALIGN(size, sizeof(u64)); | 93 | size = ALIGN(size, sizeof(u64)); |
73 | ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); | 94 | memset(event->comm.comm + size, 0, session->id_hdr_size); |
74 | 95 | event->comm.header.size = (sizeof(event->comm) - | |
96 | (sizeof(event->comm.comm) - size) + | ||
97 | session->id_hdr_size); | ||
75 | if (!full) { | 98 | if (!full) { |
76 | ev.comm.tid = pid; | 99 | event->comm.tid = pid; |
77 | 100 | ||
78 | process(&ev, session); | 101 | process(event, &synth_sample, session); |
79 | goto out_fclose; | 102 | goto out; |
80 | } | 103 | } |
81 | 104 | ||
82 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | 105 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); |
@@ -91,22 +114,19 @@ out_race: | |||
91 | if (*end) | 114 | if (*end) |
92 | continue; | 115 | continue; |
93 | 116 | ||
94 | ev.comm.tid = pid; | 117 | event->comm.tid = pid; |
95 | 118 | ||
96 | process(&ev, session); | 119 | process(event, &synth_sample, session); |
97 | } | 120 | } |
98 | closedir(tasks); | ||
99 | 121 | ||
100 | out_fclose: | 122 | closedir(tasks); |
123 | out: | ||
101 | fclose(fp); | 124 | fclose(fp); |
102 | return tgid; | ||
103 | 125 | ||
104 | out_failure: | 126 | return tgid; |
105 | pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); | ||
106 | return -1; | ||
107 | } | 127 | } |
108 | 128 | ||
109 | static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | 129 | static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid, |
110 | event__handler_t process, | 130 | event__handler_t process, |
111 | struct perf_session *session) | 131 | struct perf_session *session) |
112 | { | 132 | { |
@@ -124,29 +144,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | |||
124 | return -1; | 144 | return -1; |
125 | } | 145 | } |
126 | 146 | ||
147 | event->header.type = PERF_RECORD_MMAP; | ||
148 | /* | ||
149 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | ||
150 | */ | ||
151 | event->header.misc = PERF_RECORD_MISC_USER; | ||
152 | |||
127 | while (1) { | 153 | while (1) { |
128 | char bf[BUFSIZ], *pbf = bf; | 154 | char bf[BUFSIZ], *pbf = bf; |
129 | event_t ev = { | ||
130 | .header = { | ||
131 | .type = PERF_RECORD_MMAP, | ||
132 | /* | ||
133 | * Just like the kernel, see __perf_event_mmap | ||
134 | * in kernel/perf_event.c | ||
135 | */ | ||
136 | .misc = PERF_RECORD_MISC_USER, | ||
137 | }, | ||
138 | }; | ||
139 | int n; | 155 | int n; |
140 | size_t size; | 156 | size_t size; |
141 | if (fgets(bf, sizeof(bf), fp) == NULL) | 157 | if (fgets(bf, sizeof(bf), fp) == NULL) |
142 | break; | 158 | break; |
143 | 159 | ||
144 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ | 160 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ |
145 | n = hex2u64(pbf, &ev.mmap.start); | 161 | n = hex2u64(pbf, &event->mmap.start); |
146 | if (n < 0) | 162 | if (n < 0) |
147 | continue; | 163 | continue; |
148 | pbf += n + 1; | 164 | pbf += n + 1; |
149 | n = hex2u64(pbf, &ev.mmap.len); | 165 | n = hex2u64(pbf, &event->mmap.len); |
150 | if (n < 0) | 166 | if (n < 0) |
151 | continue; | 167 | continue; |
152 | pbf += n + 3; | 168 | pbf += n + 3; |
@@ -161,19 +177,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | |||
161 | continue; | 177 | continue; |
162 | 178 | ||
163 | pbf += 3; | 179 | pbf += 3; |
164 | n = hex2u64(pbf, &ev.mmap.pgoff); | 180 | n = hex2u64(pbf, &event->mmap.pgoff); |
165 | 181 | ||
166 | size = strlen(execname); | 182 | size = strlen(execname); |
167 | execname[size - 1] = '\0'; /* Remove \n */ | 183 | execname[size - 1] = '\0'; /* Remove \n */ |
168 | memcpy(ev.mmap.filename, execname, size); | 184 | memcpy(event->mmap.filename, execname, size); |
169 | size = ALIGN(size, sizeof(u64)); | 185 | size = ALIGN(size, sizeof(u64)); |
170 | ev.mmap.len -= ev.mmap.start; | 186 | event->mmap.len -= event->mmap.start; |
171 | ev.mmap.header.size = (sizeof(ev.mmap) - | 187 | event->mmap.header.size = (sizeof(event->mmap) - |
172 | (sizeof(ev.mmap.filename) - size)); | 188 | (sizeof(event->mmap.filename) - size)); |
173 | ev.mmap.pid = tgid; | 189 | memset(event->mmap.filename + size, 0, session->id_hdr_size); |
174 | ev.mmap.tid = pid; | 190 | event->mmap.header.size += session->id_hdr_size; |
175 | 191 | event->mmap.pid = tgid; | |
176 | process(&ev, session); | 192 | event->mmap.tid = pid; |
193 | |||
194 | process(event, &synth_sample, session); | ||
177 | } | 195 | } |
178 | } | 196 | } |
179 | 197 | ||
@@ -187,20 +205,27 @@ int event__synthesize_modules(event__handler_t process, | |||
187 | { | 205 | { |
188 | struct rb_node *nd; | 206 | struct rb_node *nd; |
189 | struct map_groups *kmaps = &machine->kmaps; | 207 | struct map_groups *kmaps = &machine->kmaps; |
190 | u16 misc; | 208 | event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size); |
209 | |||
210 | if (event == NULL) { | ||
211 | pr_debug("Not enough memory synthesizing mmap event " | ||
212 | "for kernel modules\n"); | ||
213 | return -1; | ||
214 | } | ||
215 | |||
216 | event->header.type = PERF_RECORD_MMAP; | ||
191 | 217 | ||
192 | /* | 218 | /* |
193 | * kernel uses 0 for user space maps, see kernel/perf_event.c | 219 | * kernel uses 0 for user space maps, see kernel/perf_event.c |
194 | * __perf_event_mmap | 220 | * __perf_event_mmap |
195 | */ | 221 | */ |
196 | if (machine__is_host(machine)) | 222 | if (machine__is_host(machine)) |
197 | misc = PERF_RECORD_MISC_KERNEL; | 223 | event->header.misc = PERF_RECORD_MISC_KERNEL; |
198 | else | 224 | else |
199 | misc = PERF_RECORD_MISC_GUEST_KERNEL; | 225 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
200 | 226 | ||
201 | for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); | 227 | for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); |
202 | nd; nd = rb_next(nd)) { | 228 | nd; nd = rb_next(nd)) { |
203 | event_t ev; | ||
204 | size_t size; | 229 | size_t size; |
205 | struct map *pos = rb_entry(nd, struct map, rb_node); | 230 | struct map *pos = rb_entry(nd, struct map, rb_node); |
206 | 231 | ||
@@ -208,39 +233,78 @@ int event__synthesize_modules(event__handler_t process, | |||
208 | continue; | 233 | continue; |
209 | 234 | ||
210 | size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); | 235 | size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); |
211 | memset(&ev, 0, sizeof(ev)); | 236 | event->mmap.header.type = PERF_RECORD_MMAP; |
212 | ev.mmap.header.misc = misc; | 237 | event->mmap.header.size = (sizeof(event->mmap) - |
213 | ev.mmap.header.type = PERF_RECORD_MMAP; | 238 | (sizeof(event->mmap.filename) - size)); |
214 | ev.mmap.header.size = (sizeof(ev.mmap) - | 239 | memset(event->mmap.filename + size, 0, session->id_hdr_size); |
215 | (sizeof(ev.mmap.filename) - size)); | 240 | event->mmap.header.size += session->id_hdr_size; |
216 | ev.mmap.start = pos->start; | 241 | event->mmap.start = pos->start; |
217 | ev.mmap.len = pos->end - pos->start; | 242 | event->mmap.len = pos->end - pos->start; |
218 | ev.mmap.pid = machine->pid; | 243 | event->mmap.pid = machine->pid; |
219 | 244 | ||
220 | memcpy(ev.mmap.filename, pos->dso->long_name, | 245 | memcpy(event->mmap.filename, pos->dso->long_name, |
221 | pos->dso->long_name_len + 1); | 246 | pos->dso->long_name_len + 1); |
222 | process(&ev, session); | 247 | process(event, &synth_sample, session); |
223 | } | 248 | } |
224 | 249 | ||
250 | free(event); | ||
225 | return 0; | 251 | return 0; |
226 | } | 252 | } |
227 | 253 | ||
228 | int event__synthesize_thread(pid_t pid, event__handler_t process, | 254 | static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event, |
229 | struct perf_session *session) | 255 | pid_t pid, event__handler_t process, |
256 | struct perf_session *session) | ||
230 | { | 257 | { |
231 | pid_t tgid = event__synthesize_comm(pid, 1, process, session); | 258 | pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process, |
259 | session); | ||
232 | if (tgid == -1) | 260 | if (tgid == -1) |
233 | return -1; | 261 | return -1; |
234 | return event__synthesize_mmap_events(pid, tgid, process, session); | 262 | return event__synthesize_mmap_events(mmap_event, pid, tgid, |
263 | process, session); | ||
264 | } | ||
265 | |||
266 | int event__synthesize_thread(pid_t pid, event__handler_t process, | ||
267 | struct perf_session *session) | ||
268 | { | ||
269 | event_t *comm_event, *mmap_event; | ||
270 | int err = -1; | ||
271 | |||
272 | comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); | ||
273 | if (comm_event == NULL) | ||
274 | goto out; | ||
275 | |||
276 | mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); | ||
277 | if (mmap_event == NULL) | ||
278 | goto out_free_comm; | ||
279 | |||
280 | err = __event__synthesize_thread(comm_event, mmap_event, pid, | ||
281 | process, session); | ||
282 | free(mmap_event); | ||
283 | out_free_comm: | ||
284 | free(comm_event); | ||
285 | out: | ||
286 | return err; | ||
235 | } | 287 | } |
236 | 288 | ||
237 | void event__synthesize_threads(event__handler_t process, | 289 | int event__synthesize_threads(event__handler_t process, |
238 | struct perf_session *session) | 290 | struct perf_session *session) |
239 | { | 291 | { |
240 | DIR *proc; | 292 | DIR *proc; |
241 | struct dirent dirent, *next; | 293 | struct dirent dirent, *next; |
294 | event_t *comm_event, *mmap_event; | ||
295 | int err = -1; | ||
296 | |||
297 | comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); | ||
298 | if (comm_event == NULL) | ||
299 | goto out; | ||
300 | |||
301 | mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); | ||
302 | if (mmap_event == NULL) | ||
303 | goto out_free_comm; | ||
242 | 304 | ||
243 | proc = opendir("/proc"); | 305 | proc = opendir("/proc"); |
306 | if (proc == NULL) | ||
307 | goto out_free_mmap; | ||
244 | 308 | ||
245 | while (!readdir_r(proc, &dirent, &next) && next) { | 309 | while (!readdir_r(proc, &dirent, &next) && next) { |
246 | char *end; | 310 | char *end; |
@@ -249,10 +313,18 @@ void event__synthesize_threads(event__handler_t process, | |||
249 | if (*end) /* only interested in proper numerical dirents */ | 313 | if (*end) /* only interested in proper numerical dirents */ |
250 | continue; | 314 | continue; |
251 | 315 | ||
252 | event__synthesize_thread(pid, process, session); | 316 | __event__synthesize_thread(comm_event, mmap_event, pid, |
317 | process, session); | ||
253 | } | 318 | } |
254 | 319 | ||
255 | closedir(proc); | 320 | closedir(proc); |
321 | err = 0; | ||
322 | out_free_mmap: | ||
323 | free(mmap_event); | ||
324 | out_free_comm: | ||
325 | free(comm_event); | ||
326 | out: | ||
327 | return err; | ||
256 | } | 328 | } |
257 | 329 | ||
258 | struct process_symbol_args { | 330 | struct process_symbol_args { |
@@ -260,7 +332,8 @@ struct process_symbol_args { | |||
260 | u64 start; | 332 | u64 start; |
261 | }; | 333 | }; |
262 | 334 | ||
263 | static int find_symbol_cb(void *arg, const char *name, char type, u64 start) | 335 | static int find_symbol_cb(void *arg, const char *name, char type, |
336 | u64 start, u64 end __used) | ||
264 | { | 337 | { |
265 | struct process_symbol_args *args = arg; | 338 | struct process_symbol_args *args = arg; |
266 | 339 | ||
@@ -286,18 +359,20 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
286 | char path[PATH_MAX]; | 359 | char path[PATH_MAX]; |
287 | char name_buff[PATH_MAX]; | 360 | char name_buff[PATH_MAX]; |
288 | struct map *map; | 361 | struct map *map; |
289 | 362 | int err; | |
290 | event_t ev = { | ||
291 | .header = { | ||
292 | .type = PERF_RECORD_MMAP, | ||
293 | }, | ||
294 | }; | ||
295 | /* | 363 | /* |
296 | * We should get this from /sys/kernel/sections/.text, but till that is | 364 | * We should get this from /sys/kernel/sections/.text, but till that is |
297 | * available use this, and after it is use this as a fallback for older | 365 | * available use this, and after it is use this as a fallback for older |
298 | * kernels. | 366 | * kernels. |
299 | */ | 367 | */ |
300 | struct process_symbol_args args = { .name = symbol_name, }; | 368 | struct process_symbol_args args = { .name = symbol_name, }; |
369 | event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size); | ||
370 | |||
371 | if (event == NULL) { | ||
372 | pr_debug("Not enough memory synthesizing mmap event " | ||
373 | "for kernel modules\n"); | ||
374 | return -1; | ||
375 | } | ||
301 | 376 | ||
302 | mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); | 377 | mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); |
303 | if (machine__is_host(machine)) { | 378 | if (machine__is_host(machine)) { |
@@ -305,10 +380,10 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
305 | * kernel uses PERF_RECORD_MISC_USER for user space maps, | 380 | * kernel uses PERF_RECORD_MISC_USER for user space maps, |
306 | * see kernel/perf_event.c __perf_event_mmap | 381 | * see kernel/perf_event.c __perf_event_mmap |
307 | */ | 382 | */ |
308 | ev.header.misc = PERF_RECORD_MISC_KERNEL; | 383 | event->header.misc = PERF_RECORD_MISC_KERNEL; |
309 | filename = "/proc/kallsyms"; | 384 | filename = "/proc/kallsyms"; |
310 | } else { | 385 | } else { |
311 | ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; | 386 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
312 | if (machine__is_default_guest(machine)) | 387 | if (machine__is_default_guest(machine)) |
313 | filename = (char *) symbol_conf.default_guest_kallsyms; | 388 | filename = (char *) symbol_conf.default_guest_kallsyms; |
314 | else { | 389 | else { |
@@ -321,17 +396,21 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
321 | return -ENOENT; | 396 | return -ENOENT; |
322 | 397 | ||
323 | map = machine->vmlinux_maps[MAP__FUNCTION]; | 398 | map = machine->vmlinux_maps[MAP__FUNCTION]; |
324 | size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), | 399 | size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), |
325 | "%s%s", mmap_name, symbol_name) + 1; | 400 | "%s%s", mmap_name, symbol_name) + 1; |
326 | size = ALIGN(size, sizeof(u64)); | 401 | size = ALIGN(size, sizeof(u64)); |
327 | ev.mmap.header.size = (sizeof(ev.mmap) - | 402 | event->mmap.header.type = PERF_RECORD_MMAP; |
328 | (sizeof(ev.mmap.filename) - size)); | 403 | event->mmap.header.size = (sizeof(event->mmap) - |
329 | ev.mmap.pgoff = args.start; | 404 | (sizeof(event->mmap.filename) - size) + session->id_hdr_size); |
330 | ev.mmap.start = map->start; | 405 | event->mmap.pgoff = args.start; |
331 | ev.mmap.len = map->end - ev.mmap.start; | 406 | event->mmap.start = map->start; |
332 | ev.mmap.pid = machine->pid; | 407 | event->mmap.len = map->end - event->mmap.start; |
333 | 408 | event->mmap.pid = machine->pid; | |
334 | return process(&ev, session); | 409 | |
410 | err = process(event, &synth_sample, session); | ||
411 | free(event); | ||
412 | |||
413 | return err; | ||
335 | } | 414 | } |
336 | 415 | ||
337 | static void thread__comm_adjust(struct thread *self, struct hists *hists) | 416 | static void thread__comm_adjust(struct thread *self, struct hists *hists) |
@@ -361,7 +440,8 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm, | |||
361 | return 0; | 440 | return 0; |
362 | } | 441 | } |
363 | 442 | ||
364 | int event__process_comm(event_t *self, struct perf_session *session) | 443 | int event__process_comm(event_t *self, struct sample_data *sample __used, |
444 | struct perf_session *session) | ||
365 | { | 445 | { |
366 | struct thread *thread = perf_session__findnew(session, self->comm.tid); | 446 | struct thread *thread = perf_session__findnew(session, self->comm.tid); |
367 | 447 | ||
@@ -376,7 +456,8 @@ int event__process_comm(event_t *self, struct perf_session *session) | |||
376 | return 0; | 456 | return 0; |
377 | } | 457 | } |
378 | 458 | ||
379 | int event__process_lost(event_t *self, struct perf_session *session) | 459 | int event__process_lost(event_t *self, struct sample_data *sample __used, |
460 | struct perf_session *session) | ||
380 | { | 461 | { |
381 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); | 462 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); |
382 | session->hists.stats.total_lost += self->lost.lost; | 463 | session->hists.stats.total_lost += self->lost.lost; |
@@ -392,7 +473,7 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self) | |||
392 | * a zero sized synthesized MMAP event for the kernel. | 473 | * a zero sized synthesized MMAP event for the kernel. |
393 | */ | 474 | */ |
394 | if (maps[MAP__FUNCTION]->end == 0) | 475 | if (maps[MAP__FUNCTION]->end == 0) |
395 | maps[MAP__FUNCTION]->end = ~0UL; | 476 | maps[MAP__FUNCTION]->end = ~0ULL; |
396 | } | 477 | } |
397 | 478 | ||
398 | static int event__process_kernel_mmap(event_t *self, | 479 | static int event__process_kernel_mmap(event_t *self, |
@@ -485,7 +566,8 @@ out_problem: | |||
485 | return -1; | 566 | return -1; |
486 | } | 567 | } |
487 | 568 | ||
488 | int event__process_mmap(event_t *self, struct perf_session *session) | 569 | int event__process_mmap(event_t *self, struct sample_data *sample __used, |
570 | struct perf_session *session) | ||
489 | { | 571 | { |
490 | struct machine *machine; | 572 | struct machine *machine; |
491 | struct thread *thread; | 573 | struct thread *thread; |
@@ -526,7 +608,8 @@ out_problem: | |||
526 | return 0; | 608 | return 0; |
527 | } | 609 | } |
528 | 610 | ||
529 | int event__process_task(event_t *self, struct perf_session *session) | 611 | int event__process_task(event_t *self, struct sample_data *sample __used, |
612 | struct perf_session *session) | ||
530 | { | 613 | { |
531 | struct thread *thread = perf_session__findnew(session, self->fork.tid); | 614 | struct thread *thread = perf_session__findnew(session, self->fork.tid); |
532 | struct thread *parent = perf_session__findnew(session, self->fork.ptid); | 615 | struct thread *parent = perf_session__findnew(session, self->fork.ptid); |
@@ -548,18 +631,19 @@ int event__process_task(event_t *self, struct perf_session *session) | |||
548 | return 0; | 631 | return 0; |
549 | } | 632 | } |
550 | 633 | ||
551 | int event__process(event_t *event, struct perf_session *session) | 634 | int event__process(event_t *event, struct sample_data *sample, |
635 | struct perf_session *session) | ||
552 | { | 636 | { |
553 | switch (event->header.type) { | 637 | switch (event->header.type) { |
554 | case PERF_RECORD_COMM: | 638 | case PERF_RECORD_COMM: |
555 | event__process_comm(event, session); | 639 | event__process_comm(event, sample, session); |
556 | break; | 640 | break; |
557 | case PERF_RECORD_MMAP: | 641 | case PERF_RECORD_MMAP: |
558 | event__process_mmap(event, session); | 642 | event__process_mmap(event, sample, session); |
559 | break; | 643 | break; |
560 | case PERF_RECORD_FORK: | 644 | case PERF_RECORD_FORK: |
561 | case PERF_RECORD_EXIT: | 645 | case PERF_RECORD_EXIT: |
562 | event__process_task(event, session); | 646 | event__process_task(event, sample, session); |
563 | break; | 647 | break; |
564 | default: | 648 | default: |
565 | break; | 649 | break; |
@@ -674,32 +758,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, | |||
674 | symbol_filter_t filter) | 758 | symbol_filter_t filter) |
675 | { | 759 | { |
676 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 760 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
677 | struct thread *thread; | 761 | struct thread *thread = perf_session__findnew(session, self->ip.pid); |
678 | |||
679 | event__parse_sample(self, session->sample_type, data); | ||
680 | |||
681 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n", | ||
682 | self->header.misc, data->pid, data->tid, data->ip, | ||
683 | data->period, data->cpu); | ||
684 | |||
685 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
686 | unsigned int i; | ||
687 | |||
688 | dump_printf("... chain: nr:%Lu\n", data->callchain->nr); | ||
689 | 762 | ||
690 | if (!ip_callchain__valid(data->callchain, self)) { | ||
691 | pr_debug("call-chain problem with event, " | ||
692 | "skipping it.\n"); | ||
693 | goto out_filtered; | ||
694 | } | ||
695 | |||
696 | if (dump_trace) { | ||
697 | for (i = 0; i < data->callchain->nr; i++) | ||
698 | dump_printf("..... %2d: %016Lx\n", | ||
699 | i, data->callchain->ips[i]); | ||
700 | } | ||
701 | } | ||
702 | thread = perf_session__findnew(session, self->ip.pid); | ||
703 | if (thread == NULL) | 763 | if (thread == NULL) |
704 | return -1; | 764 | return -1; |
705 | 765 | ||
@@ -766,9 +826,65 @@ out_filtered: | |||
766 | return 0; | 826 | return 0; |
767 | } | 827 | } |
768 | 828 | ||
769 | int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) | 829 | static int event__parse_id_sample(const event_t *event, |
830 | struct perf_session *session, | ||
831 | struct sample_data *sample) | ||
770 | { | 832 | { |
771 | const u64 *array = event->sample.array; | 833 | const u64 *array; |
834 | u64 type; | ||
835 | |||
836 | sample->cpu = sample->pid = sample->tid = -1; | ||
837 | sample->stream_id = sample->id = sample->time = -1ULL; | ||
838 | |||
839 | if (!session->sample_id_all) | ||
840 | return 0; | ||
841 | |||
842 | array = event->sample.array; | ||
843 | array += ((event->header.size - | ||
844 | sizeof(event->header)) / sizeof(u64)) - 1; | ||
845 | type = session->sample_type; | ||
846 | |||
847 | if (type & PERF_SAMPLE_CPU) { | ||
848 | u32 *p = (u32 *)array; | ||
849 | sample->cpu = *p; | ||
850 | array--; | ||
851 | } | ||
852 | |||
853 | if (type & PERF_SAMPLE_STREAM_ID) { | ||
854 | sample->stream_id = *array; | ||
855 | array--; | ||
856 | } | ||
857 | |||
858 | if (type & PERF_SAMPLE_ID) { | ||
859 | sample->id = *array; | ||
860 | array--; | ||
861 | } | ||
862 | |||
863 | if (type & PERF_SAMPLE_TIME) { | ||
864 | sample->time = *array; | ||
865 | array--; | ||
866 | } | ||
867 | |||
868 | if (type & PERF_SAMPLE_TID) { | ||
869 | u32 *p = (u32 *)array; | ||
870 | sample->pid = p[0]; | ||
871 | sample->tid = p[1]; | ||
872 | } | ||
873 | |||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | int event__parse_sample(const event_t *event, struct perf_session *session, | ||
878 | struct sample_data *data) | ||
879 | { | ||
880 | const u64 *array; | ||
881 | u64 type; | ||
882 | |||
883 | if (event->header.type != PERF_RECORD_SAMPLE) | ||
884 | return event__parse_id_sample(event, session, data); | ||
885 | |||
886 | array = event->sample.array; | ||
887 | type = session->sample_type; | ||
772 | 888 | ||
773 | if (type & PERF_SAMPLE_IP) { | 889 | if (type & PERF_SAMPLE_IP) { |
774 | data->ip = event->ip.ip; | 890 | data->ip = event->ip.ip; |