perf tools: Add time argument on COMM setting
This way we can later delimit a lifecycle for the COMM and map a hist to a precise COMM:timeslice couple. PERF_RECORD_COMM and PERF_RECORD_FORK events that don't have PERF_SAMPLE_TIME samples can only send 0 value as a timestamp and thus should overwrite any previous COMM on a given thread because there is no sensible way to keep track of all the comms lifecycles in a thread without time informations. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Tested-by: Jiri Olsa <jolsa@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-6tyow99vgmmtt9qwr2u2lqd7@git.kernel.org [ Made it cope with PERF_RECORD_MMAP2 ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
b9c5143a01
commit
162f0befda
@@ -512,18 +512,18 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
|
||||
|
||||
int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_comm_event(machine, event);
|
||||
return machine__process_comm_event(machine, event, sample);
|
||||
}
|
||||
|
||||
int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_lost_event(machine, event);
|
||||
return machine__process_lost_event(machine, event, sample);
|
||||
}
|
||||
|
||||
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
|
||||
@@ -546,18 +546,18 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
|
||||
|
||||
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_mmap_event(machine, event);
|
||||
return machine__process_mmap_event(machine, event, sample);
|
||||
}
|
||||
|
||||
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_mmap2_event(machine, event);
|
||||
return machine__process_mmap2_event(machine, event, sample);
|
||||
}
|
||||
|
||||
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
|
||||
@@ -569,18 +569,18 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
|
||||
|
||||
int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_fork_event(machine, event);
|
||||
return machine__process_fork_event(machine, event, sample);
|
||||
}
|
||||
|
||||
int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_exit_event(machine, event);
|
||||
return machine__process_exit_event(machine, event, sample);
|
||||
}
|
||||
|
||||
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
|
||||
@@ -611,10 +611,10 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
|
||||
|
||||
int perf_event__process(struct perf_tool *tool __maybe_unused,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
{
|
||||
return machine__process_event(machine, event);
|
||||
return machine__process_event(machine, event, sample);
|
||||
}
|
||||
|
||||
void thread__find_addr_map(struct thread *self,
|
||||
|
@@ -40,7 +40,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(comm, sizeof(comm), "[guest/%d]", pid);
|
||||
thread__set_comm(thread, comm);
|
||||
thread__set_comm(thread, comm, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -331,7 +331,8 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid)
|
||||
return __machine__findnew_thread(machine, 0, tid, false);
|
||||
}
|
||||
|
||||
int machine__process_comm_event(struct machine *machine, union perf_event *event)
|
||||
int machine__process_comm_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample)
|
||||
{
|
||||
struct thread *thread = machine__findnew_thread(machine,
|
||||
event->comm.pid,
|
||||
@@ -340,7 +341,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
|
||||
if (dump_trace)
|
||||
perf_event__fprintf_comm(event, stdout);
|
||||
|
||||
if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
|
||||
if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
|
||||
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -349,7 +350,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
|
||||
}
|
||||
|
||||
int machine__process_lost_event(struct machine *machine __maybe_unused,
|
||||
union perf_event *event)
|
||||
union perf_event *event, struct perf_sample *sample __maybe_unused)
|
||||
{
|
||||
dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
|
||||
event->lost.id, event->lost.lost);
|
||||
@@ -984,7 +985,8 @@ out_problem:
|
||||
}
|
||||
|
||||
int machine__process_mmap2_event(struct machine *machine,
|
||||
union perf_event *event)
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused)
|
||||
{
|
||||
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
||||
struct thread *thread;
|
||||
@@ -1031,7 +1033,8 @@ out_problem:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int machine__process_mmap_event(struct machine *machine, union perf_event *event)
|
||||
int machine__process_mmap_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused)
|
||||
{
|
||||
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
||||
struct thread *thread;
|
||||
@@ -1088,7 +1091,8 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)
|
||||
list_add_tail(&th->node, &machine->dead_threads);
|
||||
}
|
||||
|
||||
int machine__process_fork_event(struct machine *machine, union perf_event *event)
|
||||
int machine__process_fork_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample)
|
||||
{
|
||||
struct thread *thread = machine__find_thread(machine, event->fork.tid);
|
||||
struct thread *parent = machine__findnew_thread(machine,
|
||||
@@ -1105,7 +1109,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
|
||||
perf_event__fprintf_task(event, stdout);
|
||||
|
||||
if (thread == NULL || parent == NULL ||
|
||||
thread__fork(thread, parent) < 0) {
|
||||
thread__fork(thread, parent, sample->time) < 0) {
|
||||
dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1113,8 +1117,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
|
||||
return 0;
|
||||
}
|
||||
|
||||
int machine__process_exit_event(struct machine *machine __maybe_unused,
|
||||
union perf_event *event)
|
||||
int machine__process_exit_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused)
|
||||
{
|
||||
struct thread *thread = machine__find_thread(machine, event->fork.tid);
|
||||
|
||||
@@ -1127,23 +1131,24 @@ int machine__process_exit_event(struct machine *machine __maybe_unused,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int machine__process_event(struct machine *machine, union perf_event *event)
|
||||
int machine__process_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (event->header.type) {
|
||||
case PERF_RECORD_COMM:
|
||||
ret = machine__process_comm_event(machine, event); break;
|
||||
ret = machine__process_comm_event(machine, event, sample); break;
|
||||
case PERF_RECORD_MMAP:
|
||||
ret = machine__process_mmap_event(machine, event); break;
|
||||
ret = machine__process_mmap_event(machine, event, sample); break;
|
||||
case PERF_RECORD_MMAP2:
|
||||
ret = machine__process_mmap2_event(machine, event); break;
|
||||
ret = machine__process_mmap2_event(machine, event, sample); break;
|
||||
case PERF_RECORD_FORK:
|
||||
ret = machine__process_fork_event(machine, event); break;
|
||||
ret = machine__process_fork_event(machine, event, sample); break;
|
||||
case PERF_RECORD_EXIT:
|
||||
ret = machine__process_exit_event(machine, event); break;
|
||||
ret = machine__process_exit_event(machine, event, sample); break;
|
||||
case PERF_RECORD_LOST:
|
||||
ret = machine__process_lost_event(machine, event); break;
|
||||
ret = machine__process_lost_event(machine, event, sample); break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
|
@@ -40,13 +40,20 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
|
||||
|
||||
struct thread *machine__find_thread(struct machine *machine, pid_t tid);
|
||||
|
||||
int machine__process_comm_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_exit_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_fork_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_lost_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_mmap_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_mmap2_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_event(struct machine *machine, union perf_event *event);
|
||||
int machine__process_comm_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
int machine__process_exit_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
int machine__process_fork_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
int machine__process_lost_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
int machine__process_mmap_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
int machine__process_event(struct machine *machine, union perf_event *event,
|
||||
struct perf_sample *sample);
|
||||
|
||||
typedef void (*machine__process_t)(struct machine *machine, void *data);
|
||||
|
||||
|
@@ -1100,7 +1100,7 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
|
||||
{
|
||||
struct thread *thread = perf_session__findnew(self, 0);
|
||||
|
||||
if (thread == NULL || thread__set_comm(thread, "swapper")) {
|
||||
if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
|
||||
pr_err("problem inserting idle task.\n");
|
||||
thread = NULL;
|
||||
}
|
||||
|
@@ -31,7 +31,8 @@ void thread__delete(struct thread *thread)
|
||||
free(thread);
|
||||
}
|
||||
|
||||
int thread__set_comm(struct thread *thread, const char *comm)
|
||||
int thread__set_comm(struct thread *thread, const char *comm,
|
||||
u64 timestamp __maybe_unused)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -73,7 +74,8 @@ 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)
|
||||
int thread__fork(struct thread *thread, struct thread *parent,
|
||||
u64 timestamp __maybe_unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@@ -33,11 +33,11 @@ static inline void thread__exited(struct thread *thread)
|
||||
thread->dead = true;
|
||||
}
|
||||
|
||||
int thread__set_comm(struct thread *self, const char *comm);
|
||||
int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
|
||||
int thread__comm_len(struct thread *self);
|
||||
const char *thread__comm_str(const struct thread *thread);
|
||||
void thread__insert_map(struct thread *self, struct map *map);
|
||||
int thread__fork(struct thread *self, struct thread *parent);
|
||||
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
|
||||
size_t thread__fprintf(struct thread *thread, FILE *fp);
|
||||
|
||||
static inline struct map *thread__find_map(struct thread *self,
|
||||
|
Reference in New Issue
Block a user