ftrace: function graph return for function entry
authorSteven Rostedt <srostedt@redhat.com>
Wed, 3 Dec 2008 04:50:05 +0000 (23:50 -0500)
committerIngo Molnar <mingo@elte.hu>
Wed, 3 Dec 2008 07:56:26 +0000 (08:56 +0100)
Impact: feature, let entry function decide to trace or not

This patch lets the graph tracer entry function decide if the tracing
should be done at the end as well. This requires all function graph
entry functions return 1 if it should trace, or 0 if the return should
not be traced.

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/ftrace.c
include/linux/ftrace.h
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h

index 826682abed1d9f91311f466d5f0a62b46d238062..43ceb3f454bfce00386eeaaf377014871272a809 100644 (file)
@@ -1196,6 +1196,9 @@ ENTRY(mcount)
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        cmpl $ftrace_stub, ftrace_graph_return
        jnz ftrace_graph_caller
+
+       cmpl $ftrace_graph_entry_stub, ftrace_graph_entry
+       jnz ftrace_graph_caller
 #endif
 .globl ftrace_stub
 ftrace_stub:
index 9060ba6497e2714c6bbb73aab34b4879bc9e630c..54e0bbdccb994d9b1b87747158487e4817ccde81 100644 (file)
@@ -120,6 +120,9 @@ ENTRY(mcount)
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        cmpq $ftrace_stub, ftrace_graph_return
        jnz ftrace_graph_caller
+
+       cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
+       jnz ftrace_graph_caller
 #endif
 
 .globl ftrace_stub
index adba8e9a427c7beea213013a9fdf0502847418ac..d278ad2ebda2c221122909c45214ad195196dcab 100644 (file)
@@ -425,6 +425,7 @@ static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
        trace->calltime = current->ret_stack[index].calltime;
        trace->overrun = atomic_read(&current->trace_overrun);
        trace->depth = index;
+       barrier();
        current->curr_ret_stack--;
 }
 
@@ -506,7 +507,11 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
        }
 
        trace.func = self_addr;
-       ftrace_graph_entry(&trace);
 
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               current->curr_ret_stack--;
+               *parent = old;
+       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index 58ca1c3a3f4d4b6402a3b8cc816fa565a59db99f..469ceb3e85ba4e8cdda03299f718a7430785e59a 100644 (file)
@@ -371,7 +371,7 @@ struct ftrace_graph_ret {
 #define FTRACE_RETSTACK_ALLOC_SIZE 32
 /* Type of the callback handlers for tracing function graph*/
 typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
-typedef void (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
+typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
 
 extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
                                trace_func_graph_ent_t entryfunc);
index a44af05ae2d00c63b7c3633f1fa43841894d620a..65b9e863056b4fc7f7fa6ba8c228045d18fb0a31 100644 (file)
@@ -1636,11 +1636,15 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
 
 static atomic_t ftrace_graph_active;
 
+int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace)
+{
+       return 0;
+}
+
 /* The callbacks that hook a function */
 trace_func_graph_ret_t ftrace_graph_return =
                        (trace_func_graph_ret_t)ftrace_stub;
-trace_func_graph_ent_t ftrace_graph_entry =
-                       (trace_func_graph_ent_t)ftrace_stub;
+trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub;
 
 /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
 static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
@@ -1738,7 +1742,7 @@ void unregister_ftrace_graph(void)
 
        atomic_dec(&ftrace_graph_active);
        ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
-       ftrace_graph_entry = (trace_func_graph_ent_t)ftrace_stub;
+       ftrace_graph_entry = ftrace_graph_entry_stub;
        ftrace_shutdown(FTRACE_STOP_FUNC_RET);
 
        mutex_unlock(&ftrace_sysctl_lock);
index 380de630ebce6533b76d6c196ec4bddb7bb89fb5..8b6409a62b54b7c53ebeba915dbcf95826b97ad3 100644 (file)
@@ -1200,7 +1200,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip)
 }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-void trace_graph_entry(struct ftrace_graph_ent *trace)
+int trace_graph_entry(struct ftrace_graph_ent *trace)
 {
        struct trace_array *tr = &global_trace;
        struct trace_array_cpu *data;
@@ -1219,6 +1219,8 @@ void trace_graph_entry(struct ftrace_graph_ent *trace)
        }
        atomic_dec(&data->disabled);
        local_irq_restore(flags);
+
+       return 1;
 }
 
 void trace_graph_return(struct ftrace_graph_ret *trace)
index f96f4e787ff39fb8310ddc0efdc5845ccd43f30c..0565ae9a2210a05c898d1ca4b2384fca1be72b7c 100644 (file)
@@ -412,7 +412,7 @@ void trace_function(struct trace_array *tr,
                    unsigned long flags, int pc);
 
 void trace_graph_return(struct ftrace_graph_ret *trace);
-void trace_graph_entry(struct ftrace_graph_ent *trace);
+int trace_graph_entry(struct ftrace_graph_ent *trace);
 void trace_bts(struct trace_array *tr,
               unsigned long from,
               unsigned long to);