diff options
-rw-r--r-- | include/uapi/linux/perf_event.h | 2 | ||||
-rw-r--r-- | tools/include/uapi/linux/perf_event.h | 2 | ||||
-rw-r--r-- | tools/perf/util/event.c | 1 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 19 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 13 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 2 |
6 files changed, 29 insertions, 10 deletions
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index f35eb72739c0..9de8780ac8d9 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h | |||
@@ -646,10 +646,12 @@ struct perf_event_mmap_page { | |||
646 | * | 646 | * |
647 | * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events | 647 | * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events |
648 | * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event | 648 | * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event |
649 | * PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal) | ||
649 | * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events | 650 | * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events |
650 | */ | 651 | */ |
651 | #define PERF_RECORD_MISC_MMAP_DATA (1 << 13) | 652 | #define PERF_RECORD_MISC_MMAP_DATA (1 << 13) |
652 | #define PERF_RECORD_MISC_COMM_EXEC (1 << 13) | 653 | #define PERF_RECORD_MISC_COMM_EXEC (1 << 13) |
654 | #define PERF_RECORD_MISC_FORK_EXEC (1 << 13) | ||
653 | #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) | 655 | #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) |
654 | /* | 656 | /* |
655 | * These PERF_RECORD_MISC_* flags below are safely reused | 657 | * These PERF_RECORD_MISC_* flags below are safely reused |
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index f35eb72739c0..9de8780ac8d9 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h | |||
@@ -646,10 +646,12 @@ struct perf_event_mmap_page { | |||
646 | * | 646 | * |
647 | * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events | 647 | * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events |
648 | * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event | 648 | * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event |
649 | * PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal) | ||
649 | * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events | 650 | * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events |
650 | */ | 651 | */ |
651 | #define PERF_RECORD_MISC_MMAP_DATA (1 << 13) | 652 | #define PERF_RECORD_MISC_MMAP_DATA (1 << 13) |
652 | #define PERF_RECORD_MISC_COMM_EXEC (1 << 13) | 653 | #define PERF_RECORD_MISC_COMM_EXEC (1 << 13) |
654 | #define PERF_RECORD_MISC_FORK_EXEC (1 << 13) | ||
653 | #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) | 655 | #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) |
654 | /* | 656 | /* |
655 | * These PERF_RECORD_MISC_* flags below are safely reused | 657 | * These PERF_RECORD_MISC_* flags below are safely reused |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index bc646185f8d9..e9c108a6b1c3 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -308,6 +308,7 @@ static int perf_event__synthesize_fork(struct perf_tool *tool, | |||
308 | event->fork.pid = tgid; | 308 | event->fork.pid = tgid; |
309 | event->fork.tid = pid; | 309 | event->fork.tid = pid; |
310 | event->fork.header.type = PERF_RECORD_FORK; | 310 | event->fork.header.type = PERF_RECORD_FORK; |
311 | event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC; | ||
311 | 312 | ||
312 | event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); | 313 | event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); |
313 | 314 | ||
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 8ee8ab39d8ac..8f36ce813bc5 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1708,6 +1708,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event | |||
1708 | struct thread *parent = machine__findnew_thread(machine, | 1708 | struct thread *parent = machine__findnew_thread(machine, |
1709 | event->fork.ppid, | 1709 | event->fork.ppid, |
1710 | event->fork.ptid); | 1710 | event->fork.ptid); |
1711 | bool do_maps_clone = true; | ||
1711 | int err = 0; | 1712 | int err = 0; |
1712 | 1713 | ||
1713 | if (dump_trace) | 1714 | if (dump_trace) |
@@ -1736,9 +1737,25 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event | |||
1736 | 1737 | ||
1737 | thread = machine__findnew_thread(machine, event->fork.pid, | 1738 | thread = machine__findnew_thread(machine, event->fork.pid, |
1738 | event->fork.tid); | 1739 | event->fork.tid); |
1740 | /* | ||
1741 | * When synthesizing FORK events, we are trying to create thread | ||
1742 | * objects for the already running tasks on the machine. | ||
1743 | * | ||
1744 | * Normally, for a kernel FORK event, we want to clone the parent's | ||
1745 | * maps because that is what the kernel just did. | ||
1746 | * | ||
1747 | * But when synthesizing, this should not be done. If we do, we end up | ||
1748 | * with overlapping maps as we process the sythesized MMAP2 events that | ||
1749 | * get delivered shortly thereafter. | ||
1750 | * | ||
1751 | * Use the FORK event misc flags in an internal way to signal this | ||
1752 | * situation, so we can elide the map clone when appropriate. | ||
1753 | */ | ||
1754 | if (event->fork.header.misc & PERF_RECORD_MISC_FORK_EXEC) | ||
1755 | do_maps_clone = false; | ||
1739 | 1756 | ||
1740 | if (thread == NULL || parent == NULL || | 1757 | if (thread == NULL || parent == NULL || |
1741 | thread__fork(thread, parent, sample->time) < 0) { | 1758 | thread__fork(thread, parent, sample->time, do_maps_clone) < 0) { |
1742 | dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); | 1759 | dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); |
1743 | err = -1; | 1760 | err = -1; |
1744 | } | 1761 | } |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 2048d393ece6..3d9ed7d0e281 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -330,7 +330,8 @@ static int thread__prepare_access(struct thread *thread) | |||
330 | } | 330 | } |
331 | 331 | ||
332 | static int thread__clone_map_groups(struct thread *thread, | 332 | static int thread__clone_map_groups(struct thread *thread, |
333 | struct thread *parent) | 333 | struct thread *parent, |
334 | bool do_maps_clone) | ||
334 | { | 335 | { |
335 | /* This is new thread, we share map groups for process. */ | 336 | /* This is new thread, we share map groups for process. */ |
336 | if (thread->pid_ == parent->pid_) | 337 | if (thread->pid_ == parent->pid_) |
@@ -341,15 +342,11 @@ static int thread__clone_map_groups(struct thread *thread, | |||
341 | thread->pid_, thread->tid, parent->pid_, parent->tid); | 342 | thread->pid_, thread->tid, parent->pid_, parent->tid); |
342 | return 0; | 343 | return 0; |
343 | } | 344 | } |
344 | |||
345 | /* But this one is new process, copy maps. */ | 345 | /* But this one is new process, copy maps. */ |
346 | if (map_groups__clone(thread, parent->mg) < 0) | 346 | return do_maps_clone ? map_groups__clone(thread, parent->mg) : 0; |
347 | return -ENOMEM; | ||
348 | |||
349 | return 0; | ||
350 | } | 347 | } |
351 | 348 | ||
352 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) | 349 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone) |
353 | { | 350 | { |
354 | if (parent->comm_set) { | 351 | if (parent->comm_set) { |
355 | const char *comm = thread__comm_str(parent); | 352 | const char *comm = thread__comm_str(parent); |
@@ -362,7 +359,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) | |||
362 | } | 359 | } |
363 | 360 | ||
364 | thread->ppid = parent->tid; | 361 | thread->ppid = parent->tid; |
365 | return thread__clone_map_groups(thread, parent); | 362 | return thread__clone_map_groups(thread, parent, do_maps_clone); |
366 | } | 363 | } |
367 | 364 | ||
368 | void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, | 365 | void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 36c09a9904e6..30e2b4c165fe 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -89,7 +89,7 @@ struct comm *thread__comm(const struct thread *thread); | |||
89 | struct comm *thread__exec_comm(const struct thread *thread); | 89 | struct comm *thread__exec_comm(const struct thread *thread); |
90 | const char *thread__comm_str(const struct thread *thread); | 90 | const char *thread__comm_str(const struct thread *thread); |
91 | int thread__insert_map(struct thread *thread, struct map *map); | 91 | int thread__insert_map(struct thread *thread, struct map *map); |
92 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); | 92 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone); |
93 | size_t thread__fprintf(struct thread *thread, FILE *fp); | 93 | size_t thread__fprintf(struct thread *thread, FILE *fp); |
94 | 94 | ||
95 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread); | 95 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread); |