tracing: profile likely and unlikely annotations
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / kernel / trace / trace_unlikely.c
blob94932696069ff7f95ded475856ca7b21d2026f9b
1 /*
2 * unlikely profiler
4 * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
5 */
6 #include <linux/kallsyms.h>
7 #include <linux/seq_file.h>
8 #include <linux/spinlock.h>
9 #include <linux/debugfs.h>
10 #include <linux/uaccess.h>
11 #include <linux/module.h>
12 #include <linux/ftrace.h>
13 #include <linux/hash.h>
14 #include <linux/fs.h>
15 #include <asm/local.h>
16 #include "trace.h"
18 void ftrace_likely_update(struct ftrace_likely_data *f, int val, int expect)
20 /* FIXME: Make this atomic! */
21 if (val == expect)
22 f->correct++;
23 else
24 f->incorrect++;
26 EXPORT_SYMBOL(ftrace_likely_update);
28 struct ftrace_pointer {
29 void *start;
30 void *stop;
33 static void *
34 t_next(struct seq_file *m, void *v, loff_t *pos)
36 struct ftrace_pointer *f = m->private;
37 struct ftrace_likely_data *p = v;
39 (*pos)++;
41 if (v == (void *)1)
42 return f->start;
44 ++p;
46 if ((void *)p >= (void *)f->stop)
47 return NULL;
49 return p;
52 static void *t_start(struct seq_file *m, loff_t *pos)
54 void *t = (void *)1;
55 loff_t l = 0;
57 for (; t && l < *pos; t = t_next(m, t, &l))
60 return t;
63 static void t_stop(struct seq_file *m, void *p)
67 static int t_show(struct seq_file *m, void *v)
69 struct ftrace_likely_data *p = v;
70 const char *f;
71 unsigned long percent;
73 if (v == (void *)1) {
74 seq_printf(m, " correct incorrect %% "
75 " Function "
76 " File Line\n"
77 " ------- --------- - "
78 " -------- "
79 " ---- ----\n");
80 return 0;
83 /* Only print the file, not the path */
84 f = p->file + strlen(p->file);
85 while (f >= p->file && *f != '/')
86 f--;
87 f++;
89 if (p->correct) {
90 percent = p->incorrect * 100;
91 percent /= p->correct + p->incorrect;
92 } else
93 percent = p->incorrect ? 100 : 0;
95 seq_printf(m, "%8lu %8lu %3lu ", p->correct, p->incorrect, percent);
96 seq_printf(m, "%-30.30s %-20.20s %d\n", p->func, f, p->line);
97 return 0;
100 static struct seq_operations tracing_likely_seq_ops = {
101 .start = t_start,
102 .next = t_next,
103 .stop = t_stop,
104 .show = t_show,
107 static int tracing_likely_open(struct inode *inode, struct file *file)
109 int ret;
111 ret = seq_open(file, &tracing_likely_seq_ops);
112 if (!ret) {
113 struct seq_file *m = file->private_data;
114 m->private = (void *)inode->i_private;
117 return ret;
120 static struct file_operations tracing_likely_fops = {
121 .open = tracing_likely_open,
122 .read = seq_read,
123 .llseek = seq_lseek,
126 extern unsigned long __start_likely_profile[];
127 extern unsigned long __stop_likely_profile[];
128 extern unsigned long __start_unlikely_profile[];
129 extern unsigned long __stop_unlikely_profile[];
131 static struct ftrace_pointer ftrace_likely_pos = {
132 .start = __start_likely_profile,
133 .stop = __stop_likely_profile,
136 static struct ftrace_pointer ftrace_unlikely_pos = {
137 .start = __start_unlikely_profile,
138 .stop = __stop_unlikely_profile,
141 static __init int ftrace_unlikely_init(void)
143 struct dentry *d_tracer;
144 struct dentry *entry;
146 d_tracer = tracing_init_dentry();
148 entry = debugfs_create_file("profile_likely", 0444, d_tracer,
149 &ftrace_likely_pos,
150 &tracing_likely_fops);
151 if (!entry)
152 pr_warning("Could not create debugfs 'profile_likely' entry\n");
154 entry = debugfs_create_file("profile_unlikely", 0444, d_tracer,
155 &ftrace_unlikely_pos,
156 &tracing_likely_fops);
157 if (!entry)
158 pr_warning("Could not create debugfs"
159 " 'profile_unlikely' entry\n");
161 return 0;
164 device_initcall(ftrace_unlikely_init);