diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2008-11-12 00:14:40 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-12 05:52:02 -0500 |
commit | 52f232cb720a7babb752849cbc2cab2d24021209 (patch) | |
tree | 47c7e800549457bd5ab9b54f47729acac6e10780 /kernel/trace/trace_unlikely.c | |
parent | 1f0d69a9fc815db82f15722bf05227190b1d714d (diff) |
tracing: likely/unlikely branch annotation tracer
Impact: new likely/unlikely branch tracer
This patch adds a way to record the instances of the likely() and unlikely()
branch condition annotations.
When "unlikely" is set in /debugfs/tracing/iter_ctrl the unlikely conditions
will be added to any of the ftrace tracers. The change takes effect when
a new tracer is passed into the current_tracer file.
For example:
bash-3471 [003] 357.014755: [INCORRECT] sched_info_dequeued:sched_stats.h:177
bash-3471 [003] 357.014756: [correct] update_curr:sched_fair.c:489
bash-3471 [003] 357.014758: [correct] calc_delta_fair:sched_fair.c:411
bash-3471 [003] 357.014759: [correct] account_group_exec_runtime:sched_stats.h:356
bash-3471 [003] 357.014761: [correct] update_curr:sched_fair.c:489
bash-3471 [003] 357.014763: [INCORRECT] calc_delta_fair:sched_fair.c:411
bash-3471 [003] 357.014765: [correct] calc_delta_mine:sched.c:1279
Which shows the normal tracer heading, as well as whether the condition was
correct "[correct]" or was mistaken "[INCORRECT]", followed by the function,
file name and line number.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_unlikely.c')
-rw-r--r-- | kernel/trace/trace_unlikely.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/kernel/trace/trace_unlikely.c b/kernel/trace/trace_unlikely.c index 94932696069f..7290e0e7b4e3 100644 --- a/kernel/trace/trace_unlikely.c +++ b/kernel/trace/trace_unlikely.c | |||
@@ -15,8 +15,122 @@ | |||
15 | #include <asm/local.h> | 15 | #include <asm/local.h> |
16 | #include "trace.h" | 16 | #include "trace.h" |
17 | 17 | ||
18 | #ifdef CONFIG_UNLIKELY_TRACER | ||
19 | |||
20 | static int unlikely_tracing_enabled __read_mostly; | ||
21 | static DEFINE_MUTEX(unlikely_tracing_mutex); | ||
22 | static struct trace_array *unlikely_tracer; | ||
23 | |||
24 | static void | ||
25 | probe_likely_condition(struct ftrace_likely_data *f, int val, int expect) | ||
26 | { | ||
27 | struct trace_array *tr = unlikely_tracer; | ||
28 | struct ring_buffer_event *event; | ||
29 | struct trace_unlikely *entry; | ||
30 | unsigned long flags, irq_flags; | ||
31 | int cpu, pc; | ||
32 | const char *p; | ||
33 | |||
34 | /* | ||
35 | * I would love to save just the ftrace_likely_data pointer, but | ||
36 | * this code can also be used by modules. Ugly things can happen | ||
37 | * if the module is unloaded, and then we go and read the | ||
38 | * pointer. This is slower, but much safer. | ||
39 | */ | ||
40 | |||
41 | if (unlikely(!tr)) | ||
42 | return; | ||
43 | |||
44 | local_irq_save(flags); | ||
45 | cpu = raw_smp_processor_id(); | ||
46 | if (atomic_inc_return(&tr->data[cpu]->disabled) != 1) | ||
47 | goto out; | ||
48 | |||
49 | event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), | ||
50 | &irq_flags); | ||
51 | if (!event) | ||
52 | goto out; | ||
53 | |||
54 | pc = preempt_count(); | ||
55 | entry = ring_buffer_event_data(event); | ||
56 | tracing_generic_entry_update(&entry->ent, flags, pc); | ||
57 | entry->ent.type = TRACE_UNLIKELY; | ||
58 | |||
59 | /* Strip off the path, only save the file */ | ||
60 | p = f->file + strlen(f->file); | ||
61 | while (p >= f->file && *p != '/') | ||
62 | p--; | ||
63 | p++; | ||
64 | |||
65 | strncpy(entry->func, f->func, TRACE_FUNC_SIZE); | ||
66 | strncpy(entry->file, p, TRACE_FILE_SIZE); | ||
67 | entry->func[TRACE_FUNC_SIZE] = 0; | ||
68 | entry->file[TRACE_FILE_SIZE] = 0; | ||
69 | entry->line = f->line; | ||
70 | entry->correct = val == expect; | ||
71 | |||
72 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | ||
73 | |||
74 | out: | ||
75 | atomic_dec(&tr->data[cpu]->disabled); | ||
76 | local_irq_restore(flags); | ||
77 | } | ||
78 | |||
79 | static inline | ||
80 | void trace_likely_condition(struct ftrace_likely_data *f, int val, int expect) | ||
81 | { | ||
82 | if (!unlikely_tracing_enabled) | ||
83 | return; | ||
84 | |||
85 | probe_likely_condition(f, val, expect); | ||
86 | } | ||
87 | |||
88 | int enable_unlikely_tracing(struct trace_array *tr) | ||
89 | { | ||
90 | int ret = 0; | ||
91 | |||
92 | mutex_lock(&unlikely_tracing_mutex); | ||
93 | unlikely_tracer = tr; | ||
94 | /* | ||
95 | * Must be seen before enabling. The reader is a condition | ||
96 | * where we do not need a matching rmb() | ||
97 | */ | ||
98 | smp_wmb(); | ||
99 | unlikely_tracing_enabled++; | ||
100 | mutex_unlock(&unlikely_tracing_mutex); | ||
101 | |||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | void disable_unlikely_tracing(void) | ||
106 | { | ||
107 | mutex_lock(&unlikely_tracing_mutex); | ||
108 | |||
109 | if (!unlikely_tracing_enabled) | ||
110 | goto out_unlock; | ||
111 | |||
112 | unlikely_tracing_enabled--; | ||
113 | |||
114 | out_unlock: | ||
115 | mutex_unlock(&unlikely_tracing_mutex); | ||
116 | } | ||
117 | #else | ||
118 | static inline | ||
119 | void trace_likely_condition(struct ftrace_likely_data *f, int val, int expect) | ||
120 | { | ||
121 | } | ||
122 | #endif /* CONFIG_UNLIKELY_TRACER */ | ||
123 | |||
18 | void ftrace_likely_update(struct ftrace_likely_data *f, int val, int expect) | 124 | void ftrace_likely_update(struct ftrace_likely_data *f, int val, int expect) |
19 | { | 125 | { |
126 | /* | ||
127 | * I would love to have a trace point here instead, but the | ||
128 | * trace point code is so inundated with unlikely and likely | ||
129 | * conditions that the recursive nightmare that exists is too | ||
130 | * much to try to get working. At least for now. | ||
131 | */ | ||
132 | trace_likely_condition(f, val, expect); | ||
133 | |||
20 | /* FIXME: Make this atomic! */ | 134 | /* FIXME: Make this atomic! */ |
21 | if (val == expect) | 135 | if (val == expect) |
22 | f->correct++; | 136 | f->correct++; |