diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/ftrace.c | 36 |
1 files changed, 36 insertions, 0 deletions
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 | } |