From 1902efe7f626fdebe1520f5ff11f1309ec506708 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 11 Sep 2013 16:56:44 +0200 Subject: perf tools: Add new COMM infrastructure This new COMM infrastructure provides two features: 1) It keeps track of all comms lifecycle for a given thread. This way we can associate a timeframe to any thread COMM, as long as PERF_SAMPLE_TIME samples are joined to COMM and fork events. As a result we should have more precise COMM sorted hists with seperated entries for pre and post exec time after a fork. 2) It also makes sure that a given COMM string is not duplicated but rather shared among the threads that refer to it. This way the threads COMM can be compared against pointer values from the sort infrastructure. Signed-off-by: Frederic Weisbecker Tested-by: Jiri Olsa Cc: Jiri Olsa Cc: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-hwjf70b2wve9m2kosxiq8bb3@git.kernel.org [ Rename some accessor functions ] Signed-off-by: Namhyung Kim [ Use __ as separator for class__method for private comm_str methods ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.c | 92 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 24 deletions(-) (limited to 'tools/perf/util/thread.c') diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 0ea73fe..15c53c2 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -6,9 +6,12 @@ #include "thread.h" #include "util.h" #include "debug.h" +#include "comm.h" struct thread *thread__new(pid_t pid, pid_t tid) { + char *comm_str; + struct comm *comm; struct thread *thread = zalloc(sizeof(*thread)); if (thread != NULL) { @@ -16,47 +19,88 @@ struct thread *thread__new(pid_t pid, pid_t tid) thread->pid_ = pid; thread->tid = tid; thread->ppid = -1; - thread->comm = malloc(32); - if (thread->comm) - snprintf(thread->comm, 32, ":%d", thread->tid); + INIT_LIST_HEAD(&thread->comm_list); + + comm_str = malloc(32); + if (!comm_str) + goto err_thread; + + snprintf(comm_str, 32, ":%d", tid); + comm = comm__new(comm_str, 0); + free(comm_str); + if (!comm) + goto err_thread; + + list_add(&comm->list, &thread->comm_list); } return thread; + +err_thread: + free(thread); + return NULL; } void thread__delete(struct thread *thread) { + struct comm *comm, *tmp; + map_groups__exit(&thread->mg); - free(thread->comm); + list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { + list_del(&comm->list); + comm__free(comm); + } + free(thread); } -int thread__set_comm(struct thread *thread, const char *comm, - u64 timestamp __maybe_unused) +static struct comm *thread__comm(const struct thread *thread) { - int err; + if (list_empty(&thread->comm_list)) + return NULL; - if (thread->comm) - free(thread->comm); - thread->comm = strdup(comm); - err = thread->comm == NULL ? -ENOMEM : 0; - if (!err) { - thread->comm_set = true; + return list_first_entry(&thread->comm_list, struct comm, list); +} + +/* CHECKME: time should always be 0 if event aren't ordered */ +int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) +{ + struct comm *new, *curr = thread__comm(thread); + + /* Override latest entry if it had no specific time coverage */ + if (!curr->start) { + list_del(&curr->list); + comm__free(curr); } - return err; + + new = comm__new(str, timestamp); + if (!new) + return -ENOMEM; + + list_add(&new->list, &thread->comm_list); + thread->comm_set = true; + + return 0; } const char *thread__comm_str(const struct thread *thread) { - return thread->comm; + const struct comm *comm = thread__comm(thread); + + if (!comm) + return NULL; + + return comm__str(comm); } +/* CHECKME: it should probably better return the max comm len from its comm list */ int thread__comm_len(struct thread *thread) { if (!thread->comm_len) { - if (!thread->comm) + const char *comm = thread__comm_str(thread); + if (!comm) return 0; - thread->comm_len = strlen(thread->comm); + thread->comm_len = strlen(comm); } return thread->comm_len; @@ -74,17 +118,17 @@ void thread__insert_map(struct thread *thread, struct map *map) map_groups__insert(&thread->mg, map); } -int thread__fork(struct thread *thread, struct thread *parent, - u64 timestamp __maybe_unused) +int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) { - int i; + int i, err; if (parent->comm_set) { - if (thread->comm) - free(thread->comm); - thread->comm = strdup(parent->comm); - if (!thread->comm) + const char *comm = thread__comm_str(parent); + if (!comm) return -ENOMEM; + err = thread__set_comm(thread, comm, timestamp); + if (!err) + return err; thread->comm_set = true; } -- cgit v1.1