#include <asm/local.h>
#include "trace.h"
+#include "trace_stat.h"
#include "trace_output.h"
-static struct tracer branch_trace;
-
#ifdef CONFIG_BRANCH_TRACER
+static struct tracer branch_trace;
static int branch_tracing_enabled __read_mostly;
static DEFINE_MUTEX(branch_tracing_mutex);
static void
probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
{
+ struct ftrace_event_call *call = &event_branch;
struct trace_array *tr = branch_tracer;
struct ring_buffer_event *event;
struct trace_branch *entry;
- unsigned long flags, irq_flags;
+ struct ring_buffer *buffer;
+ unsigned long flags;
int cpu, pc;
const char *p;
if (atomic_inc_return(&tr->data[cpu]->disabled) != 1)
goto out;
- event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
- &irq_flags);
+ pc = preempt_count();
+ buffer = tr->buffer;
+ event = trace_buffer_lock_reserve(buffer, TRACE_BRANCH,
+ sizeof(*entry), flags, pc);
if (!event)
goto out;
- pc = preempt_count();
entry = ring_buffer_event_data(event);
- tracing_generic_entry_update(&entry->ent, flags, pc);
- entry->ent.type = TRACE_BRANCH;
/* Strip off the path, only save the file */
p = f->file + strlen(f->file);
entry->line = f->line;
entry->correct = val == expect;
- ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
+ if (!filter_check_discard(call, entry, buffer, event))
+ ring_buffer_unlock_commit(buffer, event);
out:
atomic_dec(&tr->data[cpu]->disabled);
int enable_branch_tracing(struct trace_array *tr)
{
- int ret = 0;
-
mutex_lock(&branch_tracing_mutex);
branch_tracer = tr;
/*
branch_tracing_enabled++;
mutex_unlock(&branch_tracing_mutex);
- return ret;
+ return 0;
}
void disable_branch_tracing(void)
static int branch_trace_init(struct trace_array *tr)
{
- int cpu;
-
- for_each_online_cpu(cpu)
- tracing_reset(tr, cpu);
-
start_branch_trace(tr);
return 0;
}
stop_branch_trace(tr);
}
-static int
-trace_print_print(struct trace_seq *s, struct trace_entry *entry, int flags)
-{
- struct print_entry *field;
-
- trace_assign_type(field, entry);
-
- if (seq_print_ip_sym(s, field->ip, flags))
- goto partial;
-
- if (trace_seq_printf(s, ": %s", field->buf))
- goto partial;
-
- partial:
- return TRACE_TYPE_PARTIAL_LINE;
-}
-
-static int
-trace_branch_print(struct trace_seq *s, struct trace_entry *entry, int flags)
+static enum print_line_t trace_branch_print(struct trace_iterator *iter,
+ int flags)
{
struct trace_branch *field;
- trace_assign_type(field, entry);
+ trace_assign_type(field, iter->ent);
- if (trace_seq_printf(s, "[%s] %s:%s:%d\n",
+ if (trace_seq_printf(&iter->seq, "[%s] %s:%s:%d\n",
field->correct ? " ok " : " MISS ",
field->func,
field->file,
field->line))
return TRACE_TYPE_PARTIAL_LINE;
- return 0;
+ return TRACE_TYPE_HANDLED;
}
+static void branch_print_header(struct seq_file *s)
+{
+ seq_puts(s, "# TASK-PID CPU# TIMESTAMP CORRECT"
+ " FUNC:FILE:LINE\n");
+ seq_puts(s, "# | | | | | "
+ " |\n");
+}
static struct trace_event trace_branch_event = {
- .type = TRACE_BRANCH,
+ .type = TRACE_BRANCH,
.trace = trace_branch_print,
- .latency_trace = trace_branch_print,
- .raw = trace_nop_print,
- .hex = trace_nop_print,
- .binary = trace_nop_print,
};
+static struct tracer branch_trace __read_mostly =
+{
+ .name = "branch",
+ .init = branch_trace_init,
+ .reset = branch_trace_reset,
+#ifdef CONFIG_FTRACE_SELFTEST
+ .selftest = trace_selftest_startup_branch,
+#endif /* CONFIG_FTRACE_SELFTEST */
+ .print_header = branch_print_header,
+};
+
+__init static int init_branch_tracer(void)
+{
+ int ret;
+
+ ret = register_ftrace_event(&trace_branch_event);
+ if (!ret) {
+ printk(KERN_WARNING "Warning: could not register "
+ "branch events\n");
+ return 1;
+ }
+ return register_tracer(&branch_trace);
+}
+device_initcall(init_branch_tracer);
+
#else
static inline
void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect)
return 0;
}
-static void *annotated_branch_stat_start(void)
+static void *annotated_branch_stat_start(struct tracer_stat *trace)
{
return __start_annotated_branch_profile;
}
return -1;
if (percent_a > percent_b)
return 1;
- else
- return 0;
+
+ if (a->incorrect < b->incorrect)
+ return -1;
+ if (a->incorrect > b->incorrect)
+ return 1;
+
+ /*
+ * Since the above shows worse (incorrect) cases
+ * first, we continue that by showing best (correct)
+ * cases last.
+ */
+ if (a->correct > b->correct)
+ return -1;
+ if (a->correct < b->correct)
+ return 1;
+
+ return 0;
}
+static struct tracer_stat annotated_branch_stats = {
+ .name = "branch_annotated",
+ .stat_start = annotated_branch_stat_start,
+ .stat_next = annotated_branch_stat_next,
+ .stat_cmp = annotated_branch_stat_cmp,
+ .stat_headers = annotated_branch_stat_headers,
+ .stat_show = branch_stat_show
+};
+
+__init static int init_annotated_branch_stats(void)
+{
+ int ret;
+
+ ret = register_stat_tracer(&annotated_branch_stats);
+ if (!ret) {
+ printk(KERN_WARNING "Warning: could not register "
+ "annotated branches stats\n");
+ return 1;
+ }
+ return 0;
+}
+fs_initcall(init_annotated_branch_stats);
+
#ifdef CONFIG_PROFILE_ALL_BRANCHES
extern unsigned long __start_branch_profile[];
return 0;
}
-static void *all_branch_stat_start(void)
+static void *all_branch_stat_start(struct tracer_stat *trace)
{
return __start_branch_profile;
}
return p;
}
-static struct tracer_stat branch_stats[] = {
- {.name = "annotated",
- .stat_start = annotated_branch_stat_start,
- .stat_next = annotated_branch_stat_next,
- .stat_cmp = annotated_branch_stat_cmp,
- .stat_headers = annotated_branch_stat_headers,
- .stat_show = branch_stat_show},
-
- {.name = "all",
+static struct tracer_stat all_branch_stats = {
+ .name = "branch_all",
.stat_start = all_branch_stat_start,
.stat_next = all_branch_stat_next,
.stat_headers = all_branch_stat_headers,
- .stat_show = branch_stat_show},
-
- { }
-};
-#else
-static struct tracer_stat branch_stats[] = {
- {.name = "annotated",
- .stat_start = annotated_branch_stat_start,
- .stat_next = annotated_branch_stat_next,
- .stat_cmp = annotated_branch_stat_cmp,
- .stat_headers = annotated_branch_stat_headers,
- .stat_show = branch_stat_show},
-
- { }
-};
-#endif /* CONFIG_PROFILE_ALL_BRANCHES */
-
-
-static struct tracer branch_trace __read_mostly =
-{
- .name = "branch",
-#ifdef CONFIG_BRANCH_TRACER
- .init = branch_trace_init,
- .reset = branch_trace_reset,
-#ifdef CONFIG_FTRACE_SELFTEST
- .selftest = trace_selftest_startup_branch,
-#endif /* CONFIG_FTRACE_SELFTEST */
-#endif
- .stats = branch_stats
+ .stat_show = branch_stat_show
};
-__init static int init_branch_trace(void)
+__init static int all_annotated_branch_stats(void)
{
-#ifdef CONFIG_BRANCH_TRACER
int ret;
- ret = register_ftrace_event(&trace_branch_event);
+
+ ret = register_stat_tracer(&all_branch_stats);
if (!ret) {
- printk(KERN_WARNING "Warning: could not register branch events\n");
+ printk(KERN_WARNING "Warning: could not register "
+ "all branches stats\n");
return 1;
}
-#endif
-
- return register_tracer(&branch_trace);
+ return 0;
}
-device_initcall(init_branch_trace);
+fs_initcall(all_annotated_branch_stats);
+#endif /* CONFIG_PROFILE_ALL_BRANCHES */