diff options
Diffstat (limited to 'kernel/trace/trace_sched_wakeup.c')
-rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 42ae1e77b6b3..3c5ad6b2ec84 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c | |||
@@ -25,12 +25,15 @@ static int __read_mostly tracer_enabled; | |||
25 | static struct task_struct *wakeup_task; | 25 | static struct task_struct *wakeup_task; |
26 | static int wakeup_cpu; | 26 | static int wakeup_cpu; |
27 | static unsigned wakeup_prio = -1; | 27 | static unsigned wakeup_prio = -1; |
28 | static int wakeup_rt; | ||
28 | 29 | ||
29 | static raw_spinlock_t wakeup_lock = | 30 | static raw_spinlock_t wakeup_lock = |
30 | (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 31 | (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
31 | 32 | ||
32 | static void __wakeup_reset(struct trace_array *tr); | 33 | static void __wakeup_reset(struct trace_array *tr); |
33 | 34 | ||
35 | static int save_lat_flag; | ||
36 | |||
34 | #ifdef CONFIG_FUNCTION_TRACER | 37 | #ifdef CONFIG_FUNCTION_TRACER |
35 | /* | 38 | /* |
36 | * irqsoff uses its own tracer function to keep the overhead down: | 39 | * irqsoff uses its own tracer function to keep the overhead down: |
@@ -71,7 +74,7 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip) | |||
71 | if (task_cpu(wakeup_task) != cpu) | 74 | if (task_cpu(wakeup_task) != cpu) |
72 | goto unlock; | 75 | goto unlock; |
73 | 76 | ||
74 | trace_function(tr, data, ip, parent_ip, flags, pc); | 77 | trace_function(tr, ip, parent_ip, flags, pc); |
75 | 78 | ||
76 | unlock: | 79 | unlock: |
77 | __raw_spin_unlock(&wakeup_lock); | 80 | __raw_spin_unlock(&wakeup_lock); |
@@ -151,7 +154,8 @@ probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev, | |||
151 | if (unlikely(!tracer_enabled || next != wakeup_task)) | 154 | if (unlikely(!tracer_enabled || next != wakeup_task)) |
152 | goto out_unlock; | 155 | goto out_unlock; |
153 | 156 | ||
154 | trace_function(wakeup_trace, data, CALLER_ADDR1, CALLER_ADDR2, flags, pc); | 157 | trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc); |
158 | tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc); | ||
155 | 159 | ||
156 | /* | 160 | /* |
157 | * usecs conversion is slow so we try to delay the conversion | 161 | * usecs conversion is slow so we try to delay the conversion |
@@ -182,13 +186,10 @@ out: | |||
182 | 186 | ||
183 | static void __wakeup_reset(struct trace_array *tr) | 187 | static void __wakeup_reset(struct trace_array *tr) |
184 | { | 188 | { |
185 | struct trace_array_cpu *data; | ||
186 | int cpu; | 189 | int cpu; |
187 | 190 | ||
188 | for_each_possible_cpu(cpu) { | 191 | for_each_possible_cpu(cpu) |
189 | data = tr->data[cpu]; | ||
190 | tracing_reset(tr, cpu); | 192 | tracing_reset(tr, cpu); |
191 | } | ||
192 | 193 | ||
193 | wakeup_cpu = -1; | 194 | wakeup_cpu = -1; |
194 | wakeup_prio = -1; | 195 | wakeup_prio = -1; |
@@ -213,6 +214,7 @@ static void wakeup_reset(struct trace_array *tr) | |||
213 | static void | 214 | static void |
214 | probe_wakeup(struct rq *rq, struct task_struct *p, int success) | 215 | probe_wakeup(struct rq *rq, struct task_struct *p, int success) |
215 | { | 216 | { |
217 | struct trace_array_cpu *data; | ||
216 | int cpu = smp_processor_id(); | 218 | int cpu = smp_processor_id(); |
217 | unsigned long flags; | 219 | unsigned long flags; |
218 | long disabled; | 220 | long disabled; |
@@ -224,7 +226,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p, int success) | |||
224 | tracing_record_cmdline(p); | 226 | tracing_record_cmdline(p); |
225 | tracing_record_cmdline(current); | 227 | tracing_record_cmdline(current); |
226 | 228 | ||
227 | if (likely(!rt_task(p)) || | 229 | if ((wakeup_rt && !rt_task(p)) || |
228 | p->prio >= wakeup_prio || | 230 | p->prio >= wakeup_prio || |
229 | p->prio >= current->prio) | 231 | p->prio >= current->prio) |
230 | return; | 232 | return; |
@@ -252,9 +254,10 @@ probe_wakeup(struct rq *rq, struct task_struct *p, int success) | |||
252 | 254 | ||
253 | local_save_flags(flags); | 255 | local_save_flags(flags); |
254 | 256 | ||
255 | wakeup_trace->data[wakeup_cpu]->preempt_timestamp = ftrace_now(cpu); | 257 | data = wakeup_trace->data[wakeup_cpu]; |
256 | trace_function(wakeup_trace, wakeup_trace->data[wakeup_cpu], | 258 | data->preempt_timestamp = ftrace_now(cpu); |
257 | CALLER_ADDR1, CALLER_ADDR2, flags, pc); | 259 | tracing_sched_wakeup_trace(wakeup_trace, p, current, flags, pc); |
260 | trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc); | ||
258 | 261 | ||
259 | out_locked: | 262 | out_locked: |
260 | __raw_spin_unlock(&wakeup_lock); | 263 | __raw_spin_unlock(&wakeup_lock); |
@@ -262,12 +265,6 @@ out: | |||
262 | atomic_dec(&wakeup_trace->data[cpu]->disabled); | 265 | atomic_dec(&wakeup_trace->data[cpu]->disabled); |
263 | } | 266 | } |
264 | 267 | ||
265 | /* | ||
266 | * save_tracer_enabled is used to save the state of the tracer_enabled | ||
267 | * variable when we disable it when we open a trace output file. | ||
268 | */ | ||
269 | static int save_tracer_enabled; | ||
270 | |||
271 | static void start_wakeup_tracer(struct trace_array *tr) | 268 | static void start_wakeup_tracer(struct trace_array *tr) |
272 | { | 269 | { |
273 | int ret; | 270 | int ret; |
@@ -289,7 +286,7 @@ static void start_wakeup_tracer(struct trace_array *tr) | |||
289 | ret = register_trace_sched_switch(probe_wakeup_sched_switch); | 286 | ret = register_trace_sched_switch(probe_wakeup_sched_switch); |
290 | if (ret) { | 287 | if (ret) { |
291 | pr_info("sched trace: Couldn't activate tracepoint" | 288 | pr_info("sched trace: Couldn't activate tracepoint" |
292 | " probe to kernel_sched_schedule\n"); | 289 | " probe to kernel_sched_switch\n"); |
293 | goto fail_deprobe_wake_new; | 290 | goto fail_deprobe_wake_new; |
294 | } | 291 | } |
295 | 292 | ||
@@ -306,13 +303,10 @@ static void start_wakeup_tracer(struct trace_array *tr) | |||
306 | 303 | ||
307 | register_ftrace_function(&trace_ops); | 304 | register_ftrace_function(&trace_ops); |
308 | 305 | ||
309 | if (tracing_is_enabled()) { | 306 | if (tracing_is_enabled()) |
310 | tracer_enabled = 1; | 307 | tracer_enabled = 1; |
311 | save_tracer_enabled = 1; | 308 | else |
312 | } else { | ||
313 | tracer_enabled = 0; | 309 | tracer_enabled = 0; |
314 | save_tracer_enabled = 0; | ||
315 | } | ||
316 | 310 | ||
317 | return; | 311 | return; |
318 | fail_deprobe_wake_new: | 312 | fail_deprobe_wake_new: |
@@ -324,54 +318,54 @@ fail_deprobe: | |||
324 | static void stop_wakeup_tracer(struct trace_array *tr) | 318 | static void stop_wakeup_tracer(struct trace_array *tr) |
325 | { | 319 | { |
326 | tracer_enabled = 0; | 320 | tracer_enabled = 0; |
327 | save_tracer_enabled = 0; | ||
328 | unregister_ftrace_function(&trace_ops); | 321 | unregister_ftrace_function(&trace_ops); |
329 | unregister_trace_sched_switch(probe_wakeup_sched_switch); | 322 | unregister_trace_sched_switch(probe_wakeup_sched_switch); |
330 | unregister_trace_sched_wakeup_new(probe_wakeup); | 323 | unregister_trace_sched_wakeup_new(probe_wakeup); |
331 | unregister_trace_sched_wakeup(probe_wakeup); | 324 | unregister_trace_sched_wakeup(probe_wakeup); |
332 | } | 325 | } |
333 | 326 | ||
334 | static int wakeup_tracer_init(struct trace_array *tr) | 327 | static int __wakeup_tracer_init(struct trace_array *tr) |
335 | { | 328 | { |
329 | save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT; | ||
330 | trace_flags |= TRACE_ITER_LATENCY_FMT; | ||
331 | |||
336 | tracing_max_latency = 0; | 332 | tracing_max_latency = 0; |
337 | wakeup_trace = tr; | 333 | wakeup_trace = tr; |
338 | start_wakeup_tracer(tr); | 334 | start_wakeup_tracer(tr); |
339 | return 0; | 335 | return 0; |
340 | } | 336 | } |
341 | 337 | ||
338 | static int wakeup_tracer_init(struct trace_array *tr) | ||
339 | { | ||
340 | wakeup_rt = 0; | ||
341 | return __wakeup_tracer_init(tr); | ||
342 | } | ||
343 | |||
344 | static int wakeup_rt_tracer_init(struct trace_array *tr) | ||
345 | { | ||
346 | wakeup_rt = 1; | ||
347 | return __wakeup_tracer_init(tr); | ||
348 | } | ||
349 | |||
342 | static void wakeup_tracer_reset(struct trace_array *tr) | 350 | static void wakeup_tracer_reset(struct trace_array *tr) |
343 | { | 351 | { |
344 | stop_wakeup_tracer(tr); | 352 | stop_wakeup_tracer(tr); |
345 | /* make sure we put back any tasks we are tracing */ | 353 | /* make sure we put back any tasks we are tracing */ |
346 | wakeup_reset(tr); | 354 | wakeup_reset(tr); |
355 | |||
356 | if (!save_lat_flag) | ||
357 | trace_flags &= ~TRACE_ITER_LATENCY_FMT; | ||
347 | } | 358 | } |
348 | 359 | ||
349 | static void wakeup_tracer_start(struct trace_array *tr) | 360 | static void wakeup_tracer_start(struct trace_array *tr) |
350 | { | 361 | { |
351 | wakeup_reset(tr); | 362 | wakeup_reset(tr); |
352 | tracer_enabled = 1; | 363 | tracer_enabled = 1; |
353 | save_tracer_enabled = 1; | ||
354 | } | 364 | } |
355 | 365 | ||
356 | static void wakeup_tracer_stop(struct trace_array *tr) | 366 | static void wakeup_tracer_stop(struct trace_array *tr) |
357 | { | 367 | { |
358 | tracer_enabled = 0; | 368 | tracer_enabled = 0; |
359 | save_tracer_enabled = 0; | ||
360 | } | ||
361 | |||
362 | static void wakeup_tracer_open(struct trace_iterator *iter) | ||
363 | { | ||
364 | /* stop the trace while dumping */ | ||
365 | tracer_enabled = 0; | ||
366 | } | ||
367 | |||
368 | static void wakeup_tracer_close(struct trace_iterator *iter) | ||
369 | { | ||
370 | /* forget about any processes we were recording */ | ||
371 | if (save_tracer_enabled) { | ||
372 | wakeup_reset(iter->tr); | ||
373 | tracer_enabled = 1; | ||
374 | } | ||
375 | } | 369 | } |
376 | 370 | ||
377 | static struct tracer wakeup_tracer __read_mostly = | 371 | static struct tracer wakeup_tracer __read_mostly = |
@@ -381,8 +375,20 @@ static struct tracer wakeup_tracer __read_mostly = | |||
381 | .reset = wakeup_tracer_reset, | 375 | .reset = wakeup_tracer_reset, |
382 | .start = wakeup_tracer_start, | 376 | .start = wakeup_tracer_start, |
383 | .stop = wakeup_tracer_stop, | 377 | .stop = wakeup_tracer_stop, |
384 | .open = wakeup_tracer_open, | 378 | .print_max = 1, |
385 | .close = wakeup_tracer_close, | 379 | #ifdef CONFIG_FTRACE_SELFTEST |
380 | .selftest = trace_selftest_startup_wakeup, | ||
381 | #endif | ||
382 | }; | ||
383 | |||
384 | static struct tracer wakeup_rt_tracer __read_mostly = | ||
385 | { | ||
386 | .name = "wakeup_rt", | ||
387 | .init = wakeup_rt_tracer_init, | ||
388 | .reset = wakeup_tracer_reset, | ||
389 | .start = wakeup_tracer_start, | ||
390 | .stop = wakeup_tracer_stop, | ||
391 | .wait_pipe = poll_wait_pipe, | ||
386 | .print_max = 1, | 392 | .print_max = 1, |
387 | #ifdef CONFIG_FTRACE_SELFTEST | 393 | #ifdef CONFIG_FTRACE_SELFTEST |
388 | .selftest = trace_selftest_startup_wakeup, | 394 | .selftest = trace_selftest_startup_wakeup, |
@@ -397,6 +403,10 @@ __init static int init_wakeup_tracer(void) | |||
397 | if (ret) | 403 | if (ret) |
398 | return ret; | 404 | return ret; |
399 | 405 | ||
406 | ret = register_tracer(&wakeup_rt_tracer); | ||
407 | if (ret) | ||
408 | return ret; | ||
409 | |||
400 | return 0; | 410 | return 0; |
401 | } | 411 | } |
402 | device_initcall(init_wakeup_tracer); | 412 | device_initcall(init_wakeup_tracer); |