Skip to content

Commit

Permalink
ftrace: Use bsearch to find record ip
Browse files Browse the repository at this point in the history
Now that each set of pages in the function list are sorted by
ip, we can use bsearch to find a record within each set of pages.
This speeds up the ftrace_location() function by magnitudes.

For archs (like x86) that need to add a breakpoint at every function
that will be converted from a nop to a callback and vice versa,
the breakpoint callback needs to know if the breakpoint was for
ftrace or not. It requires finding the breakpoint ip within the
records. Doing a linear search is extremely inefficient. It is
a must to be able to do a fast binary search to find these locations.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Dec 21, 2011
1 parent 6895061 commit 5855fea
Showing 1 changed file with 23 additions and 15 deletions.
38 changes: 23 additions & 15 deletions kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/hardirq.h>
#include <linux/kthread.h>
#include <linux/uaccess.h>
#include <linux/bsearch.h>
#include <linux/module.h>
#include <linux/ftrace.h>
#include <linux/sysctl.h>
Expand Down Expand Up @@ -1300,6 +1301,19 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
} \
}


static int ftrace_cmp_recs(const void *a, const void *b)
{
const struct dyn_ftrace *reca = a;
const struct dyn_ftrace *recb = b;

if (reca->ip > recb->ip)
return 1;
if (reca->ip < recb->ip)
return -1;
return 0;
}

/**
* ftrace_location - return true if the ip giving is a traced location
* @ip: the instruction pointer to check
Expand All @@ -1313,11 +1327,17 @@ int ftrace_location(unsigned long ip)
{
struct ftrace_page *pg;
struct dyn_ftrace *rec;
struct dyn_ftrace key;

do_for_each_ftrace_rec(pg, rec) {
if (rec->ip == ip)
key.ip = ip;

for (pg = ftrace_pages_start; pg; pg = pg->next) {
rec = bsearch(&key, pg->records, pg->index,
sizeof(struct dyn_ftrace),
ftrace_cmp_recs);
if (rec)
return 1;
} while_for_each_ftrace_rec();
}

return 0;
}
Expand Down Expand Up @@ -3587,18 +3607,6 @@ static void ftrace_swap_recs(void *a, void *b, int size)
*recb = t;
}

static int ftrace_cmp_recs(const void *a, const void *b)
{
const struct dyn_ftrace *reca = a;
const struct dyn_ftrace *recb = b;

if (reca->ip > recb->ip)
return 1;
if (reca->ip < recb->ip)
return -1;
return 0;
}

static int ftrace_process_locs(struct module *mod,
unsigned long *start,
unsigned long *end)
Expand Down

0 comments on commit 5855fea

Please sign in to comment.