diff options
Diffstat (limited to 'kernel/trace/trace_sched_wakeup.c')
-rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 270 |
1 files changed, 128 insertions, 142 deletions
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 7d04b9890755..4ea7e6845efb 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c | |||
@@ -35,26 +35,19 @@ static arch_spinlock_t wakeup_lock = | |||
35 | 35 | ||
36 | static void wakeup_reset(struct trace_array *tr); | 36 | static void wakeup_reset(struct trace_array *tr); |
37 | static void __wakeup_reset(struct trace_array *tr); | 37 | static void __wakeup_reset(struct trace_array *tr); |
38 | static int start_func_tracer(struct trace_array *tr, int graph); | ||
39 | static void stop_func_tracer(struct trace_array *tr, int graph); | ||
38 | 40 | ||
39 | static int save_flags; | 41 | static int save_flags; |
40 | 42 | ||
41 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 43 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
42 | static int wakeup_display_graph(struct trace_array *tr, int set); | ||
43 | # define is_graph(tr) ((tr)->trace_flags & TRACE_ITER_DISPLAY_GRAPH) | 44 | # define is_graph(tr) ((tr)->trace_flags & TRACE_ITER_DISPLAY_GRAPH) |
44 | #else | 45 | #else |
45 | static inline int wakeup_display_graph(struct trace_array *tr, int set) | ||
46 | { | ||
47 | return 0; | ||
48 | } | ||
49 | # define is_graph(tr) false | 46 | # define is_graph(tr) false |
50 | #endif | 47 | #endif |
51 | 48 | ||
52 | |||
53 | #ifdef CONFIG_FUNCTION_TRACER | 49 | #ifdef CONFIG_FUNCTION_TRACER |
54 | 50 | ||
55 | static int wakeup_graph_entry(struct ftrace_graph_ent *trace); | ||
56 | static void wakeup_graph_return(struct ftrace_graph_ret *trace); | ||
57 | |||
58 | static bool function_enabled; | 51 | static bool function_enabled; |
59 | 52 | ||
60 | /* | 53 | /* |
@@ -104,122 +97,8 @@ out_enable: | |||
104 | return 0; | 97 | return 0; |
105 | } | 98 | } |
106 | 99 | ||
107 | /* | ||
108 | * wakeup uses its own tracer function to keep the overhead down: | ||
109 | */ | ||
110 | static void | ||
111 | wakeup_tracer_call(unsigned long ip, unsigned long parent_ip, | ||
112 | struct ftrace_ops *op, struct pt_regs *pt_regs) | ||
113 | { | ||
114 | struct trace_array *tr = wakeup_trace; | ||
115 | struct trace_array_cpu *data; | ||
116 | unsigned long flags; | ||
117 | int pc; | ||
118 | |||
119 | if (!func_prolog_preempt_disable(tr, &data, &pc)) | ||
120 | return; | ||
121 | |||
122 | local_irq_save(flags); | ||
123 | trace_function(tr, ip, parent_ip, flags, pc); | ||
124 | local_irq_restore(flags); | ||
125 | |||
126 | atomic_dec(&data->disabled); | ||
127 | preempt_enable_notrace(); | ||
128 | } | ||
129 | |||
130 | static int register_wakeup_function(struct trace_array *tr, int graph, int set) | ||
131 | { | ||
132 | int ret; | ||
133 | |||
134 | /* 'set' is set if TRACE_ITER_FUNCTION is about to be set */ | ||
135 | if (function_enabled || (!set && !(tr->trace_flags & TRACE_ITER_FUNCTION))) | ||
136 | return 0; | ||
137 | |||
138 | if (graph) | ||
139 | ret = register_ftrace_graph(&wakeup_graph_return, | ||
140 | &wakeup_graph_entry); | ||
141 | else | ||
142 | ret = register_ftrace_function(tr->ops); | ||
143 | |||
144 | if (!ret) | ||
145 | function_enabled = true; | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static void unregister_wakeup_function(struct trace_array *tr, int graph) | ||
151 | { | ||
152 | if (!function_enabled) | ||
153 | return; | ||
154 | |||
155 | if (graph) | ||
156 | unregister_ftrace_graph(); | ||
157 | else | ||
158 | unregister_ftrace_function(tr->ops); | ||
159 | |||
160 | function_enabled = false; | ||
161 | } | ||
162 | |||
163 | static int wakeup_function_set(struct trace_array *tr, u32 mask, int set) | ||
164 | { | ||
165 | if (!(mask & TRACE_ITER_FUNCTION)) | ||
166 | return 0; | ||
167 | |||
168 | if (set) | ||
169 | register_wakeup_function(tr, is_graph(tr), 1); | ||
170 | else | ||
171 | unregister_wakeup_function(tr, is_graph(tr)); | ||
172 | return 1; | ||
173 | } | ||
174 | #else | ||
175 | static int register_wakeup_function(struct trace_array *tr, int graph, int set) | ||
176 | { | ||
177 | return 0; | ||
178 | } | ||
179 | static void unregister_wakeup_function(struct trace_array *tr, int graph) { } | ||
180 | static int wakeup_function_set(struct trace_array *tr, u32 mask, int set) | ||
181 | { | ||
182 | return 0; | ||
183 | } | ||
184 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
185 | |||
186 | static int wakeup_flag_changed(struct trace_array *tr, u32 mask, int set) | ||
187 | { | ||
188 | struct tracer *tracer = tr->current_trace; | ||
189 | |||
190 | if (wakeup_function_set(tr, mask, set)) | ||
191 | return 0; | ||
192 | |||
193 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 100 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
194 | if (mask & TRACE_ITER_DISPLAY_GRAPH) | ||
195 | return wakeup_display_graph(tr, set); | ||
196 | #endif | ||
197 | 101 | ||
198 | return trace_keep_overwrite(tracer, mask, set); | ||
199 | } | ||
200 | |||
201 | static int start_func_tracer(struct trace_array *tr, int graph) | ||
202 | { | ||
203 | int ret; | ||
204 | |||
205 | ret = register_wakeup_function(tr, graph, 0); | ||
206 | |||
207 | if (!ret && tracing_is_enabled()) | ||
208 | tracer_enabled = 1; | ||
209 | else | ||
210 | tracer_enabled = 0; | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static void stop_func_tracer(struct trace_array *tr, int graph) | ||
216 | { | ||
217 | tracer_enabled = 0; | ||
218 | |||
219 | unregister_wakeup_function(tr, graph); | ||
220 | } | ||
221 | |||
222 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
223 | static int wakeup_display_graph(struct trace_array *tr, int set) | 102 | static int wakeup_display_graph(struct trace_array *tr, int set) |
224 | { | 103 | { |
225 | if (!(is_graph(tr) ^ set)) | 104 | if (!(is_graph(tr) ^ set)) |
@@ -283,6 +162,11 @@ static void wakeup_graph_return(struct ftrace_graph_ret *trace) | |||
283 | return; | 162 | return; |
284 | } | 163 | } |
285 | 164 | ||
165 | static struct fgraph_ops fgraph_wakeup_ops = { | ||
166 | .entryfunc = &wakeup_graph_entry, | ||
167 | .retfunc = &wakeup_graph_return, | ||
168 | }; | ||
169 | |||
286 | static void wakeup_trace_open(struct trace_iterator *iter) | 170 | static void wakeup_trace_open(struct trace_iterator *iter) |
287 | { | 171 | { |
288 | if (is_graph(iter->tr)) | 172 | if (is_graph(iter->tr)) |
@@ -318,20 +202,87 @@ static void wakeup_print_header(struct seq_file *s) | |||
318 | else | 202 | else |
319 | trace_default_header(s); | 203 | trace_default_header(s); |
320 | } | 204 | } |
205 | #endif /* else CONFIG_FUNCTION_GRAPH_TRACER */ | ||
321 | 206 | ||
207 | /* | ||
208 | * wakeup uses its own tracer function to keep the overhead down: | ||
209 | */ | ||
322 | static void | 210 | static void |
323 | __trace_function(struct trace_array *tr, | 211 | wakeup_tracer_call(unsigned long ip, unsigned long parent_ip, |
324 | unsigned long ip, unsigned long parent_ip, | 212 | struct ftrace_ops *op, struct pt_regs *pt_regs) |
325 | unsigned long flags, int pc) | ||
326 | { | 213 | { |
327 | if (is_graph(tr)) | 214 | struct trace_array *tr = wakeup_trace; |
328 | trace_graph_function(tr, ip, parent_ip, flags, pc); | 215 | struct trace_array_cpu *data; |
216 | unsigned long flags; | ||
217 | int pc; | ||
218 | |||
219 | if (!func_prolog_preempt_disable(tr, &data, &pc)) | ||
220 | return; | ||
221 | |||
222 | local_irq_save(flags); | ||
223 | trace_function(tr, ip, parent_ip, flags, pc); | ||
224 | local_irq_restore(flags); | ||
225 | |||
226 | atomic_dec(&data->disabled); | ||
227 | preempt_enable_notrace(); | ||
228 | } | ||
229 | |||
230 | static int register_wakeup_function(struct trace_array *tr, int graph, int set) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | /* 'set' is set if TRACE_ITER_FUNCTION is about to be set */ | ||
235 | if (function_enabled || (!set && !(tr->trace_flags & TRACE_ITER_FUNCTION))) | ||
236 | return 0; | ||
237 | |||
238 | if (graph) | ||
239 | ret = register_ftrace_graph(&fgraph_wakeup_ops); | ||
329 | else | 240 | else |
330 | trace_function(tr, ip, parent_ip, flags, pc); | 241 | ret = register_ftrace_function(tr->ops); |
242 | |||
243 | if (!ret) | ||
244 | function_enabled = true; | ||
245 | |||
246 | return ret; | ||
331 | } | 247 | } |
332 | #else | ||
333 | #define __trace_function trace_function | ||
334 | 248 | ||
249 | static void unregister_wakeup_function(struct trace_array *tr, int graph) | ||
250 | { | ||
251 | if (!function_enabled) | ||
252 | return; | ||
253 | |||
254 | if (graph) | ||
255 | unregister_ftrace_graph(&fgraph_wakeup_ops); | ||
256 | else | ||
257 | unregister_ftrace_function(tr->ops); | ||
258 | |||
259 | function_enabled = false; | ||
260 | } | ||
261 | |||
262 | static int wakeup_function_set(struct trace_array *tr, u32 mask, int set) | ||
263 | { | ||
264 | if (!(mask & TRACE_ITER_FUNCTION)) | ||
265 | return 0; | ||
266 | |||
267 | if (set) | ||
268 | register_wakeup_function(tr, is_graph(tr), 1); | ||
269 | else | ||
270 | unregister_wakeup_function(tr, is_graph(tr)); | ||
271 | return 1; | ||
272 | } | ||
273 | #else /* CONFIG_FUNCTION_TRACER */ | ||
274 | static int register_wakeup_function(struct trace_array *tr, int graph, int set) | ||
275 | { | ||
276 | return 0; | ||
277 | } | ||
278 | static void unregister_wakeup_function(struct trace_array *tr, int graph) { } | ||
279 | static int wakeup_function_set(struct trace_array *tr, u32 mask, int set) | ||
280 | { | ||
281 | return 0; | ||
282 | } | ||
283 | #endif /* else CONFIG_FUNCTION_TRACER */ | ||
284 | |||
285 | #ifndef CONFIG_FUNCTION_GRAPH_TRACER | ||
335 | static enum print_line_t wakeup_print_line(struct trace_iterator *iter) | 286 | static enum print_line_t wakeup_print_line(struct trace_iterator *iter) |
336 | { | 287 | { |
337 | return TRACE_TYPE_UNHANDLED; | 288 | return TRACE_TYPE_UNHANDLED; |
@@ -340,23 +291,58 @@ static enum print_line_t wakeup_print_line(struct trace_iterator *iter) | |||
340 | static void wakeup_trace_open(struct trace_iterator *iter) { } | 291 | static void wakeup_trace_open(struct trace_iterator *iter) { } |
341 | static void wakeup_trace_close(struct trace_iterator *iter) { } | 292 | static void wakeup_trace_close(struct trace_iterator *iter) { } |
342 | 293 | ||
343 | #ifdef CONFIG_FUNCTION_TRACER | ||
344 | static int wakeup_graph_entry(struct ftrace_graph_ent *trace) | ||
345 | { | ||
346 | return -1; | ||
347 | } | ||
348 | static void wakeup_graph_return(struct ftrace_graph_ret *trace) { } | ||
349 | static void wakeup_print_header(struct seq_file *s) | 294 | static void wakeup_print_header(struct seq_file *s) |
350 | { | 295 | { |
351 | trace_default_header(s); | 296 | trace_default_header(s); |
352 | } | 297 | } |
353 | #else | 298 | #endif /* !CONFIG_FUNCTION_GRAPH_TRACER */ |
354 | static void wakeup_print_header(struct seq_file *s) | 299 | |
300 | static void | ||
301 | __trace_function(struct trace_array *tr, | ||
302 | unsigned long ip, unsigned long parent_ip, | ||
303 | unsigned long flags, int pc) | ||
355 | { | 304 | { |
356 | trace_latency_header(s); | 305 | if (is_graph(tr)) |
306 | trace_graph_function(tr, ip, parent_ip, flags, pc); | ||
307 | else | ||
308 | trace_function(tr, ip, parent_ip, flags, pc); | ||
309 | } | ||
310 | |||
311 | static int wakeup_flag_changed(struct trace_array *tr, u32 mask, int set) | ||
312 | { | ||
313 | struct tracer *tracer = tr->current_trace; | ||
314 | |||
315 | if (wakeup_function_set(tr, mask, set)) | ||
316 | return 0; | ||
317 | |||
318 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
319 | if (mask & TRACE_ITER_DISPLAY_GRAPH) | ||
320 | return wakeup_display_graph(tr, set); | ||
321 | #endif | ||
322 | |||
323 | return trace_keep_overwrite(tracer, mask, set); | ||
324 | } | ||
325 | |||
326 | static int start_func_tracer(struct trace_array *tr, int graph) | ||
327 | { | ||
328 | int ret; | ||
329 | |||
330 | ret = register_wakeup_function(tr, graph, 0); | ||
331 | |||
332 | if (!ret && tracing_is_enabled()) | ||
333 | tracer_enabled = 1; | ||
334 | else | ||
335 | tracer_enabled = 0; | ||
336 | |||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | static void stop_func_tracer(struct trace_array *tr, int graph) | ||
341 | { | ||
342 | tracer_enabled = 0; | ||
343 | |||
344 | unregister_wakeup_function(tr, graph); | ||
357 | } | 345 | } |
358 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
359 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
360 | 346 | ||
361 | /* | 347 | /* |
362 | * Should this new latency be reported/recorded? | 348 | * Should this new latency be reported/recorded? |