[PATCH v11 02/30] find: add find_first_andnot_bit()

James Morse posted 30 patches 9 months ago
There is a newer version of this series
[PATCH v11 02/30] find: add find_first_andnot_bit()
Posted by James Morse 9 months ago
From: "Yury Norov [NVIDIA]" <yury.norov@gmail.com>

The function helps to implement cpumask_andnot() APIs.

Tested-by: James Morse <james.morse@arm.com>
Reviewed-by: James Morse <james.morse@arm.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
Signed-off-by: James Morse <james.morse@arm.com>
---
 include/linux/find.h | 25 +++++++++++++++++++++++++
 lib/find_bit.c       | 11 +++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/linux/find.h b/include/linux/find.h
index 68685714bc18..5a2c267ea7f9 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_andnot_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);
@@ -347,6 +349,29 @@ unsigned long find_first_and_bit(const unsigned long *addr1,
 }
 #endif
 
+/**
+ * find_first_andnot_bit - find the first bit set in 1st memory region and unset in 2nd
+ * @addr1: The first address to base the search on
+ * @addr2: The second 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 __always_inline
+unsigned long find_first_andnot_bit(const unsigned long *addr1,
+				 const unsigned long *addr2,
+				 unsigned long size)
+{
+	if (small_const_nbits(size)) {
+		unsigned long val = *addr1 & (~*addr2) & GENMASK(size - 1, 0);
+
+		return val ? __ffs(val) : size;
+	}
+
+	return _find_first_andnot_bit(addr1, addr2, size);
+}
+
 /**
  * find_first_and_and_bit - find the first set bit in 3 memory regions
  * @addr1: The first address to base the search on
diff --git a/lib/find_bit.c b/lib/find_bit.c
index 0836bb3d76c5..06b6342aa3ae 100644
--- a/lib/find_bit.c
+++ b/lib/find_bit.c
@@ -116,6 +116,17 @@ unsigned long _find_first_and_bit(const unsigned long *addr1,
 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.
  */
-- 
2.39.5
Re: [PATCH v11 02/30] find: add find_first_andnot_bit()
Posted by Fenghua Yu 9 months ago
Hi, James and Yury,

On 5/13/25 10:15, James Morse wrote:
> From: "Yury Norov [NVIDIA]" <yury.norov@gmail.com>
>
> The function helps to implement cpumask_andnot() APIs.
>
> Tested-by: James Morse <james.morse@arm.com>
> Reviewed-by: James Morse <james.morse@arm.com>
> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
> Signed-off-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
>   include/linux/find.h | 25 +++++++++++++++++++++++++
>   lib/find_bit.c       | 11 +++++++++++
>   2 files changed, 36 insertions(+)
>
> diff --git a/include/linux/find.h b/include/linux/find.h
> index 68685714bc18..5a2c267ea7f9 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_andnot_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);
> @@ -347,6 +349,29 @@ unsigned long find_first_and_bit(const unsigned long *addr1,
>   }
>   #endif
>   
> +/**
> + * find_first_andnot_bit - find the first bit set in 1st memory region and unset in 2nd
> + * @addr1: The first address to base the search on
> + * @addr2: The second 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 __always_inline
> +unsigned long find_first_andnot_bit(const unsigned long *addr1,
> +				 const unsigned long *addr2,
> +				 unsigned long size)
CHECK: Alignment should match open parenthesis

> +{
> +	if (small_const_nbits(size)) {
> +		unsigned long val = *addr1 & (~*addr2) & GENMASK(size - 1, 0);
> +
> +		return val ? __ffs(val) : size;
> +	}
> +
> +	return _find_first_andnot_bit(addr1, addr2, size);
> +}
> +
>   /**
>    * find_first_and_and_bit - find the first set bit in 3 memory regions
>    * @addr1: The first address to base the search on
> diff --git a/lib/find_bit.c b/lib/find_bit.c
> index 0836bb3d76c5..06b6342aa3ae 100644
> --- a/lib/find_bit.c
> +++ b/lib/find_bit.c
> @@ -116,6 +116,17 @@ unsigned long _find_first_and_bit(const unsigned long *addr1,
>   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)
Ditto.
> +{
> +	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.
>    */

Thanks.

-Fenghua
Re: [PATCH v11 02/30] find: add find_first_andnot_bit()
Posted by Reinette Chatre 9 months ago
Hi Fenghua,

