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.

lib/bitmap: add bitmap_{read,write}()

The two new functions allow reading/writing values of length up to
BITS_PER_LONG bits at arbitrary position in the bitmap.

The code was taken from "bitops: Introduce the for_each_set_clump macro"
by Syed Nayyar Waris with a number of changes and simplifications:
- instead of using roundup(), which adds an unnecessary dependency
on <linux/math.h>, we calculate space as BITS_PER_LONG-offset;
- indentation is reduced by not using else-clauses (suggested by
checkpatch for bitmap_get_value());
- bitmap_get_value()/bitmap_set_value() are renamed to bitmap_read()
and bitmap_write();
- some redundant computations are omitted.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Syed Nayyar Waris <syednwaris@gmail.com>
Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
Link: https://lore.kernel.org/lkml/fe12eedf3666f4af5138de0e70b67a07c7f40338.1592224129.git.syednwaris@gmail.com/
Suggested-by: Yury Norov <yury.norov@gmail.com>
Co-developed-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Alexander Potapenko <glider@google.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Yury Norov <yury.norov@gmail.com>
Signed-off-by: Yury Norov <yury.norov@gmail.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Syed Nayyar Waris and committed by
David S. Miller
63c15822 d79b28fd

+77
+77
include/linux/bitmap.h
··· 83 83 * bitmap_to_arr64(buf, src, nbits) Copy nbits from buf to u64[] dst 84 84 * bitmap_get_value8(map, start) Get 8bit value from map at start 85 85 * bitmap_set_value8(map, value, start) Set 8bit value to map at start 86 + * bitmap_read(map, start, nbits) Read an nbits-sized value from 87 + * map at start 88 + * bitmap_write(map, value, start, nbits) Write an nbits-sized value to 89 + * map at start 86 90 * 87 91 * Note, bitmap_zero() and bitmap_fill() operate over the region of 88 92 * unsigned longs, that is, bits behind bitmap till the unsigned long ··· 756 752 757 753 map[index] &= ~(0xFFUL << offset); 758 754 map[index] |= value << offset; 755 + } 756 + 757 + /** 758 + * bitmap_read - read a value of n-bits from the memory region 759 + * @map: address to the bitmap memory region 760 + * @start: bit offset of the n-bit value 761 + * @nbits: size of value in bits, nonzero, up to BITS_PER_LONG 762 + * 763 + * Returns: value of @nbits bits located at the @start bit offset within the 764 + * @map memory region. For @nbits = 0 and @nbits > BITS_PER_LONG the return 765 + * value is undefined. 766 + */ 767 + static inline unsigned long bitmap_read(const unsigned long *map, 768 + unsigned long start, 769 + unsigned long nbits) 770 + { 771 + size_t index = BIT_WORD(start); 772 + unsigned long offset = start % BITS_PER_LONG; 773 + unsigned long space = BITS_PER_LONG - offset; 774 + unsigned long value_low, value_high; 775 + 776 + if (unlikely(!nbits || nbits > BITS_PER_LONG)) 777 + return 0; 778 + 779 + if (space >= nbits) 780 + return (map[index] >> offset) & BITMAP_LAST_WORD_MASK(nbits); 781 + 782 + value_low = map[index] & BITMAP_FIRST_WORD_MASK(start); 783 + value_high = map[index + 1] & BITMAP_LAST_WORD_MASK(start + nbits); 784 + return (value_low >> offset) | (value_high << space); 785 + } 786 + 787 + /** 788 + * bitmap_write - write n-bit value within a memory region 789 + * @map: address to the bitmap memory region 790 + * @value: value to write, clamped to nbits 791 + * @start: bit offset of the n-bit value 792 + * @nbits: size of value in bits, nonzero, up to BITS_PER_LONG. 793 + * 794 + * bitmap_write() behaves as-if implemented as @nbits calls of __assign_bit(), 795 + * i.e. bits beyond @nbits are ignored: 796 + * 797 + * for (bit = 0; bit < nbits; bit++) 798 + * __assign_bit(start + bit, bitmap, val & BIT(bit)); 799 + * 800 + * For @nbits == 0 and @nbits > BITS_PER_LONG no writes are performed. 801 + */ 802 + static inline void bitmap_write(unsigned long *map, unsigned long value, 803 + unsigned long start, unsigned long nbits) 804 + { 805 + size_t index; 806 + unsigned long offset; 807 + unsigned long space; 808 + unsigned long mask; 809 + bool fit; 810 + 811 + if (unlikely(!nbits || nbits > BITS_PER_LONG)) 812 + return; 813 + 814 + mask = BITMAP_LAST_WORD_MASK(nbits); 815 + value &= mask; 816 + offset = start % BITS_PER_LONG; 817 + space = BITS_PER_LONG - offset; 818 + fit = space >= nbits; 819 + index = BIT_WORD(start); 820 + 821 + map[index] &= (fit ? (~(mask << offset)) : ~BITMAP_FIRST_WORD_MASK(start)); 822 + map[index] |= value << offset; 823 + if (fit) 824 + return; 825 + 826 + map[index + 1] &= BITMAP_FIRST_WORD_MASK(start + nbits); 827 + map[index + 1] |= (value >> space); 759 828 } 760 829 761 830 #endif /* __ASSEMBLY__ */