diff options
Diffstat (limited to 'kernel/trace/trace_functions.c')
-rw-r--r-- | kernel/trace/trace_functions.c | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index 3a5fa08cedb..2dce3c7370d 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c | |||
@@ -20,6 +20,7 @@ static struct trace_array *func_trace; | |||
20 | 20 | ||
21 | static void start_function_trace(struct trace_array *tr) | 21 | static void start_function_trace(struct trace_array *tr) |
22 | { | 22 | { |
23 | func_trace = tr; | ||
23 | tr->cpu = get_cpu(); | 24 | tr->cpu = get_cpu(); |
24 | tracing_reset_online_cpus(tr); | 25 | tracing_reset_online_cpus(tr); |
25 | put_cpu(); | 26 | put_cpu(); |
@@ -36,7 +37,6 @@ static void stop_function_trace(struct trace_array *tr) | |||
36 | 37 | ||
37 | static int function_trace_init(struct trace_array *tr) | 38 | static int function_trace_init(struct trace_array *tr) |
38 | { | 39 | { |
39 | func_trace = tr; | ||
40 | start_function_trace(tr); | 40 | start_function_trace(tr); |
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
@@ -52,6 +52,64 @@ static void function_trace_start(struct trace_array *tr) | |||
52 | } | 52 | } |
53 | 53 | ||
54 | static void | 54 | static void |
55 | function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip) | ||
56 | { | ||
57 | struct trace_array *tr = func_trace; | ||
58 | struct trace_array_cpu *data; | ||
59 | unsigned long flags; | ||
60 | long disabled; | ||
61 | int cpu, resched; | ||
62 | int pc; | ||
63 | |||
64 | if (unlikely(!ftrace_function_enabled)) | ||
65 | return; | ||
66 | |||
67 | pc = preempt_count(); | ||
68 | resched = ftrace_preempt_disable(); | ||
69 | local_save_flags(flags); | ||
70 | cpu = raw_smp_processor_id(); | ||
71 | data = tr->data[cpu]; | ||
72 | disabled = atomic_inc_return(&data->disabled); | ||
73 | |||
74 | if (likely(disabled == 1)) | ||
75 | trace_function(tr, data, ip, parent_ip, flags, pc); | ||
76 | |||
77 | atomic_dec(&data->disabled); | ||
78 | ftrace_preempt_enable(resched); | ||
79 | } | ||
80 | |||
81 | static void | ||
82 | function_trace_call(unsigned long ip, unsigned long parent_ip) | ||
83 | { | ||
84 | struct trace_array *tr = func_trace; | ||
85 | struct trace_array_cpu *data; | ||
86 | unsigned long flags; | ||
87 | long disabled; | ||
88 | int cpu; | ||
89 | int pc; | ||
90 | |||
91 | if (unlikely(!ftrace_function_enabled)) | ||
92 | return; | ||
93 | |||
94 | /* | ||
95 | * Need to use raw, since this must be called before the | ||
96 | * recursive protection is performed. | ||
97 | */ | ||
98 | local_irq_save(flags); | ||
99 | cpu = raw_smp_processor_id(); | ||
100 | data = tr->data[cpu]; | ||
101 | disabled = atomic_inc_return(&data->disabled); | ||
102 | |||
103 | if (likely(disabled == 1)) { | ||
104 | pc = preempt_count(); | ||
105 | trace_function(tr, data, ip, parent_ip, flags, pc); | ||
106 | } | ||
107 | |||
108 | atomic_dec(&data->disabled); | ||
109 | local_irq_restore(flags); | ||
110 | } | ||
111 | |||
112 | static void | ||
55 | function_stack_trace_call(unsigned long ip, unsigned long parent_ip) | 113 | function_stack_trace_call(unsigned long ip, unsigned long parent_ip) |
56 | { | 114 | { |
57 | struct trace_array *tr = func_trace; | 115 | struct trace_array *tr = func_trace; |
@@ -90,6 +148,30 @@ function_stack_trace_call(unsigned long ip, unsigned long parent_ip) | |||
90 | local_irq_restore(flags); | 148 | local_irq_restore(flags); |
91 | } | 149 | } |
92 | 150 | ||
151 | |||
152 | static struct ftrace_ops trace_ops __read_mostly = | ||
153 | { | ||
154 | .func = function_trace_call, | ||
155 | }; | ||
156 | |||
157 | void tracing_start_function_trace(void) | ||
158 | { | ||
159 | ftrace_function_enabled = 0; | ||
160 | |||
161 | if (trace_flags & TRACE_ITER_PREEMPTONLY) | ||
162 | trace_ops.func = function_trace_call_preempt_only; | ||
163 | else | ||
164 | trace_ops.func = function_trace_call; | ||
165 | |||
166 | register_ftrace_function(&trace_ops); | ||
167 | ftrace_function_enabled = 1; | ||
168 | } | ||
169 | |||
170 | void tracing_stop_function_trace(void) | ||
171 | { | ||
172 | ftrace_function_enabled = 0; | ||
173 | unregister_ftrace_function(&trace_ops); | ||
174 | } | ||
93 | static struct ftrace_ops trace_stack_ops __read_mostly = | 175 | static struct ftrace_ops trace_stack_ops __read_mostly = |
94 | { | 176 | { |
95 | .func = function_stack_trace_call, | 177 | .func = function_stack_trace_call, |