194b80ffdSSteven Rostedt /* 294b80ffdSSteven Rostedt * unlikely profiler 394b80ffdSSteven Rostedt * 494b80ffdSSteven Rostedt * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com> 594b80ffdSSteven Rostedt */ 694b80ffdSSteven Rostedt #include <linux/kallsyms.h> 794b80ffdSSteven Rostedt #include <linux/seq_file.h> 894b80ffdSSteven Rostedt #include <linux/spinlock.h> 965c6dc6aSFrederic Weisbecker #include <linux/irqflags.h> 1094b80ffdSSteven Rostedt #include <linux/uaccess.h> 1194b80ffdSSteven Rostedt #include <linux/module.h> 1294b80ffdSSteven Rostedt #include <linux/ftrace.h> 1394b80ffdSSteven Rostedt #include <linux/hash.h> 1494b80ffdSSteven Rostedt #include <linux/fs.h> 1594b80ffdSSteven Rostedt #include <asm/local.h> 16f633cef0SSteven Rostedt 1794b80ffdSSteven Rostedt #include "trace.h" 18002bb86dSFrederic Weisbecker #include "trace_stat.h" 19f633cef0SSteven Rostedt #include "trace_output.h" 2094b80ffdSSteven Rostedt 2194b80ffdSSteven Rostedt #ifdef CONFIG_BRANCH_TRACER 2294b80ffdSSteven Rostedt 23002bb86dSFrederic Weisbecker static struct tracer branch_trace; 2494b80ffdSSteven Rostedt static int branch_tracing_enabled __read_mostly; 2594b80ffdSSteven Rostedt static DEFINE_MUTEX(branch_tracing_mutex); 26e302cf3fSFrederic Weisbecker 2794b80ffdSSteven Rostedt static struct trace_array *branch_tracer; 2894b80ffdSSteven Rostedt 2994b80ffdSSteven Rostedt static void 3094b80ffdSSteven Rostedt probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) 3194b80ffdSSteven Rostedt { 322425bcb9SSteven Rostedt (Red Hat) struct trace_event_call *call = &event_branch; 3394b80ffdSSteven Rostedt struct trace_array *tr = branch_tracer; 34a7603ff4SSteven Rostedt struct trace_array_cpu *data; 3594b80ffdSSteven Rostedt struct ring_buffer_event *event; 3694b80ffdSSteven Rostedt struct trace_branch *entry; 378f6e8a31SSteven Rostedt struct ring_buffer *buffer; 380a987751SArnaldo Carvalho de Melo unsigned long flags; 396224beb1SSteven Rostedt (Red Hat) int pc; 4094b80ffdSSteven Rostedt const char *p; 4194b80ffdSSteven Rostedt 426224beb1SSteven Rostedt (Red Hat) if (current->trace_recursion & TRACE_BRANCH_BIT) 436224beb1SSteven Rostedt (Red Hat) return; 446224beb1SSteven Rostedt (Red Hat) 4594b80ffdSSteven Rostedt /* 4694b80ffdSSteven Rostedt * I would love to save just the ftrace_likely_data pointer, but 4794b80ffdSSteven Rostedt * this code can also be used by modules. Ugly things can happen 4894b80ffdSSteven Rostedt * if the module is unloaded, and then we go and read the 4994b80ffdSSteven Rostedt * pointer. This is slower, but much safer. 5094b80ffdSSteven Rostedt */ 5194b80ffdSSteven Rostedt 5294b80ffdSSteven Rostedt if (unlikely(!tr)) 5394b80ffdSSteven Rostedt return; 5494b80ffdSSteven Rostedt 556224beb1SSteven Rostedt (Red Hat) raw_local_irq_save(flags); 566224beb1SSteven Rostedt (Red Hat) current->trace_recursion |= TRACE_BRANCH_BIT; 576224beb1SSteven Rostedt (Red Hat) data = this_cpu_ptr(tr->trace_buffer.data); 586224beb1SSteven Rostedt (Red Hat) if (atomic_read(&data->disabled)) 5994b80ffdSSteven Rostedt goto out; 6094b80ffdSSteven Rostedt 6151a763ddSArnaldo Carvalho de Melo pc = preempt_count(); 62153e8ed9SSteven Rostedt (Red Hat) buffer = tr->trace_buffer.buffer; 638f6e8a31SSteven Rostedt event = trace_buffer_lock_reserve(buffer, TRACE_BRANCH, 6451a763ddSArnaldo Carvalho de Melo sizeof(*entry), flags, pc); 6594b80ffdSSteven Rostedt if (!event) 6694b80ffdSSteven Rostedt goto out; 6794b80ffdSSteven Rostedt 6894b80ffdSSteven Rostedt entry = ring_buffer_event_data(event); 6994b80ffdSSteven Rostedt 7094b80ffdSSteven Rostedt /* Strip off the path, only save the file */ 7194b80ffdSSteven Rostedt p = f->file + strlen(f->file); 7294b80ffdSSteven Rostedt while (p >= f->file && *p != '/') 7394b80ffdSSteven Rostedt p--; 7494b80ffdSSteven Rostedt p++; 7594b80ffdSSteven Rostedt 7694b80ffdSSteven Rostedt strncpy(entry->func, f->func, TRACE_FUNC_SIZE); 7794b80ffdSSteven Rostedt strncpy(entry->file, p, TRACE_FILE_SIZE); 7894b80ffdSSteven Rostedt entry->func[TRACE_FUNC_SIZE] = 0; 7994b80ffdSSteven Rostedt entry->file[TRACE_FILE_SIZE] = 0; 8094b80ffdSSteven Rostedt entry->line = f->line; 8194b80ffdSSteven Rostedt entry->correct = val == expect; 8294b80ffdSSteven Rostedt 83f306cc82STom Zanussi if (!call_filter_check_discard(call, entry, buffer, event)) 847ffbd48dSSteven Rostedt __buffer_unlock_commit(buffer, event); 8594b80ffdSSteven Rostedt 8694b80ffdSSteven Rostedt out: 876224beb1SSteven Rostedt (Red Hat) current->trace_recursion &= ~TRACE_BRANCH_BIT; 886224beb1SSteven Rostedt (Red Hat) raw_local_irq_restore(flags); 8994b80ffdSSteven Rostedt } 9094b80ffdSSteven Rostedt 9194b80ffdSSteven Rostedt static inline 9294b80ffdSSteven Rostedt void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect) 9394b80ffdSSteven Rostedt { 9494b80ffdSSteven Rostedt if (!branch_tracing_enabled) 9594b80ffdSSteven Rostedt return; 9694b80ffdSSteven Rostedt 9794b80ffdSSteven Rostedt probe_likely_condition(f, val, expect); 9894b80ffdSSteven Rostedt } 9994b80ffdSSteven Rostedt 10094b80ffdSSteven Rostedt int enable_branch_tracing(struct trace_array *tr) 10194b80ffdSSteven Rostedt { 10294b80ffdSSteven Rostedt mutex_lock(&branch_tracing_mutex); 10394b80ffdSSteven Rostedt branch_tracer = tr; 10494b80ffdSSteven Rostedt /* 10594b80ffdSSteven Rostedt * Must be seen before enabling. The reader is a condition 10694b80ffdSSteven Rostedt * where we do not need a matching rmb() 10794b80ffdSSteven Rostedt */ 10894b80ffdSSteven Rostedt smp_wmb(); 10994b80ffdSSteven Rostedt branch_tracing_enabled++; 11094b80ffdSSteven Rostedt mutex_unlock(&branch_tracing_mutex); 11194b80ffdSSteven Rostedt 112f54fc98aSWenji Huang return 0; 11394b80ffdSSteven Rostedt } 11494b80ffdSSteven Rostedt 11594b80ffdSSteven Rostedt void disable_branch_tracing(void) 11694b80ffdSSteven Rostedt { 11794b80ffdSSteven Rostedt mutex_lock(&branch_tracing_mutex); 11894b80ffdSSteven Rostedt 11994b80ffdSSteven Rostedt if (!branch_tracing_enabled) 12094b80ffdSSteven Rostedt goto out_unlock; 12194b80ffdSSteven Rostedt 12294b80ffdSSteven Rostedt branch_tracing_enabled--; 12394b80ffdSSteven Rostedt 12494b80ffdSSteven Rostedt out_unlock: 12594b80ffdSSteven Rostedt mutex_unlock(&branch_tracing_mutex); 12694b80ffdSSteven Rostedt } 12794b80ffdSSteven Rostedt 1281c80025aSFrederic Weisbecker static int branch_trace_init(struct trace_array *tr) 12994b80ffdSSteven Rostedt { 13030616929SDmitry Safonov return enable_branch_tracing(tr); 13194b80ffdSSteven Rostedt } 13294b80ffdSSteven Rostedt 13394b80ffdSSteven Rostedt static void branch_trace_reset(struct trace_array *tr) 13494b80ffdSSteven Rostedt { 13530616929SDmitry Safonov disable_branch_tracing(); 13694b80ffdSSteven Rostedt } 13794b80ffdSSteven Rostedt 138ae7462b4SArnaldo Carvalho de Melo static enum print_line_t trace_branch_print(struct trace_iterator *iter, 139a9a57763SSteven Rostedt int flags, struct trace_event *event) 140f633cef0SSteven Rostedt { 141f633cef0SSteven Rostedt struct trace_branch *field; 142f633cef0SSteven Rostedt 1432c9b238eSArnaldo Carvalho de Melo trace_assign_type(field, iter->ent); 144f633cef0SSteven Rostedt 1457d40f671SSteven Rostedt (Red Hat) trace_seq_printf(&iter->seq, "[%s] %s:%s:%d\n", 146f633cef0SSteven Rostedt field->correct ? " ok " : " MISS ", 147f633cef0SSteven Rostedt field->func, 148f633cef0SSteven Rostedt field->file, 1497d40f671SSteven Rostedt (Red Hat) field->line); 150f633cef0SSteven Rostedt 1517d40f671SSteven Rostedt (Red Hat) return trace_handle_return(&iter->seq); 152f633cef0SSteven Rostedt } 153f633cef0SSteven Rostedt 154557055beSZhaolei static void branch_print_header(struct seq_file *s) 155557055beSZhaolei { 156557055beSZhaolei seq_puts(s, "# TASK-PID CPU# TIMESTAMP CORRECT" 157d79ac28fSRasmus Villemoes " FUNC:FILE:LINE\n" 158d79ac28fSRasmus Villemoes "# | | | | | " 159557055beSZhaolei " |\n"); 160557055beSZhaolei } 161e302cf3fSFrederic Weisbecker 162a9a57763SSteven Rostedt static struct trace_event_functions trace_branch_funcs = { 163a9a57763SSteven Rostedt .trace = trace_branch_print, 164a9a57763SSteven Rostedt }; 165a9a57763SSteven Rostedt 166f633cef0SSteven Rostedt static struct trace_event trace_branch_event = { 167f633cef0SSteven Rostedt .type = TRACE_BRANCH, 168a9a57763SSteven Rostedt .funcs = &trace_branch_funcs, 169f633cef0SSteven Rostedt }; 170f633cef0SSteven Rostedt 171002bb86dSFrederic Weisbecker static struct tracer branch_trace __read_mostly = 172002bb86dSFrederic Weisbecker { 173002bb86dSFrederic Weisbecker .name = "branch", 174002bb86dSFrederic Weisbecker .init = branch_trace_init, 175002bb86dSFrederic Weisbecker .reset = branch_trace_reset, 176002bb86dSFrederic Weisbecker #ifdef CONFIG_FTRACE_SELFTEST 177002bb86dSFrederic Weisbecker .selftest = trace_selftest_startup_branch, 178002bb86dSFrederic Weisbecker #endif /* CONFIG_FTRACE_SELFTEST */ 179557055beSZhaolei .print_header = branch_print_header, 180002bb86dSFrederic Weisbecker }; 181002bb86dSFrederic Weisbecker 182002bb86dSFrederic Weisbecker __init static int init_branch_tracer(void) 183002bb86dSFrederic Weisbecker { 184002bb86dSFrederic Weisbecker int ret; 185002bb86dSFrederic Weisbecker 1869023c930SSteven Rostedt (Red Hat) ret = register_trace_event(&trace_branch_event); 187002bb86dSFrederic Weisbecker if (!ret) { 188002bb86dSFrederic Weisbecker printk(KERN_WARNING "Warning: could not register " 189002bb86dSFrederic Weisbecker "branch events\n"); 190002bb86dSFrederic Weisbecker return 1; 191002bb86dSFrederic Weisbecker } 192002bb86dSFrederic Weisbecker return register_tracer(&branch_trace); 193002bb86dSFrederic Weisbecker } 1946f415672SSteven Rostedt core_initcall(init_branch_tracer); 195002bb86dSFrederic Weisbecker 19694b80ffdSSteven Rostedt #else 19794b80ffdSSteven Rostedt static inline 19894b80ffdSSteven Rostedt void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect) 19994b80ffdSSteven Rostedt { 20094b80ffdSSteven Rostedt } 20194b80ffdSSteven Rostedt #endif /* CONFIG_BRANCH_TRACER */ 20294b80ffdSSteven Rostedt 20394b80ffdSSteven Rostedt void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect) 20494b80ffdSSteven Rostedt { 20594b80ffdSSteven Rostedt /* 20694b80ffdSSteven Rostedt * I would love to have a trace point here instead, but the 20794b80ffdSSteven Rostedt * trace point code is so inundated with unlikely and likely 20894b80ffdSSteven Rostedt * conditions that the recursive nightmare that exists is too 20994b80ffdSSteven Rostedt * much to try to get working. At least for now. 21094b80ffdSSteven Rostedt */ 21194b80ffdSSteven Rostedt trace_likely_condition(f, val, expect); 21294b80ffdSSteven Rostedt 21394b80ffdSSteven Rostedt /* FIXME: Make this atomic! */ 21494b80ffdSSteven Rostedt if (val == expect) 21594b80ffdSSteven Rostedt f->correct++; 21694b80ffdSSteven Rostedt else 21794b80ffdSSteven Rostedt f->incorrect++; 21894b80ffdSSteven Rostedt } 21994b80ffdSSteven Rostedt EXPORT_SYMBOL(ftrace_likely_update); 22094b80ffdSSteven Rostedt 221e302cf3fSFrederic Weisbecker extern unsigned long __start_annotated_branch_profile[]; 222e302cf3fSFrederic Weisbecker extern unsigned long __stop_annotated_branch_profile[]; 22394b80ffdSSteven Rostedt 224e302cf3fSFrederic Weisbecker static int annotated_branch_stat_headers(struct seq_file *m) 22594b80ffdSSteven Rostedt { 226d79ac28fSRasmus Villemoes seq_puts(m, " correct incorrect % " 227d79ac28fSRasmus Villemoes " Function " 22894b80ffdSSteven Rostedt " File Line\n" 22994b80ffdSSteven Rostedt " ------- --------- - " 23094b80ffdSSteven Rostedt " -------- " 23194b80ffdSSteven Rostedt " ---- ----\n"); 23294b80ffdSSteven Rostedt return 0; 23394b80ffdSSteven Rostedt } 23494b80ffdSSteven Rostedt 235e302cf3fSFrederic Weisbecker static inline long get_incorrect_percent(struct ftrace_branch_data *p) 236e302cf3fSFrederic Weisbecker { 237e302cf3fSFrederic Weisbecker long percent; 238e302cf3fSFrederic Weisbecker 239e302cf3fSFrederic Weisbecker if (p->correct) { 240e302cf3fSFrederic Weisbecker percent = p->incorrect * 100; 241e302cf3fSFrederic Weisbecker percent /= p->correct + p->incorrect; 242e302cf3fSFrederic Weisbecker } else 243e302cf3fSFrederic Weisbecker percent = p->incorrect ? 100 : -1; 244e302cf3fSFrederic Weisbecker 245e302cf3fSFrederic Weisbecker return percent; 246e302cf3fSFrederic Weisbecker } 247e302cf3fSFrederic Weisbecker 248e302cf3fSFrederic Weisbecker static int branch_stat_show(struct seq_file *m, void *v) 249e302cf3fSFrederic Weisbecker { 250e302cf3fSFrederic Weisbecker struct ftrace_branch_data *p = v; 251e302cf3fSFrederic Weisbecker const char *f; 252e302cf3fSFrederic Weisbecker long percent; 253e302cf3fSFrederic Weisbecker 25494b80ffdSSteven Rostedt /* Only print the file, not the path */ 25594b80ffdSSteven Rostedt f = p->file + strlen(p->file); 25694b80ffdSSteven Rostedt while (f >= p->file && *f != '/') 25794b80ffdSSteven Rostedt f--; 25894b80ffdSSteven Rostedt f++; 25994b80ffdSSteven Rostedt 2602bcd521aSSteven Rostedt /* 2612bcd521aSSteven Rostedt * The miss is overlayed on correct, and hit on incorrect. 2622bcd521aSSteven Rostedt */ 263e302cf3fSFrederic Weisbecker percent = get_incorrect_percent(p); 26494b80ffdSSteven Rostedt 265bac28bfeSSteven Rostedt seq_printf(m, "%8lu %8lu ", p->correct, p->incorrect); 266bac28bfeSSteven Rostedt if (percent < 0) 267fa6f0cc7SRasmus Villemoes seq_puts(m, " X "); 268bac28bfeSSteven Rostedt else 269bac28bfeSSteven Rostedt seq_printf(m, "%3ld ", percent); 27094b80ffdSSteven Rostedt seq_printf(m, "%-30.30s %-20.20s %d\n", p->func, f, p->line); 27194b80ffdSSteven Rostedt return 0; 27294b80ffdSSteven Rostedt } 27394b80ffdSSteven Rostedt 27442548008SSteven Rostedt static void *annotated_branch_stat_start(struct tracer_stat *trace) 27594b80ffdSSteven Rostedt { 276e302cf3fSFrederic Weisbecker return __start_annotated_branch_profile; 27794b80ffdSSteven Rostedt } 27894b80ffdSSteven Rostedt 279e302cf3fSFrederic Weisbecker static void * 280e302cf3fSFrederic Weisbecker annotated_branch_stat_next(void *v, int idx) 281e302cf3fSFrederic Weisbecker { 282e302cf3fSFrederic Weisbecker struct ftrace_branch_data *p = v; 283e302cf3fSFrederic Weisbecker 284e302cf3fSFrederic Weisbecker ++p; 285e302cf3fSFrederic Weisbecker 286e302cf3fSFrederic Weisbecker if ((void *)p >= (void *)__stop_annotated_branch_profile) 287e302cf3fSFrederic Weisbecker return NULL; 288e302cf3fSFrederic Weisbecker 289e302cf3fSFrederic Weisbecker return p; 29094b80ffdSSteven Rostedt } 29194b80ffdSSteven Rostedt 292e302cf3fSFrederic Weisbecker static int annotated_branch_stat_cmp(void *p1, void *p2) 29394b80ffdSSteven Rostedt { 294e302cf3fSFrederic Weisbecker struct ftrace_branch_data *a = p1; 295e302cf3fSFrederic Weisbecker struct ftrace_branch_data *b = p2; 29694b80ffdSSteven Rostedt 297e302cf3fSFrederic Weisbecker long percent_a, percent_b; 29894b80ffdSSteven Rostedt 299e302cf3fSFrederic Weisbecker percent_a = get_incorrect_percent(a); 300e302cf3fSFrederic Weisbecker percent_b = get_incorrect_percent(b); 30194b80ffdSSteven Rostedt 302e302cf3fSFrederic Weisbecker if (percent_a < percent_b) 303e302cf3fSFrederic Weisbecker return -1; 304e302cf3fSFrederic Weisbecker if (percent_a > percent_b) 305e302cf3fSFrederic Weisbecker return 1; 306ede55c9dSSteven Rostedt 307ede55c9dSSteven Rostedt if (a->incorrect < b->incorrect) 308ede55c9dSSteven Rostedt return -1; 309ede55c9dSSteven Rostedt if (a->incorrect > b->incorrect) 310ede55c9dSSteven Rostedt return 1; 311ede55c9dSSteven Rostedt 312ede55c9dSSteven Rostedt /* 313ede55c9dSSteven Rostedt * Since the above shows worse (incorrect) cases 314ede55c9dSSteven Rostedt * first, we continue that by showing best (correct) 315ede55c9dSSteven Rostedt * cases last. 316ede55c9dSSteven Rostedt */ 317ede55c9dSSteven Rostedt if (a->correct > b->correct) 318ede55c9dSSteven Rostedt return -1; 319ede55c9dSSteven Rostedt if (a->correct < b->correct) 320ede55c9dSSteven Rostedt return 1; 321ede55c9dSSteven Rostedt 32294b80ffdSSteven Rostedt return 0; 32394b80ffdSSteven Rostedt } 32494b80ffdSSteven Rostedt 325002bb86dSFrederic Weisbecker static struct tracer_stat annotated_branch_stats = { 326002bb86dSFrederic Weisbecker .name = "branch_annotated", 327002bb86dSFrederic Weisbecker .stat_start = annotated_branch_stat_start, 328002bb86dSFrederic Weisbecker .stat_next = annotated_branch_stat_next, 329002bb86dSFrederic Weisbecker .stat_cmp = annotated_branch_stat_cmp, 330002bb86dSFrederic Weisbecker .stat_headers = annotated_branch_stat_headers, 331002bb86dSFrederic Weisbecker .stat_show = branch_stat_show 332002bb86dSFrederic Weisbecker }; 333002bb86dSFrederic Weisbecker 334002bb86dSFrederic Weisbecker __init static int init_annotated_branch_stats(void) 335002bb86dSFrederic Weisbecker { 336002bb86dSFrederic Weisbecker int ret; 337002bb86dSFrederic Weisbecker 338002bb86dSFrederic Weisbecker ret = register_stat_tracer(&annotated_branch_stats); 339002bb86dSFrederic Weisbecker if (!ret) { 340002bb86dSFrederic Weisbecker printk(KERN_WARNING "Warning: could not register " 341002bb86dSFrederic Weisbecker "annotated branches stats\n"); 342002bb86dSFrederic Weisbecker return 1; 343002bb86dSFrederic Weisbecker } 344002bb86dSFrederic Weisbecker return 0; 345002bb86dSFrederic Weisbecker } 346002bb86dSFrederic Weisbecker fs_initcall(init_annotated_branch_stats); 347002bb86dSFrederic Weisbecker 348e302cf3fSFrederic Weisbecker #ifdef CONFIG_PROFILE_ALL_BRANCHES 349e302cf3fSFrederic Weisbecker 350e302cf3fSFrederic Weisbecker extern unsigned long __start_branch_profile[]; 351e302cf3fSFrederic Weisbecker extern unsigned long __stop_branch_profile[]; 352e302cf3fSFrederic Weisbecker 353e302cf3fSFrederic Weisbecker static int all_branch_stat_headers(struct seq_file *m) 354e302cf3fSFrederic Weisbecker { 355d79ac28fSRasmus Villemoes seq_puts(m, " miss hit % " 356d79ac28fSRasmus Villemoes " Function " 357e302cf3fSFrederic Weisbecker " File Line\n" 358e302cf3fSFrederic Weisbecker " ------- --------- - " 359e302cf3fSFrederic Weisbecker " -------- " 360e302cf3fSFrederic Weisbecker " ---- ----\n"); 361e302cf3fSFrederic Weisbecker return 0; 362e302cf3fSFrederic Weisbecker } 363e302cf3fSFrederic Weisbecker 36442548008SSteven Rostedt static void *all_branch_stat_start(struct tracer_stat *trace) 365e302cf3fSFrederic Weisbecker { 366e302cf3fSFrederic Weisbecker return __start_branch_profile; 367e302cf3fSFrederic Weisbecker } 368e302cf3fSFrederic Weisbecker 369e302cf3fSFrederic Weisbecker static void * 370e302cf3fSFrederic Weisbecker all_branch_stat_next(void *v, int idx) 371e302cf3fSFrederic Weisbecker { 372e302cf3fSFrederic Weisbecker struct ftrace_branch_data *p = v; 373e302cf3fSFrederic Weisbecker 374e302cf3fSFrederic Weisbecker ++p; 375e302cf3fSFrederic Weisbecker 376e302cf3fSFrederic Weisbecker if ((void *)p >= (void *)__stop_branch_profile) 377e302cf3fSFrederic Weisbecker return NULL; 378e302cf3fSFrederic Weisbecker 379e302cf3fSFrederic Weisbecker return p; 380e302cf3fSFrederic Weisbecker } 381e302cf3fSFrederic Weisbecker 382002bb86dSFrederic Weisbecker static struct tracer_stat all_branch_stats = { 383002bb86dSFrederic Weisbecker .name = "branch_all", 384034939b6SFrederic Weisbecker .stat_start = all_branch_stat_start, 385034939b6SFrederic Weisbecker .stat_next = all_branch_stat_next, 386034939b6SFrederic Weisbecker .stat_headers = all_branch_stat_headers, 387002bb86dSFrederic Weisbecker .stat_show = branch_stat_show 388034939b6SFrederic Weisbecker }; 389034939b6SFrederic Weisbecker 390002bb86dSFrederic Weisbecker __init static int all_annotated_branch_stats(void) 391e302cf3fSFrederic Weisbecker { 392e302cf3fSFrederic Weisbecker int ret; 393002bb86dSFrederic Weisbecker 394002bb86dSFrederic Weisbecker ret = register_stat_tracer(&all_branch_stats); 395e302cf3fSFrederic Weisbecker if (!ret) { 396002bb86dSFrederic Weisbecker printk(KERN_WARNING "Warning: could not register " 397002bb86dSFrederic Weisbecker "all branches stats\n"); 398e302cf3fSFrederic Weisbecker return 1; 399e302cf3fSFrederic Weisbecker } 400002bb86dSFrederic Weisbecker return 0; 401e302cf3fSFrederic Weisbecker } 402002bb86dSFrederic Weisbecker fs_initcall(all_annotated_branch_stats); 403002bb86dSFrederic Weisbecker #endif /* CONFIG_PROFILE_ALL_BRANCHES */ 404