}
#endif
-#ifdef CONFIG_FUNCTION_RET_TRACER
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#ifndef CONFIG_DYNAMIC_FTRACE
/* Add a function return address to the trace stack on thread info.*/
static int push_return_trace(unsigned long ret, unsigned long long time,
- unsigned long func)
+ unsigned long func, int *depth)
{
int index;
- struct thread_info *ti = current_thread_info();
+
+ if (!current->ret_stack)
+ return -EBUSY;
/* The return trace stack is full */
- if (ti->curr_ret_stack == FTRACE_RET_STACK_SIZE - 1)
+ if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
+ atomic_inc(¤t->trace_overrun);
return -EBUSY;
+ }
- index = ++ti->curr_ret_stack;
+ index = ++current->curr_ret_stack;
barrier();
- ti->ret_stack[index].ret = ret;
- ti->ret_stack[index].func = func;
- ti->ret_stack[index].calltime = time;
+ current->ret_stack[index].ret = ret;
+ current->ret_stack[index].func = func;
+ current->ret_stack[index].calltime = time;
+ *depth = index;
return 0;
}
/* Retrieve a function return address to the trace stack on thread info.*/
-static void pop_return_trace(unsigned long *ret, unsigned long long *time,
- unsigned long *func)
+static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
{
int index;
- struct thread_info *ti = current_thread_info();
- index = ti->curr_ret_stack;
- *ret = ti->ret_stack[index].ret;
- *func = ti->ret_stack[index].func;
- *time = ti->ret_stack[index].calltime;
- ti->curr_ret_stack--;
+ index = current->curr_ret_stack;
+ *ret = current->ret_stack[index].ret;
+ trace->func = current->ret_stack[index].func;
+ trace->calltime = current->ret_stack[index].calltime;
+ trace->overrun = atomic_read(¤t->trace_overrun);
+ trace->depth = index;
+ current->curr_ret_stack--;
}
/*
*/
unsigned long ftrace_return_to_handler(void)
{
- struct ftrace_retfunc trace;
- pop_return_trace(&trace.ret, &trace.calltime, &trace.func);
+ struct ftrace_graph_ret trace;
+ unsigned long ret;
+
+ pop_return_trace(&trace, &ret);
trace.rettime = cpu_clock(raw_smp_processor_id());
- ftrace_function_return(&trace);
+ ftrace_graph_return(&trace);
- return trace.ret;
+ return ret;
}
/*
unsigned long old;
unsigned long long calltime;
int faulted;
+ struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)
&return_to_handler;
);
if (WARN_ON(faulted)) {
- unregister_ftrace_return();
+ unregister_ftrace_graph();
return;
}
if (WARN_ON(!__kernel_text_address(old))) {
- unregister_ftrace_return();
+ unregister_ftrace_graph();
*parent = old;
return;
}
calltime = cpu_clock(raw_smp_processor_id());
- if (push_return_trace(old, calltime, self_addr) == -EBUSY)
+ if (push_return_trace(old, calltime,
+ self_addr, &trace.depth) == -EBUSY) {
*parent = old;
+ return;
+ }
+
+ trace.func = self_addr;
+ ftrace_graph_entry(&trace);
+
}
-#endif /* CONFIG_FUNCTION_RET_TRACER */
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */