diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-19 06:13:33 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-19 06:13:33 -0500 |
commit | 4cd0332db7e8f57cc082bab11d82c064a9721737 (patch) | |
tree | b6de7771d67c5bf6eeb890fa0f5a901365104b98 /kernel/trace/trace_functions_graph.c | |
parent | 40999096e8b9872199bf56ecd0c4d98397ccaf2f (diff) | |
parent | 712406a6bf59ebf4a00358bb59a4a2a1b2953d90 (diff) |
Merge branch 'mainline/function-graph' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/function-graph-tracer
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 0ff5cb661900..6c7738e4f98b 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -50,6 +50,81 @@ static struct tracer_flags tracer_flags = { | |||
50 | /* pid on the last trace processed */ | 50 | /* pid on the last trace processed */ |
51 | 51 | ||
52 | 52 | ||
53 | /* Add a function return address to the trace stack on thread info.*/ | ||
54 | int | ||
55 | ftrace_push_return_trace(unsigned long ret, unsigned long long time, | ||
56 | unsigned long func, int *depth) | ||
57 | { | ||
58 | int index; | ||
59 | |||
60 | if (!current->ret_stack) | ||
61 | return -EBUSY; | ||
62 | |||
63 | /* The return trace stack is full */ | ||
64 | if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { | ||
65 | atomic_inc(¤t->trace_overrun); | ||
66 | return -EBUSY; | ||
67 | } | ||
68 | |||
69 | index = ++current->curr_ret_stack; | ||
70 | barrier(); | ||
71 | current->ret_stack[index].ret = ret; | ||
72 | current->ret_stack[index].func = func; | ||
73 | current->ret_stack[index].calltime = time; | ||
74 | *depth = index; | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | /* Retrieve a function return address to the trace stack on thread info.*/ | ||
80 | void | ||
81 | ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) | ||
82 | { | ||
83 | int index; | ||
84 | |||
85 | index = current->curr_ret_stack; | ||
86 | |||
87 | if (unlikely(index < 0)) { | ||
88 | ftrace_graph_stop(); | ||
89 | WARN_ON(1); | ||
90 | /* Might as well panic, otherwise we have no where to go */ | ||
91 | *ret = (unsigned long)panic; | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | *ret = current->ret_stack[index].ret; | ||
96 | trace->func = current->ret_stack[index].func; | ||
97 | trace->calltime = current->ret_stack[index].calltime; | ||
98 | trace->overrun = atomic_read(¤t->trace_overrun); | ||
99 | trace->depth = index; | ||
100 | barrier(); | ||
101 | current->curr_ret_stack--; | ||
102 | |||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Send the trace to the ring-buffer. | ||
107 | * @return the original return address. | ||
108 | */ | ||
109 | unsigned long ftrace_return_to_handler(void) | ||
110 | { | ||
111 | struct ftrace_graph_ret trace; | ||
112 | unsigned long ret; | ||
113 | |||
114 | ftrace_pop_return_trace(&trace, &ret); | ||
115 | trace.rettime = cpu_clock(raw_smp_processor_id()); | ||
116 | ftrace_graph_return(&trace); | ||
117 | |||
118 | if (unlikely(!ret)) { | ||
119 | ftrace_graph_stop(); | ||
120 | WARN_ON(1); | ||
121 | /* Might as well panic. What else to do? */ | ||
122 | ret = (unsigned long)panic; | ||
123 | } | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
53 | static int graph_trace_init(struct trace_array *tr) | 128 | static int graph_trace_init(struct trace_array *tr) |
54 | { | 129 | { |
55 | int ret = register_ftrace_graph(&trace_graph_return, | 130 | int ret = register_ftrace_graph(&trace_graph_return, |