aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2015-02-27 17:52:10 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-03-02 09:51:30 -0500
commit4aa5f4f7bb8bc41cba15bcd0d80c4fb085027d6b (patch)
treec9784c07fefab20f57a43201fa758d55ce11c4f9 /tools/perf/util/event.c
parent3b4331d9a4f2d99603c38bfcac79943b7c6c5439 (diff)
perf tools: Fix FORK after COMM when synthesizing records for pre-existing threads
In this commit: commit 363b785f3805a2632eb09a8b430842461c21a640 Author: Don Zickus <dzickus@redhat.com> Date: Fri Mar 14 10:43:44 2014 -0400 perf tools: Speed up thread map generation We ended up emitting PERF_RECORD_FORK events after their corresponding PERF_RECORD_COMM, so the code below will remove the "existing thread" and then recreates it, unnecessarily: [root@ssdandy ~]# perf probe -x ~/bin/perf -L machine__process_fork_event <machine__process_fork_event@/home/acme/git/linux/tools/perf/util/machine.c:0> 0 int machine__process_fork_event(struct machine *machine, union perf_event *event, struct perf_sample *sample) 2 { 3 struct thread *thread = machine__find_thread(machine, event->fork.pid, event->fork.tid); 6 struct thread *parent = machine__findnew_thread(machine, event->fork.ppid, event->fork.ptid); /* if a thread currently exists for the thread id remove it */ if (thread != NULL) 12 machine__remove_thread(machine, thread); 14 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); 16 if (dump_trace) 17 perf_event__fprintf_task(event, stdout); 19 if (thread == NULL || parent == NULL || 20 thread__fork(thread, parent, sample->time) < 0) { 21 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 22 return -1; } 25 return 0; 26 } [root@ssdandy ~]# perf probe -x ~/bin/perf fork_after_comm=machine__process_fork_event:12 Added new event: probe_perf:fork_after_comm (on machine__process_fork_event:12 in /home/acme/bin/perf) You can now use it in all perf tools, such as: perf record -e probe_perf:fork_after_comm -aR sleep 1 [root@ssdandy ~]# [root@ssdandy ~]# perf record -g -e probe_perf:* trace -o /tmp/bla ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.021 MB perf.data (30 samples) ] Terminated [root@ssdandy ~]# [root@ssdandy ~]# perf report --no-children --show-total-period --stdio # To display the perf.data header info, please use --header/--header-only options. # # Samples: 30 of event 'probe_perf:fork_after_comm' # Event count (approx.): 30 # # Overhead Period Command Shared Object Symbol # ........ ............ ....... ............. ............................... # 100.00% 30 trace trace [.] machine__process_fork_event | ---machine__process_fork_event __event__synthesize_thread.part.2 perf_event__synthesize_threads cmd_trace main __libc_start_main [root@ssdandy ~]# And Looking at 'perf report -D' output we see it: 0 0 0x8698 [0x30]: PERF_RECORD_COMM: auditd:703/707 0 0 0x86c8 [0x38]: PERF_RECORD_FORK(703:707):(703:703) Fix it by more closely mimicking how the kernel generates those records when a new fork happens, i.e. first a PERF_RECORD_FORK, then a PERF_RECORD_COMM. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Borislav Petkov <bp@suse.de> Cc: David Ahern <dsahern@gmail.com> Cc: Don Zickus <dzickus@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-h0emvymi2t3mw8dlqd6d6z73@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r--tools/perf/util/event.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9e806d855b04..d5efa5092ce6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -95,9 +95,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
95 return tgid; 95 return tgid;
96} 96}
97 97
98static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 98static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
99 union perf_event *event, pid_t pid,
100 perf_event__handler_t process,
101 struct machine *machine) 99 struct machine *machine)
102{ 100{
103 size_t size; 101 size_t size;
@@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
124 (sizeof(event->comm.comm) - size) + 122 (sizeof(event->comm.comm) - size) +
125 machine->id_hdr_size); 123 machine->id_hdr_size);
126 event->comm.tid = pid; 124 event->comm.tid = pid;
125out:
126 return tgid;
127}
128
129static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
130 union perf_event *event, pid_t pid,
131 perf_event__handler_t process,
132 struct machine *machine)
133{
134 pid_t tgid = perf_event__prepare_comm(event, pid, machine);
135
136 if (tgid == -1)
137 goto out;
127 138
128 if (process(tool, event, &synth_sample, machine) != 0) 139 if (process(tool, event, &synth_sample, machine) != 0)
129 return -1; 140 return -1;
@@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
139{ 150{
140 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 151 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
141 152
142 /* this is really a clone event but we use fork to synthesize it */
143 event->fork.ppid = tgid; 153 event->fork.ppid = tgid;
144 event->fork.ptid = tgid; 154 event->fork.ptid = tgid;
145 event->fork.pid = tgid; 155 event->fork.pid = tgid;
@@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event,
368 if (*end) 378 if (*end)
369 continue; 379 continue;
370 380
371 tgid = perf_event__synthesize_comm(tool, comm_event, _pid, 381 tgid = perf_event__prepare_comm(comm_event, _pid, machine);
372 process, machine);
373 if (tgid == -1) 382 if (tgid == -1)
374 return -1; 383 return -1;
375 384
385 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
386 process, machine) < 0)
387 return -1;
388 /*
389 * Send the prepared comm event
390 */
391 if (process(tool, comm_event, &synth_sample, machine) != 0)
392 return -1;
393
376 if (_pid == pid) { 394 if (_pid == pid) {
377 /* process the parent's maps too */ 395 /* process the parent's maps too */
378 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 396 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
379 process, machine, mmap_data); 397 process, machine, mmap_data);
380 } else {
381 /* only fork the tid's map, to save time */
382 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
383 process, machine);
384 } 398 }
385 399
386 if (rc) 400 if (rc)