On 12/17/2023 1:32 PM, Yury Norov wrote: > Similarly to cpumask_weight_and(), cpumask_weight_andnot() is a handy > helper that may help to avoid creating an intermediate mask just to > calculate number of bits that set in a 1st given mask, and clear in 2nd > one. > > Signed-off-by: Yury Norov <yury.norov@xxxxxxxxx> This seems reasonable to me. Reviewed-by: Jacob Keller <jacob.e.keller@xxxxxxxxx> > --- > include/linux/bitmap.h | 12 ++++++++++++ > include/linux/cpumask.h | 13 +++++++++++++ > lib/bitmap.c | 7 +++++++ > 3 files changed, 32 insertions(+) > > diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h > index 99451431e4d6..5814e9ee40ba 100644 > --- a/include/linux/bitmap.h > +++ b/include/linux/bitmap.h > @@ -54,6 +54,7 @@ struct device; > * bitmap_full(src, nbits) Are all bits set in *src? > * bitmap_weight(src, nbits) Hamming Weight: number set bits > * bitmap_weight_and(src1, src2, nbits) Hamming Weight of and'ed bitmap > + * bitmap_weight_andnot(src1, src2, nbits) Hamming Weight of andnot'ed bitmap > * bitmap_set(dst, pos, nbits) Set specified bit area > * bitmap_clear(dst, pos, nbits) Clear specified bit area > * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area > @@ -169,6 +170,8 @@ bool __bitmap_subset(const unsigned long *bitmap1, > unsigned int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits); > unsigned int __bitmap_weight_and(const unsigned long *bitmap1, > const unsigned long *bitmap2, unsigned int nbits); > +unsigned int __bitmap_weight_andnot(const unsigned long *bitmap1, > + const unsigned long *bitmap2, unsigned int nbits); > void __bitmap_set(unsigned long *map, unsigned int start, int len); > void __bitmap_clear(unsigned long *map, unsigned int start, int len); > > @@ -425,6 +428,15 @@ unsigned long bitmap_weight_and(const unsigned long *src1, > return __bitmap_weight_and(src1, src2, nbits); > } > > +static __always_inline > +unsigned long bitmap_weight_andnot(const unsigned long *src1, > + const unsigned long *src2, unsigned int nbits) > +{ > + if (small_const_nbits(nbits)) > + return hweight_long(*src1 & ~(*src2) & BITMAP_LAST_WORD_MASK(nbits)); > + return __bitmap_weight_andnot(src1, src2, nbits); > +} > + > static __always_inline void bitmap_set(unsigned long *map, unsigned int start, > unsigned int nbits) > { > diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h > index cfb545841a2c..228c23eb36d2 100644 > --- a/include/linux/cpumask.h > +++ b/include/linux/cpumask.h > @@ -719,6 +719,19 @@ static inline unsigned int cpumask_weight_and(const struct cpumask *srcp1, > return bitmap_weight_and(cpumask_bits(srcp1), cpumask_bits(srcp2), small_cpumask_bits); > } > > +/** > + * cpumask_weight_andnot - Count of bits in (*srcp1 & ~*srcp2) > + * @srcp1: the cpumask to count bits (< nr_cpu_ids) in. > + * @srcp2: the cpumask to count bits (< nr_cpu_ids) in. > + * > + * Return: count of bits set in both *srcp1 and *srcp2 > + */ > +static inline unsigned int cpumask_weight_andnot(const struct cpumask *srcp1, > + const struct cpumask *srcp2) > +{ > + return bitmap_weight_andnot(cpumask_bits(srcp1), cpumask_bits(srcp2), small_cpumask_bits); > +} > + > /** > * cpumask_shift_right - *dstp = *srcp >> n > * @dstp: the cpumask result > diff --git a/lib/bitmap.c b/lib/bitmap.c > index 09522af227f1..b97692854966 100644 > --- a/lib/bitmap.c > +++ b/lib/bitmap.c > @@ -348,6 +348,13 @@ unsigned int __bitmap_weight_and(const unsigned long *bitmap1, > } > EXPORT_SYMBOL(__bitmap_weight_and); > > +unsigned int __bitmap_weight_andnot(const unsigned long *bitmap1, > + const unsigned long *bitmap2, unsigned int bits) > +{ > + return BITMAP_WEIGHT(bitmap1[idx] & ~bitmap2[idx], bits); > +} > +EXPORT_SYMBOL(__bitmap_weight_andnot); > + > void __bitmap_set(unsigned long *map, unsigned int start, int len) > { > unsigned long *p = map + BIT_WORD(start);