Commit-ID:  4aa5f4f7bb8bc41cba15bcd0d80c4fb085027d6b
Gitweb:     http://git.kernel.org/tip/4aa5f4f7bb8bc41cba15bcd0d80c4fb085027d6b
Author:     Arnaldo Carvalho de Melo <a...@redhat.com>
AuthorDate: Fri, 27 Feb 2015 19:52:10 -0300
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Mon, 2 Mar 2015 11:51:30 -0300

perf tools: Fix FORK after COMM when synthesizing records for pre-existing 
threads

In this commit:

  commit 363b785f3805a2632eb09a8b430842461c21a640
  Author: Don Zickus <dzic...@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.hun...@intel.com>
Cc: Borislav Petkov <b...@suse.de>
Cc: David Ahern <dsah...@gmail.com>
Cc: Don Zickus <dzic...@redhat.com>
Cc: Frederic Weisbecker <fweis...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Stephane Eranian <eran...@google.com>
Link: http://lkml.kernel.org/n/tip-h0emvymi2t3mw8dlqd6d6...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/util/event.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9e806d8..d5efa50 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)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to