diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2008-11-16 21:22:41 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-18 05:11:00 -0500 |
commit | 0231022cc32d5f2e7f3c06b75691dda0ad6aec33 (patch) | |
tree | b45429e95fc7d52bae32e62ef514f3d7ccf62ce6 /kernel | |
parent | 0619faf657806b943e6acf51f60f1cd023a96c78 (diff) |
tracing/function-return-tracer: add the overrun field
Impact: help to find the better depth of trace
We decided to arbitrary define the depth of function return trace as
"20". Perhaps this is not enough. To help finding an optimal depth, we
measure now the overrun: the number of functions that have been missed
for the current thread. By default this is not displayed, we have to
do set a particular flag on the return tracer: echo overrun >
/debug/tracing/trace_options And the overrun will be printed on the
right.
As the trace shows below, the current 20 depth is not enough.
update_wall_time+0x37f/0x8c0 -> update_xtime_cache (345 ns) (Overruns: 2838)
update_wall_time+0x384/0x8c0 -> clocksource_get_next (1141 ns) (Overruns: 2838)
do_timer+0x23/0x100 -> update_wall_time (3882 ns) (Overruns: 2838)
tick_do_update_jiffies64+0xbf/0x160 -> do_timer (5339 ns) (Overruns: 2838)
tick_sched_timer+0x6a/0xf0 -> tick_do_update_jiffies64 (7209 ns) (Overruns: 2838)
vgacon_set_cursor_size+0x98/0x120 -> native_io_delay (2613 ns) (Overruns: 274)
vgacon_cursor+0x16e/0x1d0 -> vgacon_set_cursor_size (33151 ns) (Overruns: 274)
set_cursor+0x5f/0x80 -> vgacon_cursor (36432 ns) (Overruns: 274)
con_flush_chars+0x34/0x40 -> set_cursor (38790 ns) (Overruns: 274)
release_console_sem+0x1ec/0x230 -> up (721 ns) (Overruns: 274)
release_console_sem+0x225/0x230 -> wake_up_klogd (316 ns) (Overruns: 274)
con_flush_chars+0x39/0x40 -> release_console_sem (2996 ns) (Overruns: 274)
con_write+0x22/0x30 -> con_flush_chars (46067 ns) (Overruns: 274)
n_tty_write+0x1cc/0x360 -> con_write (292670 ns) (Overruns: 274)
smp_apic_timer_interrupt+0x2a/0x90 -> native_apic_mem_write (330 ns) (Overruns: 274)
irq_enter+0x17/0x70 -> idle_cpu (413 ns) (Overruns: 274)
smp_apic_timer_interrupt+0x2f/0x90 -> irq_enter (1525 ns) (Overruns: 274)
ktime_get_ts+0x40/0x70 -> getnstimeofday (465 ns) (Overruns: 274)
ktime_get_ts+0x60/0x70 -> set_normalized_timespec (436 ns) (Overruns: 274)
ktime_get+0x16/0x30 -> ktime_get_ts (2501 ns) (Overruns: 274)
hrtimer_interrupt+0x77/0x1a0 -> ktime_get (3439 ns) (Overruns: 274)
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace.c | 1 | ||||
-rw-r--r-- | kernel/trace/trace.h | 1 | ||||
-rw-r--r-- | kernel/trace/trace_functions_return.c | 38 |
3 files changed, 34 insertions, 6 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9531fddcfb8d..e97c29a6e7b0 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -853,6 +853,7 @@ static void __trace_function_return(struct trace_array *tr, | |||
853 | entry->parent_ip = trace->ret; | 853 | entry->parent_ip = trace->ret; |
854 | entry->rettime = trace->rettime; | 854 | entry->rettime = trace->rettime; |
855 | entry->calltime = trace->calltime; | 855 | entry->calltime = trace->calltime; |
856 | entry->overrun = trace->overrun; | ||
856 | ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags); | 857 | ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags); |
857 | } | 858 | } |
858 | #endif | 859 | #endif |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 9d22618bf99f..2cb12fd98f6b 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -60,6 +60,7 @@ struct ftrace_ret_entry { | |||
60 | unsigned long parent_ip; | 60 | unsigned long parent_ip; |
61 | unsigned long long calltime; | 61 | unsigned long long calltime; |
62 | unsigned long long rettime; | 62 | unsigned long long rettime; |
63 | unsigned long overrun; | ||
63 | }; | 64 | }; |
64 | extern struct tracer boot_tracer; | 65 | extern struct tracer boot_tracer; |
65 | 66 | ||
diff --git a/kernel/trace/trace_functions_return.c b/kernel/trace/trace_functions_return.c index a68564af022b..e00d64509c9c 100644 --- a/kernel/trace/trace_functions_return.c +++ b/kernel/trace/trace_functions_return.c | |||
@@ -14,6 +14,19 @@ | |||
14 | #include "trace.h" | 14 | #include "trace.h" |
15 | 15 | ||
16 | 16 | ||
17 | #define TRACE_RETURN_PRINT_OVERRUN 0x1 | ||
18 | static struct tracer_opt trace_opts[] = { | ||
19 | /* Display overruns or not */ | ||
20 | { TRACER_OPT(overrun, TRACE_RETURN_PRINT_OVERRUN) }, | ||
21 | { } /* Empty entry */ | ||
22 | }; | ||
23 | |||
24 | static struct tracer_flags tracer_flags = { | ||
25 | .val = 0, /* Don't display overruns by default */ | ||
26 | .opts = trace_opts | ||
27 | }; | ||
28 | |||
29 | |||
17 | static int return_trace_init(struct trace_array *tr) | 30 | static int return_trace_init(struct trace_array *tr) |
18 | { | 31 | { |
19 | int cpu; | 32 | int cpu; |
@@ -42,26 +55,39 @@ print_return_function(struct trace_iterator *iter) | |||
42 | ret = trace_seq_printf(s, "%pF -> ", (void *)field->parent_ip); | 55 | ret = trace_seq_printf(s, "%pF -> ", (void *)field->parent_ip); |
43 | if (!ret) | 56 | if (!ret) |
44 | return TRACE_TYPE_PARTIAL_LINE; | 57 | return TRACE_TYPE_PARTIAL_LINE; |
58 | |||
45 | ret = seq_print_ip_sym(s, field->ip, | 59 | ret = seq_print_ip_sym(s, field->ip, |
46 | trace_flags & TRACE_ITER_SYM_MASK); | 60 | trace_flags & TRACE_ITER_SYM_MASK); |
47 | if (!ret) | 61 | if (!ret) |
48 | return TRACE_TYPE_PARTIAL_LINE; | 62 | return TRACE_TYPE_PARTIAL_LINE; |
49 | ret = trace_seq_printf(s, " (%llu ns)\n", | 63 | |
64 | ret = trace_seq_printf(s, " (%llu ns)", | ||
50 | field->rettime - field->calltime); | 65 | field->rettime - field->calltime); |
51 | if (!ret) | 66 | if (!ret) |
52 | return TRACE_TYPE_PARTIAL_LINE; | 67 | return TRACE_TYPE_PARTIAL_LINE; |
53 | else | 68 | |
54 | return TRACE_TYPE_HANDLED; | 69 | if (tracer_flags.val & TRACE_RETURN_PRINT_OVERRUN) { |
70 | ret = trace_seq_printf(s, " (Overruns: %lu)", | ||
71 | field->overrun); | ||
72 | if (!ret) | ||
73 | return TRACE_TYPE_PARTIAL_LINE; | ||
74 | } | ||
75 | |||
76 | ret = trace_seq_printf(s, "\n"); | ||
77 | if (!ret) | ||
78 | return TRACE_TYPE_PARTIAL_LINE; | ||
79 | |||
80 | return TRACE_TYPE_HANDLED; | ||
55 | } | 81 | } |
56 | return TRACE_TYPE_UNHANDLED; | 82 | return TRACE_TYPE_UNHANDLED; |
57 | } | 83 | } |
58 | 84 | ||
59 | static struct tracer return_trace __read_mostly = | 85 | static struct tracer return_trace __read_mostly = { |
60 | { | ||
61 | .name = "return", | 86 | .name = "return", |
62 | .init = return_trace_init, | 87 | .init = return_trace_init, |
63 | .reset = return_trace_reset, | 88 | .reset = return_trace_reset, |
64 | .print_line = print_return_function | 89 | .print_line = print_return_function, |
90 | .flags = &tracer_flags, | ||
65 | }; | 91 | }; |
66 | 92 | ||
67 | static __init int init_return_trace(void) | 93 | static __init int init_return_trace(void) |