* specific implementations come from the above header files
  */
 
-#define likely(x)      __builtin_expect(!!(x), 1)
-#define unlikely(x)    __builtin_expect(!!(x), 0)
+#ifdef CONFIG_TRACE_UNLIKELY_PROFILE
+struct ftrace_likely_data {
+       const char *func;
+       const char *file;
+       unsigned line;
+       unsigned long correct;
+       unsigned long incorrect;
+};
+void ftrace_likely_update(struct ftrace_likely_data *f, int val, int expect);
+
+#define likely_notrace(x)      __builtin_expect(!!(x), 1)
+#define unlikely_notrace(x)    __builtin_expect(!!(x), 0)
+
+#define likely_check(x) ({                                             \
+                       int ______r;                                    \
+                       static struct ftrace_likely_data                \
+                               __attribute__((__aligned__(4)))         \
+                               __attribute__((section("_ftrace_likely"))) \
+                               ______f = {                             \
+                               .func = __func__,                       \
+                               .file = __FILE__,                       \
+                               .line = __LINE__,                       \
+                       };                                              \
+                       ______f.line = __LINE__;                        \
+                       ______r = likely_notrace(x);                    \
+                       ftrace_likely_update(&______f, ______r, 1);     \
+                       ______r;                                        \
+               })
+#define unlikely_check(x) ({                                           \
+                       int ______r;                                    \
+                       static struct ftrace_likely_data                \
+                               __attribute__((__aligned__(4)))         \
+                               __attribute__((section("_ftrace_unlikely"))) \
+                               ______f = {                             \
+                               .func = __func__,                       \
+                               .file = __FILE__,                       \
+                               .line = __LINE__,                       \
+                       };                                              \
+                       ______f.line = __LINE__;                        \
+                       ______r = unlikely_notrace(x);                  \
+                       ftrace_likely_update(&______f, ______r, 0);     \
+                       ______r;                                        \
+               })
+
+/*
+ * Using __builtin_constant_p(x) to ignore cases where the return
+ * value is always the same.  This idea is taken from a similar patch
+ * written by Daniel Walker.
+ */
+# ifndef likely
+#  define likely(x)    (__builtin_constant_p(x) ? !!(x) : likely_check(x))
+# endif
+# ifndef unlikely
+#  define unlikely(x)  (__builtin_constant_p(x) ? !!(x) : unlikely_check(x))
+# endif
+#else
+# define likely(x)     __builtin_expect(!!(x), 1)
+# define unlikely(x)   __builtin_expect(!!(x), 0)
+#endif
 
 /* Optimization barrier */
 #ifndef barrier
 
--- /dev/null
+/*
+ * unlikely profiler
+ *
+ * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
+ */
+#include <linux/kallsyms.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/ftrace.h>
+#include <linux/hash.h>
+#include <linux/fs.h>
+#include <asm/local.h>
+#include "trace.h"
+
+void ftrace_likely_update(struct ftrace_likely_data *f, int val, int expect)
+{
+       /* FIXME: Make this atomic! */
+       if (val == expect)
+               f->correct++;
+       else
+               f->incorrect++;
+}
+EXPORT_SYMBOL(ftrace_likely_update);
+
+struct ftrace_pointer {
+       void            *start;
+       void            *stop;
+};
+
+static void *
+t_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       struct ftrace_pointer *f = m->private;
+       struct ftrace_likely_data *p = v;
+
+       (*pos)++;
+
+       if (v == (void *)1)
+               return f->start;
+
+       ++p;
+
+       if ((void *)p >= (void *)f->stop)
+               return NULL;
+
+       return p;
+}
+
+static void *t_start(struct seq_file *m, loff_t *pos)
+{
+       void *t = (void *)1;
+       loff_t l = 0;
+
+       for (; t && l < *pos; t = t_next(m, t, &l))
+               ;
+
+       return t;
+}
+
+static void t_stop(struct seq_file *m, void *p)
+{
+}
+
+static int t_show(struct seq_file *m, void *v)
+{
+       struct ftrace_likely_data *p = v;
+       const char *f;
+       unsigned long percent;
+
+       if (v == (void *)1) {
+               seq_printf(m, " correct incorrect  %% "
+                             "       Function                "
+                             "  File              Line\n"
+                             " ------- ---------  - "
+                             "       --------                "
+                             "  ----              ----\n");
+               return 0;
+       }
+
+       /* Only print the file, not the path */
+       f = p->file + strlen(p->file);
+       while (f >= p->file && *f != '/')
+               f--;
+       f++;
+
+       if (p->correct) {
+               percent = p->incorrect * 100;
+               percent /= p->correct + p->incorrect;
+       } else
+               percent = p->incorrect ? 100 : 0;
+
+       seq_printf(m, "%8lu %8lu %3lu ", p->correct, p->incorrect, percent);
+       seq_printf(m, "%-30.30s %-20.20s %d\n", p->func, f, p->line);
+       return 0;
+}
+
+static struct seq_operations tracing_likely_seq_ops = {
+       .start          = t_start,
+       .next           = t_next,
+       .stop           = t_stop,
+       .show           = t_show,
+};
+
+static int tracing_likely_open(struct inode *inode, struct file *file)
+{
+       int ret;
+
+       ret = seq_open(file, &tracing_likely_seq_ops);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+               m->private = (void *)inode->i_private;
+       }
+
+       return ret;
+}
+
+static struct file_operations tracing_likely_fops = {
+       .open           = tracing_likely_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+};
+
+extern unsigned long __start_likely_profile[];
+extern unsigned long __stop_likely_profile[];
+extern unsigned long __start_unlikely_profile[];
+extern unsigned long __stop_unlikely_profile[];
+
+static struct ftrace_pointer ftrace_likely_pos = {
+       .start                  = __start_likely_profile,
+       .stop                   = __stop_likely_profile,
+};
+
+static struct ftrace_pointer ftrace_unlikely_pos = {
+       .start                  = __start_unlikely_profile,
+       .stop                   = __stop_unlikely_profile,
+};
+
+static __init int ftrace_unlikely_init(void)
+{
+       struct dentry *d_tracer;
+       struct dentry *entry;
+
+       d_tracer = tracing_init_dentry();
+
+       entry = debugfs_create_file("profile_likely", 0444, d_tracer,
+                                   &ftrace_likely_pos,
+                                   &tracing_likely_fops);
+       if (!entry)
+               pr_warning("Could not create debugfs 'profile_likely' entry\n");
+
+       entry = debugfs_create_file("profile_unlikely", 0444, d_tracer,
+                                   &ftrace_unlikely_pos,
+                                   &tracing_likely_fops);
+       if (!entry)
+               pr_warning("Could not create debugfs"
+                          " 'profile_unlikely' entry\n");
+
+       return 0;
+}
+
+device_initcall(ftrace_unlikely_init);