perf tools: Identify which comms are from exec
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>
This commit is contained in:
parent
a5563edfa1
commit
65de51f93e
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user