summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/perf_event.h2
-rw-r--r--tools/include/uapi/linux/perf_event.h2
-rw-r--r--tools/perf/util/event.c1
-rw-r--r--tools/perf/util/machine.c19
-rw-r--r--tools/perf/util/thread.c13
-rw-r--r--tools/perf/util/thread.h2
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
332static int thread__clone_map_groups(struct thread *thread, 332static 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
352int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) 349int 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
368void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, 365void 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);
89struct comm *thread__exec_comm(const struct thread *thread); 89struct comm *thread__exec_comm(const struct thread *thread);
90const char *thread__comm_str(const struct thread *thread); 90const char *thread__comm_str(const struct thread *thread);
91int thread__insert_map(struct thread *thread, struct map *map); 91int thread__insert_map(struct thread *thread, struct map *map);
92int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 92int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone);
93size_t thread__fprintf(struct thread *thread, FILE *fp); 93size_t thread__fprintf(struct thread *thread, FILE *fp);
94 94
95struct thread *thread__main_thread(struct machine *machine, struct thread *thread); 95struct thread *thread__main_thread(struct machine *machine, struct thread *thread);