From cdc66553c4130735f0a2db943a5259e54ff1597a Mon Sep 17 00:00:00 2001 From: Dawei Li Date: Tue, 16 Apr 2024 16:54:48 +0800 Subject: cpumask: Introduce cpumask_first_and_and() Introduce cpumask_first_and_and() to get intersection between 3 cpumasks, free of any intermediate cpumask variable. Instead, cpumask_first_and_and() works in-place with all inputs and produces desired output directly. Signed-off-by: Dawei Li Signed-off-by: Thomas Gleixner Acked-by: Yury Norov Link: https://lore.kernel.org/r/20240416085454.3547175-2-dawei.li@shingroup.cn --- include/linux/find.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'include/linux/find.h') diff --git a/include/linux/find.h b/include/linux/find.h index c69598e383c1..28ec5a03393a 100644 --- a/include/linux/find.h +++ b/include/linux/find.h @@ -29,6 +29,8 @@ unsigned long __find_nth_and_andnot_bit(const unsigned long *addr1, const unsign unsigned long n); extern unsigned long _find_first_and_bit(const unsigned long *addr1, const unsigned long *addr2, unsigned long size); +unsigned long _find_first_and_and_bit(const unsigned long *addr1, const unsigned long *addr2, + const unsigned long *addr3, unsigned long size); extern unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned long size); extern unsigned long _find_last_bit(const unsigned long *addr, unsigned long size); @@ -345,6 +347,31 @@ unsigned long find_first_and_bit(const unsigned long *addr1, } #endif +/** + * find_first_and_and_bit - find the first set bit in 3 memory regions + * @addr1: The first address to base the search on + * @addr2: The second address to base the search on + * @addr3: The third address to base the search on + * @size: The bitmap size in bits + * + * Returns the bit number for the first set bit + * If no bits are set, returns @size. + */ +static inline +unsigned long find_first_and_and_bit(const unsigned long *addr1, + const unsigned long *addr2, + const unsigned long *addr3, + unsigned long size) +{ + if (small_const_nbits(size)) { + unsigned long val = *addr1 & *addr2 & *addr3 & GENMASK(size - 1, 0); + + return val ? __ffs(val) : size; + } + + return _find_first_and_and_bit(addr1, addr2, addr3, size); +} + #ifndef find_first_zero_bit /** * find_first_zero_bit - find the first cleared bit in a memory region -- cgit v1.2.3 From 0b2811ba11b04353033237359c9d042eb0cdc1c1 Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Thu, 2 May 2024 10:12:56 -0700 Subject: bitmap: relax find_nth_bit() limitation on return value The function claims to return the bitmap size, if Nth bit doesn't exist. This rule is violated in inline case because the fns() that is used there doesn't know anything about size of the bitmap. So, relax this requirement to '>= size', and make the outline implementation a bit cheaper. All in-tree kernel users of find_nth_bit() are safe against that. Reported-by: Rasmus Villemoes Closes: https://lore.kernel.org/all/Zi50cAgR8nZvgLa3@yury-ThinkPad/T/#m6da806a0525e74dcc91f35e5f20766ed4e853e8a Signed-off-by: Yury Norov --- include/linux/find.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/find.h') diff --git a/include/linux/find.h b/include/linux/find.h index c69598e383c1..02751e43d448 100644 --- a/include/linux/find.h +++ b/include/linux/find.h @@ -220,7 +220,7 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size) * idx = find_first_bit(addr, size); * * Returns the bit number of the N'th set bit. - * If no such, returns @size. + * If no such, returns >= @size. */ static inline unsigned long find_nth_bit(const unsigned long *addr, unsigned long size, unsigned long n) -- cgit v1.2.3