summaryrefslogtreecommitdiff
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2015-02-27 19:52:10 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-03-02 11:51:30 -0300
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)
return tgid;
}
-static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
- union perf_event *event, pid_t pid,
- perf_event__handler_t process,
+static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
struct machine *machine)
{
size_t size;
@@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
(sizeof(event->comm.comm) - size) +
machine->id_hdr_size);
event->comm.tid = pid;
+out:
+ return tgid;
+}
+
+static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
+ union perf_event *event, pid_t pid,
+ perf_event__handler_t process,
+ struct machine *machine)
+{
+ pid_t tgid = perf_event__prepare_comm(event, pid, machine);
+
+ if (tgid == -1)
+ goto out;
if (process(tool, event, &synth_sample, machine) != 0)
return -1;
@@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
{
memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
- /* this is really a clone event but we use fork to synthesize it */
event->fork.ppid = tgid;
event->fork.ptid = tgid;
event->fork.pid = tgid;
@@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event,
if (*end)
continue;
- tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
- process, machine);
+ tgid = perf_event__prepare_comm(comm_event, _pid, machine);
if (tgid == -1)
return -1;
+ if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
+ process, machine) < 0)
+ return -1;
+ /*
+ * Send the prepared comm event
+ */
+ if (process(tool, comm_event, &synth_sample, machine) != 0)
+ return -1;
+
if (_pid == pid) {
/* process the parent's maps too */
rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
process, machine, mmap_data);
- } else {
- /* only fork the tid's map, to save time */
- rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
- process, machine);
}
if (rc)