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

Configure Feed

Select the types of activity you want to include in your feed.

bitmap: add bitmap_weight_from()

The function calculates a Hamming weight of a bitmap starting from an
arbitrary bit.

Signed-off-by: Yury Norov <ynorov@nvidia.com>

+59
+33
include/linux/bitmap.h
··· 57 57 * bitmap_weight(src, nbits) Hamming Weight: number set bits 58 58 * bitmap_weight_and(src1, src2, nbits) Hamming Weight of and'ed bitmap 59 59 * bitmap_weight_andnot(src1, src2, nbits) Hamming Weight of andnot'ed bitmap 60 + * bitmap_weight_from(src, start, end) Hamming Weight starting from @start 60 61 * bitmap_set(dst, pos, nbits) Set specified bit area 61 62 * bitmap_clear(dst, pos, nbits) Clear specified bit area 62 63 * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area ··· 478 477 if (small_const_nbits(nbits)) 479 478 return hweight_long(*src1 & ~(*src2) & BITMAP_LAST_WORD_MASK(nbits)); 480 479 return __bitmap_weight_andnot(src1, src2, nbits); 480 + } 481 + 482 + /** 483 + * bitmap_weight_from - Hamming weight for a memory region 484 + * @bitmap: The base address 485 + * @start: The bitnumber to starts weighting 486 + * @end: the bitmap size in bits 487 + * 488 + * Returns the number of set bits in the region. If @start >= @end, 489 + * return >= end. 490 + */ 491 + static __always_inline 492 + unsigned long bitmap_weight_from(const unsigned long *bitmap, 493 + unsigned int start, unsigned int end) 494 + { 495 + unsigned long w; 496 + 497 + if (unlikely(start >= end)) 498 + return end; 499 + 500 + if (small_const_nbits(end)) 501 + return hweight_long(*bitmap & GENMASK(end - 1, start)); 502 + 503 + bitmap += start / BITS_PER_LONG; 504 + /* Opencode round_down() to not include math.h */ 505 + end -= start & ~(BITS_PER_LONG - 1); 506 + start %= BITS_PER_LONG; 507 + w = bitmap_weight(bitmap, end); 508 + if (start) 509 + w -= hweight_long(*bitmap & BITMAP_LAST_WORD_MASK(start)); 510 + 511 + return w; 481 512 } 482 513 483 514 static __always_inline
+26
lib/test_bitmap.c
··· 854 854 } 855 855 } 856 856 857 + static void __init test_bitmap_weight(void) 858 + { 859 + unsigned int bit, w1, w2, w; 860 + DECLARE_BITMAP(b, 30); 861 + 862 + bitmap_parselist("all:1/2", b, 30); 863 + 864 + /* Test inline implementation */ 865 + w = bitmap_weight(b, 30); 866 + w1 = bitmap_weight(b, 15); 867 + w2 = bitmap_weight_from(b, 15, 30); 868 + 869 + expect_eq_uint(15, w); 870 + expect_eq_uint(8, w1); 871 + expect_eq_uint(7, w2); 872 + 873 + /* Test outline implementation */ 874 + w = bitmap_weight(exp1, EXP1_IN_BITS); 875 + for (bit = 0; bit < EXP1_IN_BITS; bit++) { 876 + w1 = bitmap_weight(exp1, bit); 877 + w2 = bitmap_weight_from(exp1, bit, EXP1_IN_BITS); 878 + expect_eq_uint(w1 + w2, w); 879 + } 880 + } 881 + 857 882 static void __init test_for_each_clear_bit(void) 858 883 { 859 884 DECLARE_BITMAP(orig, 500); ··· 1469 1444 test_bitmap_const_eval(); 1470 1445 test_bitmap_read_write(); 1471 1446 test_bitmap_read_perf(); 1447 + test_bitmap_weight(); 1472 1448 test_bitmap_write_perf(); 1473 1449 1474 1450 test_find_nth_bit();