When multi-file data storage is enabled, it processes all task, comm and mmap events first and then goes to the sample events. So all it sees is the last comm of a thread although it has information at the time of sample.
Sort thread's comm by time so that it can find appropriate comm at the sample time. The thread__comm_time() will mostly work even if PERF_SAMPLE_TIME bit is off since in that case, sample->time will be -1 so it'll take the last comm anyway. Cc: Frederic Weisbecker <fweis...@gmail.com> Signed-off-by: Namhyung Kim <namhy...@kernel.org> --- tools/perf/util/thread.c | 34 +++++++++++++++++++++++++++++++++- tools/perf/util/thread.h | 2 ++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 9ebc8b1f9be5..083fa0fcf316 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -103,6 +103,22 @@ struct comm *thread__exec_comm(const struct thread *thread) return last; } +struct comm *thread__comm_time(const struct thread *thread, u64 timestamp) +{ + struct comm *comm; + + list_for_each_entry(comm, &thread->comm_list, list) { + if (timestamp >= comm->start) + return comm; + } + + if (list_empty(&thread->comm_list)) + return NULL; + + return list_last_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, bool exec) { @@ -118,7 +134,13 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, new = comm__new(str, timestamp, exec); if (!new) return -ENOMEM; - list_add(&new->list, &thread->comm_list); + + /* sort by time */ + list_for_each_entry(curr, &thread->comm_list, list) { + if (timestamp >= curr->start) + break; + } + list_add_tail(&new->list, &curr->list); if (exec) unwind__flush_access(thread); @@ -139,6 +161,16 @@ const char *thread__comm_str(const struct thread *thread) return comm__str(comm); } +const char *thread__comm_time_str(const struct thread *thread, u64 timestamp) +{ + const struct comm *comm = thread__comm_time(thread, timestamp); + + 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) { diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 160fd066a7d1..0b6dcd70bc8b 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -53,7 +53,9 @@ static inline int thread__set_comm(struct thread *thread, const char *comm, int thread__comm_len(struct thread *thread); struct comm *thread__comm(const struct thread *thread); struct comm *thread__exec_comm(const struct thread *thread); +struct comm *thread__comm_time(const struct thread *thread, u64 timestamp); const char *thread__comm_str(const struct thread *thread); +const char *thread__comm_time_str(const struct thread *thread, u64 timestamp); void thread__insert_map(struct thread *thread, struct map *map); int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); size_t thread__fprintf(struct thread *thread, FILE *fp); -- 2.1.3 -- 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/