Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / kernel / trace / trace_functions_graph.c
index 616b135..e6989d9 100644 (file)
@@ -18,6 +18,7 @@ struct fgraph_cpu_data {
        pid_t           last_pid;
        int             depth;
        int             ignore;
+       unsigned long   enter_funcs[FTRACE_RETFUNC_DEPTH];
 };
 
 struct fgraph_data {
@@ -187,7 +188,7 @@ static int __trace_graph_entry(struct trace_array *tr,
        struct ring_buffer *buffer = tr->buffer;
        struct ftrace_graph_ent_entry *entry;
 
-       if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled))))
+       if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
                return 0;
 
        event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT,
@@ -236,6 +237,14 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
        return ret;
 }
 
+int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
+{
+       if (tracing_thresh)
+               return 1;
+       else
+               return trace_graph_entry(trace);
+}
+
 static void __trace_graph_return(struct trace_array *tr,
                                struct ftrace_graph_ret *trace,
                                unsigned long flags,
@@ -246,7 +255,7 @@ static void __trace_graph_return(struct trace_array *tr,
        struct ring_buffer *buffer = tr->buffer;
        struct ftrace_graph_ret_entry *entry;
 
-       if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled))))
+       if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
                return;
 
        event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET,
@@ -289,13 +298,26 @@ void set_graph_array(struct trace_array *tr)
        smp_mb();
 }
 
+void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
+{
+       if (tracing_thresh &&
+           (trace->rettime - trace->calltime < tracing_thresh))
+               return;
+       else
+               trace_graph_return(trace);
+}
+
 static int graph_trace_init(struct trace_array *tr)
 {
        int ret;
 
        set_graph_array(tr);
-       ret = register_ftrace_graph(&trace_graph_return,
-                                   &trace_graph_entry);
+       if (tracing_thresh)
+               ret = register_ftrace_graph(&trace_graph_thresh_return,
+                                           &trace_graph_thresh_entry);
+       else
+               ret = register_ftrace_graph(&trace_graph_return,
+                                           &trace_graph_entry);
        if (ret)
                return ret;
        tracing_start_cmdline_record();
@@ -670,15 +692,21 @@ print_graph_entry_leaf(struct trace_iterator *iter,
        duration = graph_ret->rettime - graph_ret->calltime;
 
        if (data) {
+               struct fgraph_cpu_data *cpu_data;
                int cpu = iter->cpu;
-               int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
+
+               cpu_data = per_cpu_ptr(data->cpu_data, cpu);
 
                /*
                 * Comments display at + 1 to depth. Since
                 * this is a leaf function, keep the comments
                 * equal to this depth.
                 */
-               *depth = call->depth - 1;
+               cpu_data->depth = call->depth - 1;
+
+               /* No need to keep this function around for this depth */
+               if (call->depth < FTRACE_RETFUNC_DEPTH)
+                       cpu_data->enter_funcs[call->depth] = 0;
        }
 
        /* Overhead */
@@ -718,10 +746,15 @@ print_graph_entry_nested(struct trace_iterator *iter,
        int i;
 
        if (data) {
+               struct fgraph_cpu_data *cpu_data;
                int cpu = iter->cpu;
-               int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
 
-               *depth = call->depth;
+               cpu_data = per_cpu_ptr(data->cpu_data, cpu);
+               cpu_data->depth = call->depth;
+
+               /* Save this function pointer to see if the exit matches */
+               if (call->depth < FTRACE_RETFUNC_DEPTH)
+                       cpu_data->enter_funcs[call->depth] = call->func;
        }
 
        /* No overhead */
@@ -851,19 +884,28 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
        struct fgraph_data *data = iter->private;
        pid_t pid = ent->pid;
        int cpu = iter->cpu;
+       int func_match = 1;
        int ret;
        int i;
 
        if (data) {
+               struct fgraph_cpu_data *cpu_data;
                int cpu = iter->cpu;
-               int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
+
+               cpu_data = per_cpu_ptr(data->cpu_data, cpu);
 
                /*
                 * Comments display at + 1 to depth. This is the
                 * return from a function, we now want the comments
                 * to display at the same level of the bracket.
                 */
-               *depth = trace->depth - 1;
+               cpu_data->depth = trace->depth - 1;
+
+               if (trace->depth < FTRACE_RETFUNC_DEPTH) {
+                       if (cpu_data->enter_funcs[trace->depth] != trace->func)
+                               func_match = 0;
+                       cpu_data->enter_funcs[trace->depth] = 0;
+               }
        }
 
        if (print_graph_prologue(iter, s, 0, 0))
@@ -888,9 +930,21 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
                        return TRACE_TYPE_PARTIAL_LINE;
        }
 
-       ret = trace_seq_printf(s, "}\n");
-       if (!ret)
-               return TRACE_TYPE_PARTIAL_LINE;
+       /*
+        * If the return function does not have a matching entry,
+        * then the entry was lost. Instead of just printing
+        * the '}' and letting the user guess what function this
+        * belongs to, write out the function name.
+        */
+       if (func_match) {
+               ret = trace_seq_printf(s, "}\n");
+               if (!ret)
+                       return TRACE_TYPE_PARTIAL_LINE;
+       } else {
+               ret = trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);
+               if (!ret)
+                       return TRACE_TYPE_PARTIAL_LINE;
+       }
 
        /* Overrun */
        if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) {