Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/bitmap: add bitmap_weight_and()

The function calculates Hamming weight of (bitmap1 & bitmap2). Now we
have to do like this:
tmp = bitmap_alloc(nbits);
bitmap_and(tmp, map1, map2, nbits);
weight = bitmap_weight(tmp, nbits);
bitmap_free(tmp);

This requires additional memory, adds pressure on alloc subsystem, and
way less cache-friendly than just:
weight = bitmap_weight_and(map1, map2, nbits);

The following patches apply it for cpumask functions.

Signed-off-by: Yury Norov <yury.norov@gmail.com>

+44 -9
+12
include/linux/bitmap.h
··· 51 51 * bitmap_empty(src, nbits) Are all bits zero in *src? 52 52 * bitmap_full(src, nbits) Are all bits set in *src? 53 53 * bitmap_weight(src, nbits) Hamming Weight: number set bits 54 + * bitmap_weight_and(src1, src2, nbits) Hamming Weight of and'ed bitmap 54 55 * bitmap_set(dst, pos, nbits) Set specified bit area 55 56 * bitmap_clear(dst, pos, nbits) Clear specified bit area 56 57 * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area ··· 165 164 bool __bitmap_subset(const unsigned long *bitmap1, 166 165 const unsigned long *bitmap2, unsigned int nbits); 167 166 unsigned int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits); 167 + unsigned int __bitmap_weight_and(const unsigned long *bitmap1, 168 + const unsigned long *bitmap2, unsigned int nbits); 168 169 void __bitmap_set(unsigned long *map, unsigned int start, int len); 169 170 void __bitmap_clear(unsigned long *map, unsigned int start, int len); 170 171 ··· 440 437 if (small_const_nbits(nbits)) 441 438 return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)); 442 439 return __bitmap_weight(src, nbits); 440 + } 441 + 442 + static __always_inline 443 + unsigned long bitmap_weight_and(const unsigned long *src1, 444 + const unsigned long *src2, unsigned int nbits) 445 + { 446 + if (small_const_nbits(nbits)) 447 + return hweight_long(*src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)); 448 + return __bitmap_weight_and(src1, src2, nbits); 443 449 } 444 450 445 451 static __always_inline void bitmap_set(unsigned long *map, unsigned int start,
+11
include/linux/cpumask.h
··· 587 587 } 588 588 589 589 /** 590 + * cpumask_weight_and - Count of bits in (*srcp1 & *srcp2) 591 + * @srcp1: the cpumask to count bits (< nr_cpu_ids) in. 592 + * @srcp2: the cpumask to count bits (< nr_cpu_ids) in. 593 + */ 594 + static inline unsigned int cpumask_weight_and(const struct cpumask *srcp1, 595 + const struct cpumask *srcp2) 596 + { 597 + return bitmap_weight_and(cpumask_bits(srcp1), cpumask_bits(srcp2), nr_cpumask_bits); 598 + } 599 + 600 + /** 590 601 * cpumask_shift_right - *dstp = *srcp >> n 591 602 * @dstp: the cpumask result 592 603 * @srcp: the input to shift
+21 -9
lib/bitmap.c
··· 333 333 } 334 334 EXPORT_SYMBOL(__bitmap_subset); 335 335 336 + #define BITMAP_WEIGHT(FETCH, bits) \ 337 + ({ \ 338 + unsigned int __bits = (bits), idx, w = 0; \ 339 + \ 340 + for (idx = 0; idx < __bits / BITS_PER_LONG; idx++) \ 341 + w += hweight_long(FETCH); \ 342 + \ 343 + if (__bits % BITS_PER_LONG) \ 344 + w += hweight_long((FETCH) & BITMAP_LAST_WORD_MASK(__bits)); \ 345 + \ 346 + w; \ 347 + }) 348 + 336 349 unsigned int __bitmap_weight(const unsigned long *bitmap, unsigned int bits) 337 350 { 338 - unsigned int k, lim = bits/BITS_PER_LONG, w = 0; 339 - 340 - for (k = 0; k < lim; k++) 341 - w += hweight_long(bitmap[k]); 342 - 343 - if (bits % BITS_PER_LONG) 344 - w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); 345 - 346 - return w; 351 + return BITMAP_WEIGHT(bitmap[idx], bits); 347 352 } 348 353 EXPORT_SYMBOL(__bitmap_weight); 354 + 355 + unsigned int __bitmap_weight_and(const unsigned long *bitmap1, 356 + const unsigned long *bitmap2, unsigned int bits) 357 + { 358 + return BITMAP_WEIGHT(bitmap1[idx] & bitmap2[idx], bits); 359 + } 360 + EXPORT_SYMBOL(__bitmap_weight_and); 349 361 350 362 void __bitmap_set(unsigned long *map, unsigned int start, int len) 351 363 {