aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-12-16 19:27:42 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-12-21 07:20:50 -0500
commit5855fead9cc358adebd6bdeec202d040c623ae38 (patch)
treec95d272ff41b7873cc33feef3686ede3f020d4cd /kernel
parent68950619f8c82e468d8976130462617abea605a8 (diff)
ftrace: Use bsearch to find record ip
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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ftrace.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 2d6f8bcd188..dcd3a814d39 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -22,6 +22,7 @@
22#include <linux/hardirq.h> 22#include <linux/hardirq.h>
23#include <linux/kthread.h> 23#include <linux/kthread.h>
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <linux/bsearch.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <linux/ftrace.h> 27#include <linux/ftrace.h>
27#include <linux/sysctl.h> 28#include <linux/sysctl.h>
@@ -1300,6 +1301,19 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
1300 } \ 1301 } \
1301 } 1302 }
1302 1303
1304
1305static int ftrace_cmp_recs(const void *a, const void *b)
1306{
1307 const struct dyn_ftrace *reca = a;
1308 const struct dyn_ftrace *recb = b;
1309
1310 if (reca->ip > recb->ip)
1311 return 1;
1312 if (reca->ip < recb->ip)
1313 return -1;
1314 return 0;
1315}
1316
1303/** 1317/**
1304 * ftrace_location - return true if the ip giving is a traced location 1318 * ftrace_location - return true if the ip giving is a traced location
1305 * @ip: the instruction pointer to check 1319 * @ip: the instruction pointer to check
@@ -1313,11 +1327,17 @@ int ftrace_location(unsigned long ip)
1313{ 1327{
1314 struct ftrace_page *pg; 1328 struct ftrace_page *pg;
1315 struct dyn_ftrace *rec; 1329 struct dyn_ftrace *rec;
1330 struct dyn_ftrace key;
1316 1331
1317 do_for_each_ftrace_rec(pg, rec) { 1332 key.ip = ip;
1318 if (rec->ip == ip) 1333
1334 for (pg = ftrace_pages_start; pg; pg = pg->next) {
1335 rec = bsearch(&key, pg->records, pg->index,
1336 sizeof(struct dyn_ftrace),
1337 ftrace_cmp_recs);
1338 if (rec)
1319 return 1; 1339 return 1;
1320 } while_for_each_ftrace_rec(); 1340 }
1321 1341
1322 return 0; 1342 return 0;
1323} 1343}
@@ -3587,18 +3607,6 @@ static void ftrace_swap_recs(void *a, void *b, int size)
3587 *recb = t; 3607 *recb = t;
3588} 3608}
3589 3609
3590static int ftrace_cmp_recs(const void *a, const void *b)
3591{
3592 const struct dyn_ftrace *reca = a;
3593 const struct dyn_ftrace *recb = b;
3594
3595 if (reca->ip > recb->ip)
3596 return 1;
3597 if (reca->ip < recb->ip)
3598 return -1;
3599 return 0;
3600}
3601
3602static int ftrace_process_locs(struct module *mod, 3610static int ftrace_process_locs(struct module *mod,
3603 unsigned long *start, 3611 unsigned long *start,
3604 unsigned long *end) 3612 unsigned long *end)