diff options
Diffstat (limited to 'include/linux/bitmap.h')
-rw-r--r-- | include/linux/bitmap.h | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index c5592a5a..54a8d52a 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -2,6 +2,7 @@ #define _PERF_BITOPS_H #include <string.h> +#include <linux/bits.h> #include <linux/bitops.h> #include <linux/kernel.h> #include <stdlib.h> @@ -34,7 +35,7 @@ static inline int __bitmap_weight(const unsigned long *bitmap, int bits) w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); return w; -} +} static inline int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, const unsigned long *bitmap2, unsigned int bits) @@ -156,6 +157,49 @@ static inline unsigned long find_next_zero_bit(const unsigned long *addr, unsign return _find_next_bit(addr, size, offset, ~0UL); } +#define FIND_NEXT_BIT(FETCH, MUNGE, size, start) \ +({ \ + unsigned long mask, idx, tmp, sz = (size), __start = (start); \ + \ + if (unlikely(__start >= sz)) \ + goto out; \ + \ + mask = MUNGE(BITMAP_FIRST_WORD_MASK(__start)); \ + idx = __start / BITS_PER_LONG; \ + \ + for (tmp = (FETCH) & mask; !tmp; tmp = (FETCH)) { \ + if ((idx + 1) * BITS_PER_LONG >= sz) \ + goto out; \ + idx++; \ + } \ + \ + sz = min(idx * BITS_PER_LONG + __ffs(MUNGE(tmp)), sz); \ +out: \ + sz; \ +}) +static inline unsigned long _find_next_andnot_bit(const unsigned long *addr1, const unsigned long *addr2, + unsigned long nbits, unsigned long start) +{ + return FIND_NEXT_BIT(addr1[idx] & ~addr2[idx], /* nop */, nbits, start); +} + +static inline unsigned long find_next_andnot_bit(const unsigned long *addr1, + const unsigned long *addr2, unsigned long size, + unsigned long offset) +{ + if (small_const_nbits(size)) { + unsigned long val; + + if (unlikely(offset >= size)) + return size; + + val = *addr1 & ~*addr2 & __GENMASK(size - 1, offset); + return val ? __ffs(val) : size; + } + + return _find_next_andnot_bit(addr1, addr2, size, offset); +} + #define find_first_bit(addr, size) find_next_bit((addr), (size), 0) #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) |