aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/bitops.h1
-rw-r--r--arch/m68k/include/asm/bitops.h3
-rw-r--r--arch/unicore32/include/asm/bitops.h2
-rw-r--r--include/asm-generic/bitops/find.h20
-rw-r--r--include/linux/bitmap.h6
-rw-r--r--lib/cpumask.c9
-rw-r--r--lib/find_bit.c59
-rw-r--r--lib/find_bit_benchmark.c25
-rw-r--r--tools/include/asm-generic/bitops/find.h16
-rw-r--r--tools/lib/find_bit.c39
10 files changed, 147 insertions, 33 deletions
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index ce5ee762ed66..4cab9bb823fb 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -338,6 +338,7 @@ static inline int find_next_bit_le(const void *p, int size, int offset)
338 338
339#endif 339#endif
340 340
341#include <asm-generic/bitops/find.h>
341#include <asm-generic/bitops/le.h> 342#include <asm-generic/bitops/le.h>
342 343
343/* 344/*
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index dda58cfe8c22..93b47b1f6fb4 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -311,7 +311,6 @@ static inline int bfchg_mem_test_and_change_bit(int nr,
311 * functions. 311 * functions.
312 */ 312 */
313#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) 313#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
314#include <asm-generic/bitops/find.h>
315#include <asm-generic/bitops/ffz.h> 314#include <asm-generic/bitops/ffz.h>
316#else 315#else
317 316
@@ -441,6 +440,8 @@ static inline unsigned long ffz(unsigned long word)
441 440
442#endif 441#endif
443 442
443#include <asm-generic/bitops/find.h>
444
444#ifdef __KERNEL__ 445#ifdef __KERNEL__
445 446
446#if defined(CONFIG_CPU_HAS_NO_BITFIELDS) 447#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h
index 401f597bc38c..c0cbdbe17168 100644
--- a/arch/unicore32/include/asm/bitops.h
+++ b/arch/unicore32/include/asm/bitops.h
@@ -44,4 +44,6 @@ static inline int fls(int x)
44#define find_first_bit find_first_bit 44#define find_first_bit find_first_bit
45#define find_first_zero_bit find_first_zero_bit 45#define find_first_zero_bit find_first_zero_bit
46 46
47#include <asm-generic/bitops/find.h>
48
47#endif /* __UNICORE_BITOPS_H__ */ 49#endif /* __UNICORE_BITOPS_H__ */
diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h
index 1ba611e16fa0..8a1ee10014de 100644
--- a/include/asm-generic/bitops/find.h
+++ b/include/asm-generic/bitops/find.h
@@ -16,6 +16,22 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
16 size, unsigned long offset); 16 size, unsigned long offset);
17#endif 17#endif
18 18
19#ifndef find_next_and_bit
20/**
21 * find_next_and_bit - find the next set bit in both memory regions
22 * @addr1: The first address to base the search on
23 * @addr2: The second address to base the search on
24 * @offset: The bitnumber to start searching at
25 * @size: The bitmap size in bits
26 *
27 * Returns the bit number for the next set bit
28 * If no bits are set, returns @size.
29 */
30extern unsigned long find_next_and_bit(const unsigned long *addr1,
31 const unsigned long *addr2, unsigned long size,
32 unsigned long offset);
33#endif
34
19#ifndef find_next_zero_bit 35#ifndef find_next_zero_bit
20/** 36/**
21 * find_next_zero_bit - find the next cleared bit in a memory region 37 * find_next_zero_bit - find the next cleared bit in a memory region
@@ -55,8 +71,12 @@ extern unsigned long find_first_zero_bit(const unsigned long *addr,
55 unsigned long size); 71 unsigned long size);
56#else /* CONFIG_GENERIC_FIND_FIRST_BIT */ 72#else /* CONFIG_GENERIC_FIND_FIRST_BIT */
57 73
74#ifndef find_first_bit
58#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) 75#define find_first_bit(addr, size) find_next_bit((addr), (size), 0)
76#endif
77#ifndef find_first_zero_bit
59#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) 78#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
79#endif
60 80
61#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ 81#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
62 82
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index d9bf699e0e7a..5f11fbdc27f8 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -88,8 +88,12 @@
88 * test_and_change_bit(bit, addr) Change bit and return old value 88 * test_and_change_bit(bit, addr) Change bit and return old value
89 * find_first_zero_bit(addr, nbits) Position first zero bit in *addr 89 * find_first_zero_bit(addr, nbits) Position first zero bit in *addr
90 * find_first_bit(addr, nbits) Position first set bit in *addr 90 * find_first_bit(addr, nbits) Position first set bit in *addr
91 * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit 91 * find_next_zero_bit(addr, nbits, bit)
92 * Position next zero bit in *addr >= bit
92 * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit 93 * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
94 * find_next_and_bit(addr1, addr2, nbits, bit)
95 * Same as find_next_bit, but in
96 * (*addr1 & *addr2)
93 * 97 *
94 */ 98 */
95 99
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 35fe142ebb5e..beca6244671a 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -33,10 +33,11 @@ EXPORT_SYMBOL(cpumask_next);
33int cpumask_next_and(int n, const struct cpumask *src1p, 33int cpumask_next_and(int n, const struct cpumask *src1p,
34 const struct cpumask *src2p) 34 const struct cpumask *src2p)
35{ 35{
36 while ((n = cpumask_next(n, src1p)) < nr_cpu_ids) 36 /* -1 is a legal arg here. */
37 if (cpumask_test_cpu(n, src2p)) 37 if (n != -1)
38 break; 38 cpumask_check(n);
39 return n; 39 return find_next_and_bit(cpumask_bits(src1p), cpumask_bits(src2p),
40 nr_cpumask_bits, n + 1);
40} 41}
41EXPORT_SYMBOL(cpumask_next_and); 42EXPORT_SYMBOL(cpumask_next_and);
42 43
diff --git a/lib/find_bit.c b/lib/find_bit.c
index 6ed74f78380c..ee3df93ba69a 100644
--- a/lib/find_bit.c
+++ b/lib/find_bit.c
@@ -21,22 +21,29 @@
21#include <linux/export.h> 21#include <linux/export.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23 23
24#if !defined(find_next_bit) || !defined(find_next_zero_bit) 24#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
25 !defined(find_next_and_bit)
25 26
26/* 27/*
27 * This is a common helper function for find_next_bit and 28 * This is a common helper function for find_next_bit, find_next_zero_bit, and
28 * find_next_zero_bit. The difference is the "invert" argument, which 29 * find_next_and_bit. The differences are:
29 * is XORed with each fetched word before searching it for one bits. 30 * - The "invert" argument, which is XORed with each fetched word before
31 * searching it for one bits.
32 * - The optional "addr2", which is anded with "addr1" if present.
30 */ 33 */
31static unsigned long _find_next_bit(const unsigned long *addr, 34static inline unsigned long _find_next_bit(const unsigned long *addr1,
32 unsigned long nbits, unsigned long start, unsigned long invert) 35 const unsigned long *addr2, unsigned long nbits,
36 unsigned long start, unsigned long invert)
33{ 37{
34 unsigned long tmp; 38 unsigned long tmp;
35 39
36 if (unlikely(start >= nbits)) 40 if (unlikely(start >= nbits))
37 return nbits; 41 return nbits;
38 42
39 tmp = addr[start / BITS_PER_LONG] ^ invert; 43 tmp = addr1[start / BITS_PER_LONG];
44 if (addr2)
45 tmp &= addr2[start / BITS_PER_LONG];
46 tmp ^= invert;
40 47
41 /* Handle 1st word. */ 48 /* Handle 1st word. */
42 tmp &= BITMAP_FIRST_WORD_MASK(start); 49 tmp &= BITMAP_FIRST_WORD_MASK(start);
@@ -47,7 +54,10 @@ static unsigned long _find_next_bit(const unsigned long *addr,
47 if (start >= nbits) 54 if (start >= nbits)
48 return nbits; 55 return nbits;
49 56
50 tmp = addr[start / BITS_PER_LONG] ^ invert; 57 tmp = addr1[start / BITS_PER_LONG];
58 if (addr2)
59 tmp &= addr2[start / BITS_PER_LONG];
60 tmp ^= invert;
51 } 61 }
52 62
53 return min(start + __ffs(tmp), nbits); 63 return min(start + __ffs(tmp), nbits);
@@ -61,7 +71,7 @@ static unsigned long _find_next_bit(const unsigned long *addr,
61unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 71unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
62 unsigned long offset) 72 unsigned long offset)
63{ 73{
64 return _find_next_bit(addr, size, offset, 0UL); 74 return _find_next_bit(addr, NULL, size, offset, 0UL);
65} 75}
66EXPORT_SYMBOL(find_next_bit); 76EXPORT_SYMBOL(find_next_bit);
67#endif 77#endif
@@ -70,11 +80,21 @@ EXPORT_SYMBOL(find_next_bit);
70unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 80unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
71 unsigned long offset) 81 unsigned long offset)
72{ 82{
73 return _find_next_bit(addr, size, offset, ~0UL); 83 return _find_next_bit(addr, NULL, size, offset, ~0UL);
74} 84}
75EXPORT_SYMBOL(find_next_zero_bit); 85EXPORT_SYMBOL(find_next_zero_bit);
76#endif 86#endif
77 87
88#if !defined(find_next_and_bit)
89unsigned long find_next_and_bit(const unsigned long *addr1,
90 const unsigned long *addr2, unsigned long size,
91 unsigned long offset)
92{
93 return _find_next_bit(addr1, addr2, size, offset, 0UL);
94}
95EXPORT_SYMBOL(find_next_and_bit);
96#endif
97
78#ifndef find_first_bit 98#ifndef find_first_bit
79/* 99/*
80 * Find the first set bit in a memory region. 100 * Find the first set bit in a memory region.
@@ -146,15 +166,19 @@ static inline unsigned long ext2_swab(const unsigned long y)
146} 166}
147 167
148#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) 168#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
149static unsigned long _find_next_bit_le(const unsigned long *addr, 169static inline unsigned long _find_next_bit_le(const unsigned long *addr1,
150 unsigned long nbits, unsigned long start, unsigned long invert) 170 const unsigned long *addr2, unsigned long nbits,
171 unsigned long start, unsigned long invert)
151{ 172{
152 unsigned long tmp; 173 unsigned long tmp;
153 174
154 if (unlikely(start >= nbits)) 175 if (unlikely(start >= nbits))
155 return nbits; 176 return nbits;
156 177
157 tmp = addr[start / BITS_PER_LONG] ^ invert; 178 tmp = addr1[start / BITS_PER_LONG];
179 if (addr2)
180 tmp &= addr2[start / BITS_PER_LONG];
181 tmp ^= invert;
158 182
159 /* Handle 1st word. */ 183 /* Handle 1st word. */
160 tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); 184 tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
@@ -165,7 +189,10 @@ static unsigned long _find_next_bit_le(const unsigned long *addr,
165 if (start >= nbits) 189 if (start >= nbits)
166 return nbits; 190 return nbits;
167 191
168 tmp = addr[start / BITS_PER_LONG] ^ invert; 192 tmp = addr1[start / BITS_PER_LONG];
193 if (addr2)
194 tmp &= addr2[start / BITS_PER_LONG];
195 tmp ^= invert;
169 } 196 }
170 197
171 return min(start + __ffs(ext2_swab(tmp)), nbits); 198 return min(start + __ffs(ext2_swab(tmp)), nbits);
@@ -176,7 +203,7 @@ static unsigned long _find_next_bit_le(const unsigned long *addr,
176unsigned long find_next_zero_bit_le(const void *addr, unsigned 203unsigned long find_next_zero_bit_le(const void *addr, unsigned
177 long size, unsigned long offset) 204 long size, unsigned long offset)
178{ 205{
179 return _find_next_bit_le(addr, size, offset, ~0UL); 206 return _find_next_bit_le(addr, NULL, size, offset, ~0UL);
180} 207}
181EXPORT_SYMBOL(find_next_zero_bit_le); 208EXPORT_SYMBOL(find_next_zero_bit_le);
182#endif 209#endif
@@ -185,7 +212,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le);
185unsigned long find_next_bit_le(const void *addr, unsigned 212unsigned long find_next_bit_le(const void *addr, unsigned
186 long size, unsigned long offset) 213 long size, unsigned long offset)
187{ 214{
188 return _find_next_bit_le(addr, size, offset, 0UL); 215 return _find_next_bit_le(addr, NULL, size, offset, 0UL);
189} 216}
190EXPORT_SYMBOL(find_next_bit_le); 217EXPORT_SYMBOL(find_next_bit_le);
191#endif 218#endif
diff --git a/lib/find_bit_benchmark.c b/lib/find_bit_benchmark.c
index 67b19233c28f..5985a25e6cbc 100644
--- a/lib/find_bit_benchmark.c
+++ b/lib/find_bit_benchmark.c
@@ -35,6 +35,7 @@
35#define SPARSE 500 35#define SPARSE 500
36 36
37static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata; 37static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata;
38static DECLARE_BITMAP(bitmap2, BITMAP_LEN) __initdata;
38 39
39/* 40/*
40 * This is Schlemiel the Painter's algorithm. It should be called after 41 * This is Schlemiel the Painter's algorithm. It should be called after
@@ -103,6 +104,22 @@ static int __init test_find_last_bit(const void *bitmap, unsigned long len)
103 return 0; 104 return 0;
104} 105}
105 106
107static int __init test_find_next_and_bit(const void *bitmap,
108 const void *bitmap2, unsigned long len)
109{
110 unsigned long i, cnt;
111 cycles_t cycles;
112
113 cycles = get_cycles();
114 for (cnt = i = 0; i < BITMAP_LEN; cnt++)
115 i = find_next_and_bit(bitmap, bitmap2, BITMAP_LEN, i+1);
116 cycles = get_cycles() - cycles;
117 pr_err("find_next_and_bit:\t\t%llu cycles, %ld iterations\n",
118 (u64)cycles, cnt);
119
120 return 0;
121}
122
106static int __init find_bit_test(void) 123static int __init find_bit_test(void)
107{ 124{
108 unsigned long nbits = BITMAP_LEN / SPARSE; 125 unsigned long nbits = BITMAP_LEN / SPARSE;
@@ -110,23 +127,29 @@ static int __init find_bit_test(void)
110 pr_err("\nStart testing find_bit() with random-filled bitmap\n"); 127 pr_err("\nStart testing find_bit() with random-filled bitmap\n");
111 128
112 get_random_bytes(bitmap, sizeof(bitmap)); 129 get_random_bytes(bitmap, sizeof(bitmap));
130 get_random_bytes(bitmap2, sizeof(bitmap2));
113 131
114 test_find_next_bit(bitmap, BITMAP_LEN); 132 test_find_next_bit(bitmap, BITMAP_LEN);
115 test_find_next_zero_bit(bitmap, BITMAP_LEN); 133 test_find_next_zero_bit(bitmap, BITMAP_LEN);
116 test_find_last_bit(bitmap, BITMAP_LEN); 134 test_find_last_bit(bitmap, BITMAP_LEN);
117 test_find_first_bit(bitmap, BITMAP_LEN); 135 test_find_first_bit(bitmap, BITMAP_LEN);
136 test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN);
118 137
119 pr_err("\nStart testing find_bit() with sparse bitmap\n"); 138 pr_err("\nStart testing find_bit() with sparse bitmap\n");
120 139
121 bitmap_zero(bitmap, BITMAP_LEN); 140 bitmap_zero(bitmap, BITMAP_LEN);
141 bitmap_zero(bitmap2, BITMAP_LEN);
122 142
123 while (nbits--) 143 while (nbits--) {
124 __set_bit(prandom_u32() % BITMAP_LEN, bitmap); 144 __set_bit(prandom_u32() % BITMAP_LEN, bitmap);
145 __set_bit(prandom_u32() % BITMAP_LEN, bitmap2);
146 }
125 147
126 test_find_next_bit(bitmap, BITMAP_LEN); 148 test_find_next_bit(bitmap, BITMAP_LEN);
127 test_find_next_zero_bit(bitmap, BITMAP_LEN); 149 test_find_next_zero_bit(bitmap, BITMAP_LEN);
128 test_find_last_bit(bitmap, BITMAP_LEN); 150 test_find_last_bit(bitmap, BITMAP_LEN);
129 test_find_first_bit(bitmap, BITMAP_LEN); 151 test_find_first_bit(bitmap, BITMAP_LEN);
152 test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN);
130 153
131 /* 154 /*
132 * Everything is OK. Return error just to let user run benchmark 155 * Everything is OK. Return error just to let user run benchmark
diff --git a/tools/include/asm-generic/bitops/find.h b/tools/include/asm-generic/bitops/find.h
index 9311fadaaab2..16ed1982cb34 100644
--- a/tools/include/asm-generic/bitops/find.h
+++ b/tools/include/asm-generic/bitops/find.h
@@ -16,6 +16,22 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
16 size, unsigned long offset); 16 size, unsigned long offset);
17#endif 17#endif
18 18
19#ifndef find_next_and_bit
20/**
21 * find_next_and_bit - find the next set bit in both memory regions
22 * @addr1: The first address to base the search on
23 * @addr2: The second address to base the search on
24 * @offset: The bitnumber to start searching at
25 * @size: The bitmap size in bits
26 *
27 * Returns the bit number for the next set bit
28 * If no bits are set, returns @size.
29 */
30extern unsigned long find_next_and_bit(const unsigned long *addr1,
31 const unsigned long *addr2, unsigned long size,
32 unsigned long offset);
33#endif
34
19#ifndef find_next_zero_bit 35#ifndef find_next_zero_bit
20 36
21/** 37/**
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c
index 42c15f906aac..a88bd507091e 100644
--- a/tools/lib/find_bit.c
+++ b/tools/lib/find_bit.c
@@ -22,22 +22,29 @@
22#include <linux/bitmap.h> 22#include <linux/bitmap.h>
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24 24
25#if !defined(find_next_bit) 25#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
26 !defined(find_next_and_bit)
26 27
27/* 28/*
28 * This is a common helper function for find_next_bit and 29 * This is a common helper function for find_next_bit, find_next_zero_bit, and
29 * find_next_zero_bit. The difference is the "invert" argument, which 30 * find_next_and_bit. The differences are:
30 * is XORed with each fetched word before searching it for one bits. 31 * - The "invert" argument, which is XORed with each fetched word before
32 * searching it for one bits.
33 * - The optional "addr2", which is anded with "addr1" if present.
31 */ 34 */
32static unsigned long _find_next_bit(const unsigned long *addr, 35static inline unsigned long _find_next_bit(const unsigned long *addr1,
33 unsigned long nbits, unsigned long start, unsigned long invert) 36 const unsigned long *addr2, unsigned long nbits,
37 unsigned long start, unsigned long invert)
34{ 38{
35 unsigned long tmp; 39 unsigned long tmp;
36 40
37 if (unlikely(start >= nbits)) 41 if (unlikely(start >= nbits))
38 return nbits; 42 return nbits;
39 43
40 tmp = addr[start / BITS_PER_LONG] ^ invert; 44 tmp = addr1[start / BITS_PER_LONG];
45 if (addr2)
46 tmp &= addr2[start / BITS_PER_LONG];
47 tmp ^= invert;
41 48
42 /* Handle 1st word. */ 49 /* Handle 1st word. */
43 tmp &= BITMAP_FIRST_WORD_MASK(start); 50 tmp &= BITMAP_FIRST_WORD_MASK(start);
@@ -48,7 +55,10 @@ static unsigned long _find_next_bit(const unsigned long *addr,
48 if (start >= nbits) 55 if (start >= nbits)
49 return nbits; 56 return nbits;
50 57
51 tmp = addr[start / BITS_PER_LONG] ^ invert; 58 tmp = addr1[start / BITS_PER_LONG];
59 if (addr2)
60 tmp &= addr2[start / BITS_PER_LONG];
61 tmp ^= invert;
52 } 62 }
53 63
54 return min(start + __ffs(tmp), nbits); 64 return min(start + __ffs(tmp), nbits);
@@ -62,7 +72,7 @@ static unsigned long _find_next_bit(const unsigned long *addr,
62unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 72unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
63 unsigned long offset) 73 unsigned long offset)
64{ 74{
65 return _find_next_bit(addr, size, offset, 0UL); 75 return _find_next_bit(addr, NULL, size, offset, 0UL);
66} 76}
67#endif 77#endif
68 78
@@ -104,6 +114,15 @@ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
104unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 114unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
105 unsigned long offset) 115 unsigned long offset)
106{ 116{
107 return _find_next_bit(addr, size, offset, ~0UL); 117 return _find_next_bit(addr, NULL, size, offset, ~0UL);
118}
119#endif
120
121#ifndef find_next_and_bit
122unsigned long find_next_and_bit(const unsigned long *addr1,
123 const unsigned long *addr2, unsigned long size,
124 unsigned long offset)
125{
126 return _find_next_bit(addr1, addr2, size, offset, 0UL);
108} 127}
109#endif 128#endif