diff options
| -rw-r--r-- | include/linux/sched.h | 2 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 36 |
2 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 89cd308cc7a5..471e36d30123 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1409,6 +1409,8 @@ struct task_struct { | |||
| 1409 | int curr_ret_stack; | 1409 | int curr_ret_stack; |
| 1410 | /* Stack of return addresses for return function tracing */ | 1410 | /* Stack of return addresses for return function tracing */ |
| 1411 | struct ftrace_ret_stack *ret_stack; | 1411 | struct ftrace_ret_stack *ret_stack; |
| 1412 | /* time stamp for last schedule */ | ||
| 1413 | unsigned long long ftrace_timestamp; | ||
| 1412 | /* | 1414 | /* |
| 1413 | * Number of functions that haven't been traced | 1415 | * Number of functions that haven't been traced |
| 1414 | * because of depth overrun. | 1416 | * because of depth overrun. |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index c81a759fbf76..0b90364d1a2c 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
| 30 | #include <linux/hash.h> | 30 | #include <linux/hash.h> |
| 31 | 31 | ||
| 32 | #include <trace/sched.h> | ||
| 33 | |||
| 32 | #include <asm/ftrace.h> | 34 | #include <asm/ftrace.h> |
| 33 | 35 | ||
| 34 | #include "trace.h" | 36 | #include "trace.h" |
| @@ -2590,6 +2592,31 @@ free: | |||
| 2590 | return ret; | 2592 | return ret; |
| 2591 | } | 2593 | } |
| 2592 | 2594 | ||
| 2595 | static void | ||
| 2596 | ftrace_graph_probe_sched_switch(struct rq *__rq, struct task_struct *prev, | ||
| 2597 | struct task_struct *next) | ||
| 2598 | { | ||
| 2599 | unsigned long long timestamp; | ||
| 2600 | int index; | ||
| 2601 | |||
| 2602 | timestamp = trace_clock_local(); | ||
| 2603 | |||
| 2604 | prev->ftrace_timestamp = timestamp; | ||
| 2605 | |||
| 2606 | /* only process tasks that we timestamped */ | ||
| 2607 | if (!next->ftrace_timestamp) | ||
| 2608 | return; | ||
| 2609 | |||
| 2610 | /* | ||
| 2611 | * Update all the counters in next to make up for the | ||
| 2612 | * time next was sleeping. | ||
| 2613 | */ | ||
| 2614 | timestamp -= next->ftrace_timestamp; | ||
| 2615 | |||
| 2616 | for (index = next->curr_ret_stack; index >= 0; index--) | ||
| 2617 | next->ret_stack[index].calltime += timestamp; | ||
| 2618 | } | ||
| 2619 | |||
| 2593 | /* Allocate a return stack for each task */ | 2620 | /* Allocate a return stack for each task */ |
| 2594 | static int start_graph_tracing(void) | 2621 | static int start_graph_tracing(void) |
| 2595 | { | 2622 | { |
| @@ -2611,6 +2638,13 @@ static int start_graph_tracing(void) | |||
| 2611 | ret = alloc_retstack_tasklist(ret_stack_list); | 2638 | ret = alloc_retstack_tasklist(ret_stack_list); |
| 2612 | } while (ret == -EAGAIN); | 2639 | } while (ret == -EAGAIN); |
| 2613 | 2640 | ||
| 2641 | if (!ret) { | ||
| 2642 | ret = register_trace_sched_switch(ftrace_graph_probe_sched_switch); | ||
| 2643 | if (ret) | ||
| 2644 | pr_info("ftrace_graph: Couldn't activate tracepoint" | ||
| 2645 | " probe to kernel_sched_switch\n"); | ||
| 2646 | } | ||
| 2647 | |||
| 2614 | kfree(ret_stack_list); | 2648 | kfree(ret_stack_list); |
| 2615 | return ret; | 2649 | return ret; |
| 2616 | } | 2650 | } |
| @@ -2674,6 +2708,7 @@ void unregister_ftrace_graph(void) | |||
| 2674 | mutex_lock(&ftrace_lock); | 2708 | mutex_lock(&ftrace_lock); |
| 2675 | 2709 | ||
| 2676 | atomic_dec(&ftrace_graph_active); | 2710 | atomic_dec(&ftrace_graph_active); |
| 2711 | unregister_trace_sched_switch(ftrace_graph_probe_sched_switch); | ||
| 2677 | ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; | 2712 | ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; |
| 2678 | ftrace_graph_entry = ftrace_graph_entry_stub; | 2713 | ftrace_graph_entry = ftrace_graph_entry_stub; |
| 2679 | ftrace_shutdown(FTRACE_STOP_FUNC_RET); | 2714 | ftrace_shutdown(FTRACE_STOP_FUNC_RET); |
| @@ -2694,6 +2729,7 @@ void ftrace_graph_init_task(struct task_struct *t) | |||
| 2694 | t->curr_ret_stack = -1; | 2729 | t->curr_ret_stack = -1; |
| 2695 | atomic_set(&t->tracing_graph_pause, 0); | 2730 | atomic_set(&t->tracing_graph_pause, 0); |
| 2696 | atomic_set(&t->trace_overrun, 0); | 2731 | atomic_set(&t->trace_overrun, 0); |
| 2732 | t->ftrace_timestamp = 0; | ||
| 2697 | } else | 2733 | } else |
| 2698 | t->ret_stack = NULL; | 2734 | t->ret_stack = NULL; |
| 2699 | } | 2735 | } |
