aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_unlikely.c
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2008-11-12 00:14:40 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-12 05:52:02 -0500
commit52f232cb720a7babb752849cbc2cab2d24021209 (patch)
tree47c7e800549457bd5ab9b54f47729acac6e10780 /kernel/trace/trace_unlikely.c
parent1f0d69a9fc815db82f15722bf05227190b1d714d (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.c114
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
20static int unlikely_tracing_enabled __read_mostly;
21static DEFINE_MUTEX(unlikely_tracing_mutex);
22static struct trace_array *unlikely_tracer;
23
24static void
25probe_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
79static inline
80void 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
88int 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
105void 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
118static inline
119void trace_likely_condition(struct ftrace_likely_data *f, int val, int expect)
120{
121}
122#endif /* CONFIG_UNLIKELY_TRACER */
123
18void ftrace_likely_update(struct ftrace_likely_data *f, int val, int expect) 124void 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++;