diff options
| author | Tim Abbott <tabbott@ksplice.com> | 2011-04-14 14:00:19 -0400 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2011-05-19 03:25:27 -0400 |
| commit | 1a94dc35bc5c166d89913dc01a49d27a3c21a455 (patch) | |
| tree | 575196f1d0b9528b7d63b9bff692dd81e1aeac0f /lib | |
| parent | f02e8a6596b7dc9b2171f7ff5654039ef0950cdc (diff) | |
lib: Add generic binary search function to the kernel.
There a large number hand-coded binary searches in the kernel (run
"git grep search | grep binary" to find many of them). Since in my
experience, hand-coding binary searches can be error-prone, it seems
worth cleaning this up by providing a generic binary search function.
This generic binary search implementation comes from Ksplice. It has
the same basic API as the C library bsearch() function. Ksplice uses
it in half a dozen places with 4 different comparison functions, and I
think our code is substantially cleaner because of this.
Signed-off-by: Tim Abbott <tabbott@ksplice.com>
Extra-bikeshedding-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Extra-bikeshedding-by: André Goddard Rosa <andre.goddard@gmail.com>
Extra-bikeshedding-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Alessio Igor Bogani <abogani@kernel.org>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 3 | ||||
| -rw-r--r-- | lib/bsearch.c | 53 |
2 files changed, 55 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile index ef0f28571156..4b49a249064b 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -21,7 +21,8 @@ lib-y += kobject.o kref.o klist.o | |||
| 21 | 21 | ||
| 22 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 22 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ |
| 23 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ | 23 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ |
| 24 | string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o | 24 | string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \ |
| 25 | bsearch.o | ||
| 25 | obj-y += kstrtox.o | 26 | obj-y += kstrtox.o |
| 26 | obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o | 27 | obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o |
| 27 | 28 | ||
diff --git a/lib/bsearch.c b/lib/bsearch.c new file mode 100644 index 000000000000..5b54758e2afb --- /dev/null +++ b/lib/bsearch.c | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* | ||
| 2 | * A generic implementation of binary search for the Linux kernel | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008-2009 Ksplice, Inc. | ||
| 5 | * Author: Tim Abbott <tabbott@ksplice.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation; version 2. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/bsearch.h> | ||
| 14 | |||
| 15 | /* | ||
| 16 | * bsearch - binary search an array of elements | ||
| 17 | * @key: pointer to item being searched for | ||
| 18 | * @base: pointer to first element to search | ||
| 19 | * @num: number of elements | ||
| 20 | * @size: size of each element | ||
| 21 | * @cmp: pointer to comparison function | ||
| 22 | * | ||
| 23 | * This function does a binary search on the given array. The | ||
| 24 | * contents of the array should already be in ascending sorted order | ||
| 25 | * under the provided comparison function. | ||
| 26 | * | ||
| 27 | * Note that the key need not have the same type as the elements in | ||
| 28 | * the array, e.g. key could be a string and the comparison function | ||
| 29 | * could compare the string with the struct's name field. However, if | ||
| 30 | * the key and elements in the array are of the same type, you can use | ||
| 31 | * the same comparison function for both sort() and bsearch(). | ||
| 32 | */ | ||
| 33 | void *bsearch(const void *key, const void *base, size_t num, size_t size, | ||
| 34 | int (*cmp)(const void *key, const void *elt)) | ||
| 35 | { | ||
| 36 | size_t start = 0, end = num; | ||
| 37 | int result; | ||
| 38 | |||
| 39 | while (start < end) { | ||
| 40 | size_t mid = start + (end - start) / 2; | ||
| 41 | |||
| 42 | result = cmp(key, base + mid * size); | ||
| 43 | if (result < 0) | ||
| 44 | end = mid; | ||
| 45 | else if (result > 0) | ||
| 46 | start = mid + 1; | ||
| 47 | else | ||
| 48 | return (void *)base + mid * size; | ||
| 49 | } | ||
| 50 | |||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | EXPORT_SYMBOL(bsearch); | ||
