diff options
-rw-r--r-- | tools/lib/find_bit.c | 103 | ||||
-rw-r--r-- | tools/perf/util/include/linux/bitmap.h | 2 |
2 files changed, 51 insertions, 54 deletions
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c index 732d8c38d2c3..9122a9e80046 100644 --- a/tools/lib/find_bit.c +++ b/tools/lib/find_bit.c | |||
@@ -1,10 +1,17 @@ | |||
1 | /* find_next_bit.c: fallback find next bit implementation | 1 | /* bit search implementation |
2 | * | 2 | * |
3 | * Copied from lib/find_next_bit.c to tools/lib/find_bit.c | 3 | * Copied from lib/find_bit.c to tools/lib/find_bit.c |
4 | * | 4 | * |
5 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 5 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. |
6 | * Written by David Howells (dhowells@redhat.com) | 6 | * Written by David Howells (dhowells@redhat.com) |
7 | * | 7 | * |
8 | * Copyright (C) 2008 IBM Corporation | ||
9 | * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au> | ||
10 | * (Inspired by David Howell's find_next_bit implementation) | ||
11 | * | ||
12 | * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease | ||
13 | * size and improve performance, 2015. | ||
14 | * | ||
8 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 16 | * modify it under the terms of the GNU General Public License |
10 | * as published by the Free Software Foundation; either version | 17 | * as published by the Free Software Foundation; either version |
@@ -12,52 +19,50 @@ | |||
12 | */ | 19 | */ |
13 | 20 | ||
14 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
15 | #include <asm/types.h> | 22 | #include <linux/bitmap.h> |
16 | #include <asm/byteorder.h> | 23 | #include <linux/kernel.h> |
17 | 24 | ||
18 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) | 25 | #if !defined(find_next_bit) |
19 | 26 | ||
20 | #ifndef find_next_bit | ||
21 | /* | 27 | /* |
22 | * Find the next set bit in a memory region. | 28 | * This is a common helper function for find_next_bit and |
29 | * find_next_zero_bit. The difference is the "invert" argument, which | ||
30 | * is XORed with each fetched word before searching it for one bits. | ||
23 | */ | 31 | */ |
24 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | 32 | static unsigned long _find_next_bit(const unsigned long *addr, |
25 | unsigned long offset) | 33 | unsigned long nbits, unsigned long start, unsigned long invert) |
26 | { | 34 | { |
27 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
28 | unsigned long result = offset & ~(BITS_PER_LONG-1); | ||
29 | unsigned long tmp; | 35 | unsigned long tmp; |
30 | 36 | ||
31 | if (offset >= size) | 37 | if (!nbits || start >= nbits) |
32 | return size; | 38 | return nbits; |
33 | size -= result; | 39 | |
34 | offset %= BITS_PER_LONG; | 40 | tmp = addr[start / BITS_PER_LONG] ^ invert; |
35 | if (offset) { | 41 | |
36 | tmp = *(p++); | 42 | /* Handle 1st word. */ |
37 | tmp &= (~0UL << offset); | 43 | tmp &= BITMAP_FIRST_WORD_MASK(start); |
38 | if (size < BITS_PER_LONG) | 44 | start = round_down(start, BITS_PER_LONG); |
39 | goto found_first; | 45 | |
40 | if (tmp) | 46 | while (!tmp) { |
41 | goto found_middle; | 47 | start += BITS_PER_LONG; |
42 | size -= BITS_PER_LONG; | 48 | if (start >= nbits) |
43 | result += BITS_PER_LONG; | 49 | return nbits; |
44 | } | 50 | |
45 | while (size & ~(BITS_PER_LONG-1)) { | 51 | tmp = addr[start / BITS_PER_LONG] ^ invert; |
46 | if ((tmp = *(p++))) | ||
47 | goto found_middle; | ||
48 | result += BITS_PER_LONG; | ||
49 | size -= BITS_PER_LONG; | ||
50 | } | 52 | } |
51 | if (!size) | ||
52 | return result; | ||
53 | tmp = *p; | ||
54 | 53 | ||
55 | found_first: | 54 | return min(start + __ffs(tmp), nbits); |
56 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | 55 | } |
57 | if (tmp == 0UL) /* Are any bits set? */ | 56 | #endif |
58 | return result + size; /* Nope. */ | 57 | |
59 | found_middle: | 58 | #ifndef find_next_bit |
60 | return result + __ffs(tmp); | 59 | /* |
60 | * Find the next set bit in a memory region. | ||
61 | */ | ||
62 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | ||
63 | unsigned long offset) | ||
64 | { | ||
65 | return _find_next_bit(addr, size, offset, 0UL); | ||
61 | } | 66 | } |
62 | #endif | 67 | #endif |
63 | 68 | ||
@@ -67,23 +72,13 @@ found_middle: | |||
67 | */ | 72 | */ |
68 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) | 73 | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) |
69 | { | 74 | { |
70 | const unsigned long *p = addr; | 75 | unsigned long idx; |
71 | unsigned long result = 0; | ||
72 | unsigned long tmp; | ||
73 | 76 | ||
74 | while (size & ~(BITS_PER_LONG-1)) { | 77 | for (idx = 0; idx * BITS_PER_LONG < size; idx++) { |
75 | if ((tmp = *(p++))) | 78 | if (addr[idx]) |
76 | goto found; | 79 | return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size); |
77 | result += BITS_PER_LONG; | ||
78 | size -= BITS_PER_LONG; | ||
79 | } | 80 | } |
80 | if (!size) | ||
81 | return result; | ||
82 | 81 | ||
83 | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | 82 | return size; |
84 | if (tmp == 0UL) /* Are any bits set? */ | ||
85 | return result + size; /* Nope. */ | ||
86 | found: | ||
87 | return result + __ffs(tmp); | ||
88 | } | 83 | } |
89 | #endif | 84 | #endif |
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h index 40bd21488032..28f5493da491 100644 --- a/tools/perf/util/include/linux/bitmap.h +++ b/tools/perf/util/include/linux/bitmap.h | |||
@@ -11,6 +11,8 @@ int __bitmap_weight(const unsigned long *bitmap, int bits); | |||
11 | void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, | 11 | void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, |
12 | const unsigned long *bitmap2, int bits); | 12 | const unsigned long *bitmap2, int bits); |
13 | 13 | ||
14 | #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) | ||
15 | |||
14 | #define BITMAP_LAST_WORD_MASK(nbits) \ | 16 | #define BITMAP_LAST_WORD_MASK(nbits) \ |
15 | ( \ | 17 | ( \ |
16 | ((nbits) % BITS_PER_LONG) ? \ | 18 | ((nbits) % BITS_PER_LONG) ? \ |