On 5/14/25 12:59 PM, Fenghua Yu wrote:
> Hi, James and Yury,
> 
> On 5/13/25 10:15, James Morse wrote:
>> From: "Yury Norov [NVIDIA]" <yury.norov@gmail.com>
>>
>> The function helps to implement cpumask_andnot() APIs.
>>
>> Tested-by: James Morse <james.morse@arm.com>
>> Reviewed-by: James Morse <james.morse@arm.com>
>> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
>> Signed-off-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
>> Signed-off-by: James Morse <james.morse@arm.com>
>> ---
>>   include/linux/find.h | 25 +++++++++++++++++++++++++
>>   lib/find_bit.c       | 11 +++++++++++
>>   2 files changed, 36 insertions(+)
>>
>> diff --git a/include/linux/find.h b/include/linux/find.h
>> index 68685714bc18..5a2c267ea7f9 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_andnot_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);
>> @@ -347,6 +349,29 @@ unsigned long find_first_and_bit(const unsigned long *addr1,
>>   }
>>   #endif
>>   +/**
>> + * find_first_andnot_bit - find the first bit set in 1st memory region and unset in 2nd
>> + * @addr1: The first address to base the search on
>> + * @addr2: The second 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 __always_inline
>> +unsigned long find_first_andnot_bit(const unsigned long *addr1,
>> +                 const unsigned long *addr2,
>> +                 unsigned long size)
> CHECK: Alignment should match open parenthesis
> 

This was brought up [2] during review of V1 of this specific work [1]. 

Please compare this code to the rest of the file. Specifically, this
alignment guidance is not adhered to in this file. In this contribution
we thus accept the contribution from bitmap API maintainer (Yury) without
dictating how formatting should be done.

Reinette

[1] https://lore.kernel.org/all/20250407153856.133093-1-yury.norov@gmail.com/
[2] https://lore.kernel.org/all/062e5e61-e2c3-418e-987b-33fd9009d03f@intel.com/

Re: [PATCH v11 02/30] find: add find_first_andnot_bit()
Posted by Fenghua Yu 9 months ago
Hi, Reinette,

On 5/14/25 13:19, Reinette Chatre wrote:
> Hi Fenghua,
>
> On 5/14/25 12:59 PM, Fenghua Yu wrote:
>> Hi, James and Yury,
>>
>> On 5/13/25 10:15, James Morse wrote:
>>> From: "Yury Norov [NVIDIA]" <yury.norov@gmail.com>
>>>
>>> The function helps to implement cpumask_andnot() APIs.
>>>
>>> Tested-by: James Morse <james.morse@arm.com>
>>> Reviewed-by: James Morse <james.morse@arm.com>
>>> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
>>> Signed-off-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
>>> Signed-off-by: James Morse <james.morse@arm.com>
>>> ---
>>>    include/linux/find.h | 25 +++++++++++++++++++++++++
>>>    lib/find_bit.c       | 11 +++++++++++
>>>    2 files changed, 36 insertions(+)
>>>
>>> diff --git a/include/linux/find.h b/include/linux/find.h
>>> index 68685714bc18..5a2c267ea7f9 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_andnot_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);
>>> @@ -347,6 +349,29 @@ unsigned long find_first_and_bit(const unsigned long *addr1,
>>>    }
>>>    #endif
>>>    +/**
>>> + * find_first_andnot_bit - find the first bit set in 1st memory region and unset in 2nd
>>> + * @addr1: The first address to base the search on
>>> + * @addr2: The second 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 __always_inline
>>> +unsigned long find_first_andnot_bit(const unsigned long *addr1,
>>> +                 const unsigned long *addr2,
>>> +                 unsigned long size)
>> CHECK: Alignment should match open parenthesis
>>
> This was brought up [2] during review of V1 of this specific work [1].
>
> Please compare this code to the rest of the file. Specifically, this
> alignment guidance is not adhered to in this file. In this contribution
> we thus accept the contribution from bitmap API maintainer (Yury) without
> dictating how formatting should be done.
>
> Reinette
>
> [1] https://lore.kernel.org/all/20250407153856.133093-1-yury.norov@gmail.com/
> [2] https://lore.kernel.org/all/062e5e61-e2c3-418e-987b-33fd9009d03f@intel.com/
>
Thanks for the info. This check is acceptable here. I already put my 
Reviewed-by on this patch.

-Fenghua

Re: [PATCH v11 02/30] find: add find_first_andnot_bit()
Posted by Fenghua Yu 9 months ago
On 5/13/25 10:15, James Morse wrote:
> From: "Yury Norov [NVIDIA]" <yury.norov@gmail.com>
>
> The function helps to implement cpumask_andnot() APIs.
>
> Tested-by: James Morse <james.morse@arm.com>
> Reviewed-by: James Morse <james.morse@arm.com>
> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
> Signed-off-by: Yury Norov [NVIDIA] <yury.norov@gmail.com>
> Signed-off-by: James Morse <james.morse@arm.com>

Reviewed-by: Fenghua Yu <fenghuay@nvidia.com>

Thanks.

-Fenghua