|
4 | 4 | * Written by Rusty Russell <rusty@rustcorp.com.au>
|
5 | 5 | * (Inspired by David Howell's find_next_bit implementation)
|
6 | 6 | *
|
| 7 | + * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease |
| 8 | + * size and improve performance, 2015. |
| 9 | + * |
7 | 10 | * This program is free software; you can redistribute it and/or
|
8 | 11 | * modify it under the terms of the GNU General Public License
|
9 | 12 | * as published by the Free Software Foundation; either version
|
10 | 13 | * 2 of the License, or (at your option) any later version.
|
11 | 14 | */
|
12 | 15 |
|
13 | 16 | #include <linux/bitops.h>
|
| 17 | +#include <linux/bitmap.h> |
14 | 18 | #include <linux/export.h>
|
15 |
| -#include <asm/types.h> |
16 |
| -#include <asm/byteorder.h> |
| 19 | +#include <linux/kernel.h> |
17 | 20 |
|
18 | 21 | #ifndef find_last_bit
|
19 | 22 |
|
20 | 23 | unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
|
21 | 24 | {
|
22 |
| - unsigned long words; |
23 |
| - unsigned long tmp; |
24 |
| - |
25 |
| - /* Start at final word. */ |
26 |
| - words = size / BITS_PER_LONG; |
| 25 | + if (size) { |
| 26 | + unsigned long val = BITMAP_LAST_WORD_MASK(size); |
| 27 | + unsigned long idx = (size-1) / BITS_PER_LONG; |
27 | 28 |
|
28 |
| - /* Partial final word? */ |
29 |
| - if (size & (BITS_PER_LONG-1)) { |
30 |
| - tmp = (addr[words] & (~0UL >> (BITS_PER_LONG |
31 |
| - - (size & (BITS_PER_LONG-1))))); |
32 |
| - if (tmp) |
33 |
| - goto found; |
34 |
| - } |
| 29 | + do { |
| 30 | + val &= addr[idx]; |
| 31 | + if (val) |
| 32 | + return idx * BITS_PER_LONG + __fls(val); |
35 | 33 |
|
36 |
| - while (words) { |
37 |
| - tmp = addr[--words]; |
38 |
| - if (tmp) { |
39 |
| -found: |
40 |
| - return words * BITS_PER_LONG + __fls(tmp); |
41 |
| - } |
| 34 | + val = ~0ul; |
| 35 | + } while (idx--); |
42 | 36 | }
|
43 |
| - |
44 |
| - /* Not found */ |
45 | 37 | return size;
|
46 | 38 | }
|
47 | 39 | EXPORT_SYMBOL(find_last_bit);
|
|
0 commit comments