summaryrefslogtreecommitdiff
path: root/lib/find_bit.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/find_bit.c')
-rw-r--r--lib/find_bit.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/lib/find_bit.c b/lib/find_bit.c
index 0836bb3d76c5..d4b5a29e3e72 100644
--- a/lib/find_bit.c
+++ b/lib/find_bit.c
@@ -18,6 +18,7 @@
#include <linux/math.h>
#include <linux/minmax.h>
#include <linux/swab.h>
+#include <linux/random.h>
/*
* Common helper for find_bit() function family
@@ -117,6 +118,17 @@ EXPORT_SYMBOL(_find_first_and_bit);
#endif
/*
+ * Find the first bit set in 1st memory region and unset in 2nd.
+ */
+unsigned long _find_first_andnot_bit(const unsigned long *addr1,
+ const unsigned long *addr2,
+ unsigned long size)
+{
+ return FIND_FIRST_BIT(addr1[idx] & ~addr2[idx], /* nop */, size);
+}
+EXPORT_SYMBOL(_find_first_andnot_bit);
+
+/*
* Find the first set bit in three memory regions.
*/
unsigned long _find_first_and_and_bit(const unsigned long *addr1,
@@ -280,3 +292,26 @@ EXPORT_SYMBOL(_find_next_bit_le);
#endif
#endif /* __BIG_ENDIAN */
+
+/**
+ * find_random_bit - find a set bit at random position
+ * @addr: The address to base the search on
+ * @size: The bitmap size in bits
+ *
+ * Returns: a position of a random set bit; >= @size otherwise
+ */
+unsigned long find_random_bit(const unsigned long *addr, unsigned long size)
+{
+ int w = bitmap_weight(addr, size);
+
+ switch (w) {
+ case 0:
+ return size;
+ case 1:
+ /* Performance trick for single-bit bitmaps */
+ return find_first_bit(addr, size);
+ default:
+ return find_nth_bit(addr, size, get_random_u32_below(w));
+ }
+}
+EXPORT_SYMBOL(find_random_bit);