perf tools: Identify which comms are from exec
authorAdrian Hunter <adrian.hunter@intel.com>
Thu, 31 Jul 2014 06:00:44 +0000 (09:00 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 13 Aug 2014 22:23:08 +0000 (19:23 -0300)
For grouping together all the data from a single execution, which is
needed for pairing calls and returns e.g. any outstanding calls when a
process exec's will never return.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1406786474-9306-2-git-send-email-adrian.hunter@intel.com
[ Remove testing if comm->exec is false before setting it to true ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/comm.c
tools/perf/util/comm.h
tools/perf/util/machine.c
tools/perf/util/thread.c
tools/perf/util/thread.h

index f9e777629e21cd1780fad2dc891f4c24d637787e..b2bb59df65e10c10cfe6dd1aacb495d4804a6a4f 100644 (file)
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
        return new;
 }
 
-struct comm *comm__new(const char *str, u64 timestamp)
+struct comm *comm__new(const char *str, u64 timestamp, bool exec)
 {
        struct comm *comm = zalloc(sizeof(*comm));
 
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
                return NULL;
 
        comm->start = timestamp;
+       comm->exec = exec;
 
        comm->comm_str = comm_str__findnew(str, &comm_str_root);
        if (!comm->comm_str) {
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
        return comm;
 }
 
-int comm__override(struct comm *comm, const char *str, u64 timestamp)
+int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
 {
        struct comm_str *new, *old = comm->comm_str;
 
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp)
        comm_str__put(old);
        comm->comm_str = new;
        comm->start = timestamp;
+       if (exec)
+               comm->exec = true;
 
        return 0;
 }
index fac5bd51befc4c4a2b6aafe5cd21220829334673..51c10ab257f8b2b079d120075cc7effb45bd73e3 100644 (file)
@@ -11,11 +11,13 @@ struct comm {
        struct comm_str *comm_str;
        u64 start;
        struct list_head list;
+       bool exec;
 };
 
 void comm__free(struct comm *comm);
-struct comm *comm__new(const char *str, u64 timestamp);
+struct comm *comm__new(const char *str, u64 timestamp, bool exec);
 const char *comm__str(const struct comm *comm);
-int comm__override(struct comm *comm, const char *str, u64 timestamp);
+int comm__override(struct comm *comm, const char *str, u64 timestamp,
+                  bool exec);
 
 #endif  /* __PERF_COMM_H */
index 16bba9fff2c87b68ae55960568c58d1469665400..ea3e09f6a9c62562d0146cae135e5fe9c8a9a865 100644 (file)
@@ -404,11 +404,13 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
        struct thread *thread = machine__findnew_thread(machine,
                                                        event->comm.pid,
                                                        event->comm.tid);
+       bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
 
        if (dump_trace)
                perf_event__fprintf_comm(event, stdout);
 
-       if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
+       if (thread == NULL ||
+           __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
                dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
                return -1;
        }
index 12c7a253a63ceecfa30f93d7f52f4361a5842c44..a9df7f2c6dc934210e83755155e843b72af68011 100644 (file)
@@ -42,7 +42,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
                        goto err_thread;
 
                snprintf(comm_str, 32, ":%d", tid);
-               comm = comm__new(comm_str, 0);
+               comm = comm__new(comm_str, 0, false);
                free(comm_str);
                if (!comm)
                        goto err_thread;
@@ -81,19 +81,33 @@ struct comm *thread__comm(const struct thread *thread)
        return list_first_entry(&thread->comm_list, struct comm, list);
 }
 
+struct comm *thread__exec_comm(const struct thread *thread)
+{
+       struct comm *comm, *last = NULL;
+
+       list_for_each_entry(comm, &thread->comm_list, list) {
+               if (comm->exec)
+                       return comm;
+               last = comm;
+       }
+
+       return last;
+}
+
 /* CHECKME: time should always be 0 if event aren't ordered */
-int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
+int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
+                      bool exec)
 {
        struct comm *new, *curr = thread__comm(thread);
        int err;
 
        /* Override latest entry if it had no specific time coverage */
-       if (!curr->start) {
-               err = comm__override(curr, str, timestamp);
+       if (!curr->start && !curr->exec) {
+               err = comm__override(curr, str, timestamp, exec);
                if (err)
                        return err;
        } else {
-               new = comm__new(str, timestamp);
+               new = comm__new(str, timestamp, exec);
                if (!new)
                        return -ENOMEM;
                list_add(&new->list, &thread->comm_list);
index 716b7723cce27e03edf2d9a3d61fafc5b7fe1659..8c75fa774706352d22e2c4aa3390fb3350c89195 100644 (file)
@@ -38,9 +38,17 @@ static inline void thread__exited(struct thread *thread)
        thread->dead = true;
 }
 
-int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
+int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
+                      bool exec);
+static inline int thread__set_comm(struct thread *thread, const char *comm,
+                                  u64 timestamp)
+{
+       return __thread__set_comm(thread, comm, timestamp, false);
+}
+
 int thread__comm_len(struct thread *thread);
 struct comm *thread__comm(const struct thread *thread);
+struct comm *thread__exec_comm(const struct thread *thread);
 const char *thread__comm_str(const struct thread *thread);
 void thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);