diff options
author | Yury Norov <yury.norov@gmail.com> | 2021-08-14 23:17:01 +0200 |
---|---|---|
committer | Yury Norov <yury.norov@gmail.com> | 2022-01-15 17:47:31 +0100 |
commit | f68edc9297bf3f7c94abb54b9b0b053607f7587b (patch) | |
tree | f4e963ec2db91a06210c3b7886a233c16e411323 /lib/find_bit.c | |
parent | arch: remove GENERIC_FIND_FIRST_BIT entirely (diff) | |
download | linux-f68edc9297bf3f7c94abb54b9b0b053607f7587b.tar.xz linux-f68edc9297bf3f7c94abb54b9b0b053607f7587b.zip |
lib: add find_first_and_bit()
Currently find_first_and_bit() is an alias to find_next_and_bit(). However,
it is widely used in cpumask, so it worth to optimize it. This patch adds
its own implementation for find_first_and_bit().
On x86_64 find_bit_benchmark says:
Before (#define find_first_and_bit(...) find_next_and_bit(..., 0):
Start testing find_bit() with random-filled bitmap
[ 140.291468] find_first_and_bit: 46890919 ns, 32671 iterations
Start testing find_bit() with sparse bitmap
[ 140.295028] find_first_and_bit: 7103 ns, 1 iterations
After:
Start testing find_bit() with random-filled bitmap
[ 162.574907] find_first_and_bit: 25045813 ns, 32846 iterations
Start testing find_bit() with sparse bitmap
[ 162.578458] find_first_and_bit: 4900 ns, 1 iterations
(Thanks to Alexey Klimov for thorough testing.)
Signed-off-by: Yury Norov <yury.norov@gmail.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Alexey Klimov <aklimov@redhat.com>
Diffstat (limited to 'lib/find_bit.c')
-rw-r--r-- | lib/find_bit.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/lib/find_bit.c b/lib/find_bit.c index 0f8e2e369b1d..1b8e4b2a9cba 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c @@ -89,6 +89,27 @@ unsigned long _find_first_bit(const unsigned long *addr, unsigned long size) EXPORT_SYMBOL(_find_first_bit); #endif +#ifndef find_first_and_bit +/* + * Find the first set bit in two memory regions. + */ +unsigned long _find_first_and_bit(const unsigned long *addr1, + const unsigned long *addr2, + unsigned long size) +{ + unsigned long idx, val; + + for (idx = 0; idx * BITS_PER_LONG < size; idx++) { + val = addr1[idx] & addr2[idx]; + if (val) + return min(idx * BITS_PER_LONG + __ffs(val), size); + } + + return size; +} +EXPORT_SYMBOL(_find_first_and_bit); +#endif + #ifndef find_first_zero_bit /* * Find the first cleared bit in a memory region. |