summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2012-04-25 10:14:43 -0400
committerSteven Rostedt <rostedt@goodmis.org>2012-05-16 19:58:46 -0400
commit9644302e3315e7e36495d230d5ac7125a316d33e (patch)
tree63695acb86c89f5617820937ed254d9638894eef
parent706c81f87f84adbcf1f6553b9e6b69b3e28fc35a (diff)
ftrace: Speed up search by skipping pages by address
As all records in a page of the ftrace table are sorted, we can speed up the search algorithm by checking if the address to look for falls in between the first and last record ip on the page. This speeds up both the ftrace_location() and ftrace_text_reserved() algorithms, as it can skip full pages when the search address is not in them. Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--kernel/trace/ftrace.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index e10f9e522c44..fc93562a6654 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1411,6 +1411,8 @@ int ftrace_location(unsigned long ip)
key.ip = ip;
for (pg = ftrace_pages_start; pg; pg = pg->next) {
+ if (ip < pg->records[0].ip || ip > pg->records[pg->index - 1].ip)
+ continue;
rec = bsearch(&key, pg->records, pg->index,
sizeof(struct dyn_ftrace),
ftrace_cmp_recs);
@@ -1571,16 +1573,24 @@ void ftrace_bug(int failed, unsigned long ip)
/* Return 1 if the address range is reserved for ftrace */
-int ftrace_text_reserved(void *start, void *end)
+int ftrace_text_reserved(void *s, void *e)
{
struct dyn_ftrace *rec;
struct ftrace_page *pg;
+ unsigned long start = (unsigned long)s;
+ unsigned long end = (unsigned long)e;
+ int i;
- do_for_each_ftrace_rec(pg, rec) {
- if (rec->ip <= (unsigned long)end &&
- rec->ip + MCOUNT_INSN_SIZE > (unsigned long)start)
- return 1;
- } while_for_each_ftrace_rec();
+ for (pg = ftrace_pages_start; pg; pg = pg->next) {
+ if (end < pg->records[0].ip ||
+ start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
+ continue;
+ for (i = 0; i < pg->index; i++) {
+ rec = &pg->records[i];
+ if (rec->ip <= end && rec->ip + MCOUNT_INSN_SIZE > start)
+ return 1;
+ }
+ }
return 0;
}