aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r--tools/perf/util/event.c156
1 files changed, 100 insertions, 56 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index b0f3ca850e9e..3e580be0f6fb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -94,14 +94,10 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
94 94
95static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 95static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
96 union perf_event *event, pid_t pid, 96 union perf_event *event, pid_t pid,
97 int full,
98 perf_event__handler_t process, 97 perf_event__handler_t process,
99 struct machine *machine) 98 struct machine *machine)
100{ 99{
101 char filename[PATH_MAX];
102 size_t size; 100 size_t size;
103 DIR *tasks;
104 struct dirent dirent, *next;
105 pid_t tgid; 101 pid_t tgid;
106 102
107 memset(&event->comm, 0, sizeof(event->comm)); 103 memset(&event->comm, 0, sizeof(event->comm));
@@ -124,55 +120,35 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
124 event->comm.header.size = (sizeof(event->comm) - 120 event->comm.header.size = (sizeof(event->comm) -
125 (sizeof(event->comm.comm) - size) + 121 (sizeof(event->comm.comm) - size) +
126 machine->id_hdr_size); 122 machine->id_hdr_size);
127 if (!full) { 123 event->comm.tid = pid;
128 event->comm.tid = pid;
129
130 if (process(tool, event, &synth_sample, machine) != 0)
131 return -1;
132 124
133 goto out; 125 if (process(tool, event, &synth_sample, machine) != 0)
134 } 126 return -1;
135
136 if (machine__is_default_guest(machine))
137 return 0;
138
139 snprintf(filename, sizeof(filename), "%s/proc/%d/task",
140 machine->root_dir, pid);
141
142 tasks = opendir(filename);
143 if (tasks == NULL) {
144 pr_debug("couldn't open %s\n", filename);
145 return 0;
146 }
147 127
148 while (!readdir_r(tasks, &dirent, &next) && next) { 128out:
149 char *end; 129 return tgid;
150 pid = strtol(dirent.d_name, &end, 10); 130}
151 if (*end)
152 continue;
153 131
154 /* already have tgid; jut want to update the comm */ 132static int perf_event__synthesize_fork(struct perf_tool *tool,
155 (void) perf_event__get_comm_tgid(pid, event->comm.comm, 133 union perf_event *event, pid_t pid,
156 sizeof(event->comm.comm)); 134 pid_t tgid, perf_event__handler_t process,
135 struct machine *machine)
136{
137 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
157 138
158 size = strlen(event->comm.comm) + 1; 139 /* this is really a clone event but we use fork to synthesize it */
159 size = PERF_ALIGN(size, sizeof(u64)); 140 event->fork.ppid = tgid;
160 memset(event->comm.comm + size, 0, machine->id_hdr_size); 141 event->fork.ptid = tgid;
161 event->comm.header.size = (sizeof(event->comm) - 142 event->fork.pid = tgid;
162 (sizeof(event->comm.comm) - size) + 143 event->fork.tid = pid;
163 machine->id_hdr_size); 144 event->fork.header.type = PERF_RECORD_FORK;
164 145
165 event->comm.tid = pid; 146 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
166 147
167 if (process(tool, event, &synth_sample, machine) != 0) { 148 if (process(tool, event, &synth_sample, machine) != 0)
168 tgid = -1; 149 return -1;
169 break;
170 }
171 }
172 150
173 closedir(tasks); 151 return 0;
174out:
175 return tgid;
176} 152}
177 153
178int perf_event__synthesize_mmap_events(struct perf_tool *tool, 154int perf_event__synthesize_mmap_events(struct perf_tool *tool,
@@ -324,17 +300,71 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
324 300
325static int __event__synthesize_thread(union perf_event *comm_event, 301static int __event__synthesize_thread(union perf_event *comm_event,
326 union perf_event *mmap_event, 302 union perf_event *mmap_event,
303 union perf_event *fork_event,
327 pid_t pid, int full, 304 pid_t pid, int full,
328 perf_event__handler_t process, 305 perf_event__handler_t process,
329 struct perf_tool *tool, 306 struct perf_tool *tool,
330 struct machine *machine, bool mmap_data) 307 struct machine *machine, bool mmap_data)
331{ 308{
332 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, 309 char filename[PATH_MAX];
310 DIR *tasks;
311 struct dirent dirent, *next;
312 pid_t tgid;
313
314 /* special case: only send one comm event using passed in pid */
315 if (!full) {
316 tgid = perf_event__synthesize_comm(tool, comm_event, pid,
317 process, machine);
318
319 if (tgid == -1)
320 return -1;
321
322 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
323 process, machine, mmap_data);
324 }
325
326 if (machine__is_default_guest(machine))
327 return 0;
328
329 snprintf(filename, sizeof(filename), "%s/proc/%d/task",
330 machine->root_dir, pid);
331
332 tasks = opendir(filename);
333 if (tasks == NULL) {
334 pr_debug("couldn't open %s\n", filename);
335 return 0;
336 }
337
338 while (!readdir_r(tasks, &dirent, &next) && next) {
339 char *end;
340 int rc = 0;
341 pid_t _pid;
342
343 _pid = strtol(dirent.d_name, &end, 10);
344 if (*end)
345 continue;
346
347 tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
348 process, machine);
349 if (tgid == -1)
350 return -1;
351
352 if (_pid == pid) {
353 /* process the parent's maps too */
354 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
355 process, machine, mmap_data);
356 } else {
357 /* only fork the tid's map, to save time */
358 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
333 process, machine); 359 process, machine);
334 if (tgid == -1) 360 }
335 return -1; 361
336 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 362 if (rc)
337 process, machine, mmap_data); 363 return rc;
364 }
365
366 closedir(tasks);
367 return 0;
338} 368}
339 369
340int perf_event__synthesize_thread_map(struct perf_tool *tool, 370int perf_event__synthesize_thread_map(struct perf_tool *tool,
@@ -343,7 +373,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
343 struct machine *machine, 373 struct machine *machine,
344 bool mmap_data) 374 bool mmap_data)
345{ 375{
346 union perf_event *comm_event, *mmap_event; 376 union perf_event *comm_event, *mmap_event, *fork_event;
347 int err = -1, thread, j; 377 int err = -1, thread, j;
348 378
349 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 379 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -354,9 +384,14 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
354 if (mmap_event == NULL) 384 if (mmap_event == NULL)
355 goto out_free_comm; 385 goto out_free_comm;
356 386
387 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
388 if (fork_event == NULL)
389 goto out_free_mmap;
390
357 err = 0; 391 err = 0;
358 for (thread = 0; thread < threads->nr; ++thread) { 392 for (thread = 0; thread < threads->nr; ++thread) {
359 if (__event__synthesize_thread(comm_event, mmap_event, 393 if (__event__synthesize_thread(comm_event, mmap_event,
394 fork_event,
360 threads->map[thread], 0, 395 threads->map[thread], 0,
361 process, tool, machine, 396 process, tool, machine,
362 mmap_data)) { 397 mmap_data)) {
@@ -382,6 +417,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
382 /* if not, generate events for it */ 417 /* if not, generate events for it */
383 if (need_leader && 418 if (need_leader &&
384 __event__synthesize_thread(comm_event, mmap_event, 419 __event__synthesize_thread(comm_event, mmap_event,
420 fork_event,
385 comm_event->comm.pid, 0, 421 comm_event->comm.pid, 0,
386 process, tool, machine, 422 process, tool, machine,
387 mmap_data)) { 423 mmap_data)) {
@@ -390,6 +426,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
390 } 426 }
391 } 427 }
392 } 428 }
429 free(fork_event);
430out_free_mmap:
393 free(mmap_event); 431 free(mmap_event);
394out_free_comm: 432out_free_comm:
395 free(comm_event); 433 free(comm_event);
@@ -404,7 +442,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
404 DIR *proc; 442 DIR *proc;
405 char proc_path[PATH_MAX]; 443 char proc_path[PATH_MAX];
406 struct dirent dirent, *next; 444 struct dirent dirent, *next;
407 union perf_event *comm_event, *mmap_event; 445 union perf_event *comm_event, *mmap_event, *fork_event;
408 int err = -1; 446 int err = -1;
409 447
410 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); 448 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -415,6 +453,10 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
415 if (mmap_event == NULL) 453 if (mmap_event == NULL)
416 goto out_free_comm; 454 goto out_free_comm;
417 455
456 fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
457 if (fork_event == NULL)
458 goto out_free_mmap;
459
418 if (machine__is_default_guest(machine)) 460 if (machine__is_default_guest(machine))
419 return 0; 461 return 0;
420 462
@@ -422,7 +464,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
422 proc = opendir(proc_path); 464 proc = opendir(proc_path);
423 465
424 if (proc == NULL) 466 if (proc == NULL)
425 goto out_free_mmap; 467 goto out_free_fork;
426 468
427 while (!readdir_r(proc, &dirent, &next) && next) { 469 while (!readdir_r(proc, &dirent, &next) && next) {
428 char *end; 470 char *end;
@@ -434,12 +476,14 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
434 * We may race with exiting thread, so don't stop just because 476 * We may race with exiting thread, so don't stop just because
435 * one thread couldn't be synthesized. 477 * one thread couldn't be synthesized.
436 */ 478 */
437 __event__synthesize_thread(comm_event, mmap_event, pid, 1, 479 __event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
438 process, tool, machine, mmap_data); 480 1, process, tool, machine, mmap_data);
439 } 481 }
440 482
441 err = 0; 483 err = 0;
442 closedir(proc); 484 closedir(proc);
485out_free_fork:
486 free(fork_event);
443out_free_mmap: 487out_free_mmap:
444 free(mmap_event); 488 free(mmap_event);
445out_free_comm: 489out_free_comm: