From: Jamie Gennis <jgen...@google.com>

The tgids are tracked along side the saved_cmdlines tracking, and can be
included in trace output by enabling the 'print-tgid' trace option. This is
useful when doing post-processing of the trace data, as it allows events to be
grouped by tgid.

Cc: Steven Rostedt <rost...@goodmis.org>
Cc: kernel-t...@android.com
Signed-off-by: Joel Fernandes <joe...@google.com>
---
 kernel/trace/trace.c        | 98 +++++++++++++++++++++++++++++++++++++++++++--
 kernel/trace/trace.h        |  4 +-
 kernel/trace/trace_output.c | 14 ++++++-
 3 files changed, 110 insertions(+), 6 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c4536c449021..aa0cb12892e7 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1711,6 +1711,7 @@ void tracing_reset_all_online_cpus(void)
 
 #define SAVED_CMDLINES_DEFAULT 128
 #define NO_CMDLINE_MAP UINT_MAX
+static unsigned saved_tgids[SAVED_CMDLINES_DEFAULT];
 static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 struct saved_cmdlines_buffer {
        unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
@@ -1949,7 +1950,7 @@ static int trace_save_cmdline(struct task_struct *tsk)
        }
 
        set_cmdline(idx, tsk->comm);
-
+       saved_tgids[idx] = tsk->tgid;
        arch_spin_unlock(&trace_cmdline_lock);
 
        return 1;
@@ -1992,6 +1993,25 @@ void trace_find_cmdline(int pid, char comm[])
        preempt_enable();
 }
 
+int trace_find_tgid(int pid)
+{
+       unsigned map;
+       int tgid;
+
+       preempt_disable();
+       arch_spin_lock(&trace_cmdline_lock);
+       map = savedcmd->map_pid_to_cmdline[pid];
+       if (map != NO_CMDLINE_MAP)
+               tgid = saved_tgids[map];
+       else
+               tgid = -1;
+
+       arch_spin_unlock(&trace_cmdline_lock);
+       preempt_enable();
+
+       return tgid;
+}
+
 void tracing_record_cmdline(struct task_struct *tsk)
 {
        if (atomic_read(&trace_record_cmdline_disabled) || !tracing_is_on())
@@ -3226,6 +3246,13 @@ static void print_func_help_header(struct trace_buffer 
*buf, struct seq_file *m)
                    "#              | |       |          |         |\n");
 }
 
+static void print_func_help_header_tgid(struct trace_buffer *buf, struct 
seq_file *m)
+{
+       print_event_info(buf, m);
+       seq_puts(m, "#           TASK-PID    TGID   CPU#      TIMESTAMP  
FUNCTION\n");
+       seq_puts(m, "#              | |        |      |          |         
|\n");
+}
+
 static void print_func_help_header_irq(struct trace_buffer *buf, struct 
seq_file *m)
 {
        print_event_info(buf, m);
@@ -3238,6 +3265,18 @@ static void print_func_help_header_irq(struct 
trace_buffer *buf, struct seq_file
                    "#              | |       |   ||||       |         |\n");
 }
 
+static void print_func_help_header_irq_tgid(struct trace_buffer *buf, struct 
seq_file *m)
+{
+       print_event_info(buf, m);
+       seq_puts(m, "#                                      _-----=> 
irqs-off\n");
+       seq_puts(m, "#                                     / _----=> 
need-resched\n");
+       seq_puts(m, "#                                    | / _---=> 
hardirq/softirq\n");
+       seq_puts(m, "#                                    || / _--=> 
preempt-depth\n");
+       seq_puts(m, "#                                    ||| /     delay\n");
+       seq_puts(m, "#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  
FUNCTION\n");
+       seq_puts(m, "#              | |        |      |   ||||       |         
|\n");
+}
+
 void
 print_trace_header(struct seq_file *m, struct trace_iterator *iter)
 {
@@ -3551,9 +3590,15 @@ void trace_default_header(struct seq_file *m)
        } else {
                if (!(trace_flags & TRACE_ITER_VERBOSE)) {
                        if (trace_flags & TRACE_ITER_IRQ_INFO)
-                               print_func_help_header_irq(iter->trace_buffer, 
m);
+                               if (trace_flags & TRACE_ITER_TGID)
+                                       
print_func_help_header_irq_tgid(iter->trace_buffer, m);
+                               else
+                                       
print_func_help_header_irq(iter->trace_buffer, m);
                        else
-                               print_func_help_header(iter->trace_buffer, m);
+                               if (trace_flags & TRACE_ITER_TGID)
+                                       
print_func_help_header_tgid(iter->trace_buffer, m);
+                               else
+                                       
print_func_help_header(iter->trace_buffer, m);
                }
        }
 }
@@ -4894,6 +4939,50 @@ static void trace_insert_enum_map(struct module *mod,
 }
 
 static ssize_t
+tracing_saved_tgids_read(struct file *file, char __user *ubuf,
+                               size_t cnt, loff_t *ppos)
+{
+       char *file_buf;
+       char *buf;
+       int len = 0;
+       int pid;
+       int i;
+
+       file_buf = kmalloc(SAVED_CMDLINES_DEFAULT*(16+1+16), GFP_KERNEL);
+       if (!file_buf)
+               return -ENOMEM;
+
+       buf = file_buf;
+
+       for (i = 0; i < SAVED_CMDLINES_DEFAULT; i++) {
+               int tgid;
+               int r;
+
+               pid = savedcmd->map_cmdline_to_pid[i];
+               if (pid == -1 || pid == NO_CMDLINE_MAP)
+                       continue;
+
+               tgid = trace_find_tgid(pid);
+               r = sprintf(buf, "%d %d\n", pid, tgid);
+               buf += r;
+               len += r;
+       }
+
+       len = simple_read_from_buffer(ubuf, cnt, ppos,
+                                     file_buf, len);
+
+       kfree(file_buf);
+
+       return len;
+}
+
+static const struct file_operations tracing_saved_tgids_fops = {
+       .open   = tracing_open_generic,
+       .read   = tracing_saved_tgids_read,
+       .llseek = generic_file_llseek,
+};
+
+static ssize_t
 tracing_set_trace_read(struct file *filp, char __user *ubuf,
                       size_t cnt, loff_t *ppos)
 {
@@ -7619,6 +7708,9 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry 
*d_tracer)
        trace_create_file("trace_marker_raw", 0220, d_tracer,
                          tr, &tracing_mark_raw_fops);
 
+       trace_create_file("saved_tgids", 0444, d_tracer,
+                         tr, &tracing_saved_tgids_fops);
+
        trace_create_file("trace_clock", 0644, d_tracer, tr,
                          &trace_clock_fops);
 
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 291a1bca5748..f5bec38f40e0 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -697,6 +697,7 @@ static inline void __trace_stack(struct trace_array *tr, 
unsigned long flags,
 extern u64 ftrace_now(int cpu);
 
 extern void trace_find_cmdline(int pid, char comm[]);
+extern int trace_find_tgid(int pid);
 extern void trace_event_follow_fork(struct trace_array *tr, bool enable);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -1110,7 +1111,8 @@ extern int trace_get_user(struct trace_parser *parser, 
const char __user *ubuf,
                FUNCTION_FLAGS                                  \
                FGRAPH_FLAGS                                    \
                STACK_FLAGS                                     \
-               BRANCH_FLAGS
+               BRANCH_FLAGS                                    \
+               C(TGID,                 "print-tgid"),
 
 /*
  * By defining C, we can make TRACE_FLAGS a list of bit names
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 08f9bab8089e..00d65f87ad3d 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -581,11 +581,21 @@ int trace_print_context(struct trace_iterator *iter)
        unsigned long long t;
        unsigned long secs, usec_rem;
        char comm[TASK_COMM_LEN];
+       int tgid;
 
        trace_find_cmdline(entry->pid, comm);
 
-       trace_seq_printf(s, "%16s-%-5d [%03d] ",
-                              comm, entry->pid, iter->cpu);
+       trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
+
+       if (tr->trace_flags & TRACE_ITER_TGID) {
+               tgid = trace_find_tgid(entry->pid);
+               if (tgid < 0)
+                       trace_seq_puts(s, "(-----) ");
+               else
+                       trace_seq_printf(s, "(%5d) ", tgid);
+       }
+
+       trace_seq_printf(s, "[%03d] ", iter->cpu);
 
        if (tr->trace_flags & TRACE_ITER_IRQ_INFO)
                trace_print_lat_fmt(s, entry);
-- 
2.13.0.303.g4ebf302169-goog

Reply via email to