diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2011-12-16 19:27:42 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2011-12-21 07:20:50 -0500 |
| commit | 5855fead9cc358adebd6bdeec202d040c623ae38 (patch) | |
| tree | c95d272ff41b7873cc33feef3686ede3f020d4cd /kernel/trace | |
| parent | 68950619f8c82e468d8976130462617abea605a8 (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/trace')
| -rw-r--r-- | kernel/trace/ftrace.c | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 2d6f8bcd1884..dcd3a814d39b 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 | |||
| 1305 | static 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 | ||
| 3590 | static 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 | |||
| 3602 | static int ftrace_process_locs(struct module *mod, | 3610 | static int ftrace_process_locs(struct module *mod, |
| 3603 | unsigned long *start, | 3611 | unsigned long *start, |
| 3604 | unsigned long *end) | 3612 | unsigned long *end) |
