diff mbox series

[04/12] trace-cmd analyze: Use sched_switch to find comm mappings

Message ID 20220324025726.1727204-5-rostedt@goodmis.org (mailing list archive)
State New, archived
Headers show
Series trace-cmd: Add trace-cmd analyze command | expand

Commit Message

Steven Rostedt March 24, 2022, 2:57 a.m. UTC
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

As the saved_cmdlines may miss a lot of comms, especially if the tracing
went for a while, to know what the comms mapping of PIDs are, use the
sched_switch event if it is present. If so, then update the task with the
comm and print that. This way we get more real names instead of just
"<...>".

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 tracecmd/trace-analyze.c | 62 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/tracecmd/trace-analyze.c b/tracecmd/trace-analyze.c
index 43e9ffa95687..dec705ce8e15 100644
--- a/tracecmd/trace-analyze.c
+++ b/tracecmd/trace-analyze.c
@@ -29,6 +29,10 @@  struct cpu_data {
 struct analysis_data {
 	unsigned long long	start_ts;
 	unsigned long long	last_ts;
+	struct tep_event	*switch_event;
+	struct tep_format_field	*prev_comm;
+	struct tep_format_field	*next_comm;
+	struct tep_format_field	*next_pid;
 	struct cpu_data		*cpu_data;
 	struct trace_hash	tasks;
 	int			nr_tasks;
@@ -39,6 +43,7 @@  struct analysis_data {
 struct task_item {
 	unsigned long long	runtime;
 	unsigned long long	start_ts;
+	char			*comm;
 	struct trace_hash_item	hash;
 	int			pid;
 };
@@ -253,11 +258,51 @@  static void update_first_pid(struct cpu_data *cpu_data)
 	cpu_data->start_ts = start_ts;
 }
 
+static void process_switch(struct analysis_data *data,
+			   struct tep_handle *tep, int pid,
+			   struct tep_record *record)
+{
+	struct cpu_data *cpu_data = &data->cpu_data[record->cpu];
+	struct task_cpu_item *cpu_task;
+	struct task_item *task;
+	const char *comm;
+
+	cpu_task = get_cpu_task(cpu_data, pid);
+	task = cpu_task->task;
+
+	/* Fill in missing comms */
+	if (pid && data->prev_comm && !task->comm) {
+		comm = (char *)(record->data + data->prev_comm->offset);
+		task->comm = strdup(comm);
+	}
+
+	if (data->next_pid) {
+		unsigned long long val;
+
+		tep_read_number_field(data->next_pid, record->data, &val);
+		pid = val;
+		cpu_task = get_cpu_task(cpu_data, pid);
+		task = cpu_task->task;
+
+		/* Fill in missing comms */
+		if (pid && data->next_comm && !task->comm) {
+			comm = (char *)(record->data + data->next_comm->offset);
+			task->comm = strdup(comm);
+		}
+	}
+}
+
+static bool match_type(int type, struct tep_event *event)
+{
+	return event && type == event->id;
+}
+
 static void process_cpu(struct analysis_data *data,
 			struct tep_handle *tep,
 			struct tep_record *record)
 {
 	struct cpu_data *cpu_data;
+	int type;
 	int pid;
 
 	pid = tep_data_pid(tep, record);
@@ -266,6 +311,10 @@  static void process_cpu(struct analysis_data *data,
 
 	cpu_data = get_cpu_data(data, record);
 	update_cpu_times(cpu_data, tep, pid, record);
+
+	type = tep_data_type(tep, record);
+	if (match_type(type, data->switch_event))
+		process_switch(data, tep, pid, record);
 }
 
 static int cmp_tasks(const void *A, const void *B)
@@ -374,7 +423,7 @@  static void print_cpu_data(struct tep_handle *tep, struct cpu_data *cpu_data)
 			printf("    ---------        --- \t     --------\n");
 		}
 		printf("%16s %8d\t",
-		       tep_data_comm_from_pid(tep, task->pid),
+		       task->comm ? : tep_data_comm_from_pid(tep, task->pid),
 		       task->pid);
 		print_time(cpu_tasks[i]->runtime, '_');
 		printf(" (%%%lld)\n", (task->runtime * 100) / total_time);
@@ -444,7 +493,7 @@  static void print_total(struct tep_handle *tep, struct analysis_data *data)
 			printf("    ---------        --- \t     --------\n");
 		}
 		printf("%16s %8d\t",
-		       tep_data_comm_from_pid(tep, tasks[i]->pid),
+		       tasks[i]->comm ? : tep_data_comm_from_pid(tep, tasks[i]->pid),
 		       tasks[i]->pid);
 		print_time(tasks[i]->runtime, '_');
 		printf(" (%%%lld)\n", (tasks[i]->runtime * 100) / total_time);
@@ -470,6 +519,7 @@  static void free_tasks(struct trace_hash *hash)
 		trace_hash_while_item(item, bucket) {
 			task = task_from_hash(item);
 			trace_hash_del(item);
+			free(task->comm);
 			free(task);
 		}
 	}
@@ -518,9 +568,17 @@  static void do_trace_analyze(struct tracecmd_input *handle)
 
 	trace_hash_init(&data.tasks, 128);
 
+	data.switch_event = tep_find_event_by_name(tep, "sched", "sched_switch");
+
 	/* Set to a very large number */
 	data.start_ts = -1ULL;
 
+	if (data.switch_event) {
+		data.next_pid = tep_find_field(data.switch_event, "next_pid");
+		data.next_comm = tep_find_field(data.switch_event, "next_comm");
+		data.prev_comm = tep_find_field(data.switch_event, "prev_comm");
+	}
+
 	do {
 		record = tracecmd_read_next_data(handle, NULL);
 		if (record)