mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
lib: add find_nth{,_and,_andnot}_bit()
Kernel lacks for a function that searches for Nth bit in a bitmap. Usually people do it like this: for_each_set_bit(bit, mask, size) if (n-- == 0) return bit; We can do it more efficiently, if we: 1. find a word containing Nth bit, using hweight(); and 2. find the bit, using a helper fns(), that works similarly to __ffs() and ffz(). fns() is implemented as a simple loop. For x86_64, there's PDEP instruction to do that: ret = clz(pdep(1 << idx, num)). However, for large bitmaps the most of improvement comes from using hweight(), so I kept fns() simple. New find_nth_bit() is ~70 times faster on x86_64/kvm in find_bit benchmark: find_nth_bit: 7154190 ns, 16411 iterations for_each_bit: 505493126 ns, 16315 iterations With all that, a family of 3 new functions is added, and used where appropriate in the following patches. Signed-off-by: Yury Norov <yury.norov@gmail.com>
This commit is contained in:
parent
24291caf84
commit
3cea8d4753
3 changed files with 149 additions and 0 deletions
|
@ -247,6 +247,25 @@ static inline unsigned long __ffs64(u64 word)
|
|||
return __ffs((unsigned long)word);
|
||||
}
|
||||
|
||||
/**
|
||||
* fns - find N'th set bit in a word
|
||||
* @word: The word to search
|
||||
* @n: Bit to find
|
||||
*/
|
||||
static inline unsigned long fns(unsigned long word, unsigned int n)
|
||||
{
|
||||
unsigned int bit;
|
||||
|
||||
while (word) {
|
||||
bit = __ffs(word);
|
||||
if (n-- == 0)
|
||||
return bit;
|
||||
__clear_bit(bit, &word);
|
||||
}
|
||||
|
||||
return BITS_PER_LONG;
|
||||
}
|
||||
|
||||
/**
|
||||
* assign_bit - Assign value to a bit in memory
|
||||
* @nr: the bit to set
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue