1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2915b0882SArnaldo Carvalho de Melo #ifndef _PERF_BITOPS_H 3915b0882SArnaldo Carvalho de Melo #define _PERF_BITOPS_H 4915b0882SArnaldo Carvalho de Melo 5915b0882SArnaldo Carvalho de Melo #include <string.h> 6915b0882SArnaldo Carvalho de Melo #include <linux/bitops.h> 798c03296SJiri Olsa #include <stdlib.h> 8c68a2aabSMatthew Wilcox #include <linux/kernel.h> 9915b0882SArnaldo Carvalho de Melo 10915b0882SArnaldo Carvalho de Melo #define DECLARE_BITMAP(name,bits) \ 11915b0882SArnaldo Carvalho de Melo unsigned long name[BITS_TO_LONGS(bits)] 12915b0882SArnaldo Carvalho de Melo 13915b0882SArnaldo Carvalho de Melo int __bitmap_weight(const unsigned long *bitmap, int bits); 14915b0882SArnaldo Carvalho de Melo void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 15915b0882SArnaldo Carvalho de Melo const unsigned long *bitmap2, int bits); 16741c74f5SJiri Olsa int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, 17741c74f5SJiri Olsa const unsigned long *bitmap2, unsigned int bits); 18915b0882SArnaldo Carvalho de Melo 19915b0882SArnaldo Carvalho de Melo #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) 20915b0882SArnaldo Carvalho de Melo 21915b0882SArnaldo Carvalho de Melo #define BITMAP_LAST_WORD_MASK(nbits) \ 22915b0882SArnaldo Carvalho de Melo ( \ 23915b0882SArnaldo Carvalho de Melo ((nbits) % BITS_PER_LONG) ? \ 24915b0882SArnaldo Carvalho de Melo (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ 25915b0882SArnaldo Carvalho de Melo ) 26915b0882SArnaldo Carvalho de Melo 27915b0882SArnaldo Carvalho de Melo #define small_const_nbits(nbits) \ 28915b0882SArnaldo Carvalho de Melo (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG) 29915b0882SArnaldo Carvalho de Melo 30915b0882SArnaldo Carvalho de Melo static inline void bitmap_zero(unsigned long *dst, int nbits) 31915b0882SArnaldo Carvalho de Melo { 32915b0882SArnaldo Carvalho de Melo if (small_const_nbits(nbits)) 33915b0882SArnaldo Carvalho de Melo *dst = 0UL; 34915b0882SArnaldo Carvalho de Melo else { 35915b0882SArnaldo Carvalho de Melo int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); 36915b0882SArnaldo Carvalho de Melo memset(dst, 0, len); 37915b0882SArnaldo Carvalho de Melo } 38915b0882SArnaldo Carvalho de Melo } 39915b0882SArnaldo Carvalho de Melo 40b328daf3SMatthew Wilcox static inline void bitmap_fill(unsigned long *dst, unsigned int nbits) 41b328daf3SMatthew Wilcox { 42b328daf3SMatthew Wilcox unsigned int nlongs = BITS_TO_LONGS(nbits); 43b328daf3SMatthew Wilcox if (!small_const_nbits(nbits)) { 44b328daf3SMatthew Wilcox unsigned int len = (nlongs - 1) * sizeof(unsigned long); 45b328daf3SMatthew Wilcox memset(dst, 0xff, len); 46b328daf3SMatthew Wilcox } 47b328daf3SMatthew Wilcox dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits); 48b328daf3SMatthew Wilcox } 49b328daf3SMatthew Wilcox 50b328daf3SMatthew Wilcox static inline int bitmap_empty(const unsigned long *src, unsigned nbits) 51b328daf3SMatthew Wilcox { 52b328daf3SMatthew Wilcox if (small_const_nbits(nbits)) 53b328daf3SMatthew Wilcox return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); 54b328daf3SMatthew Wilcox 55b328daf3SMatthew Wilcox return find_first_bit(src, nbits) == nbits; 56b328daf3SMatthew Wilcox } 57b328daf3SMatthew Wilcox 58b328daf3SMatthew Wilcox static inline int bitmap_full(const unsigned long *src, unsigned int nbits) 59b328daf3SMatthew Wilcox { 60b328daf3SMatthew Wilcox if (small_const_nbits(nbits)) 61b328daf3SMatthew Wilcox return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); 62b328daf3SMatthew Wilcox 63b328daf3SMatthew Wilcox return find_first_zero_bit(src, nbits) == nbits; 64b328daf3SMatthew Wilcox } 65b328daf3SMatthew Wilcox 66915b0882SArnaldo Carvalho de Melo static inline int bitmap_weight(const unsigned long *src, int nbits) 67915b0882SArnaldo Carvalho de Melo { 68915b0882SArnaldo Carvalho de Melo if (small_const_nbits(nbits)) 69915b0882SArnaldo Carvalho de Melo return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)); 70915b0882SArnaldo Carvalho de Melo return __bitmap_weight(src, nbits); 71915b0882SArnaldo Carvalho de Melo } 72915b0882SArnaldo Carvalho de Melo 73915b0882SArnaldo Carvalho de Melo static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, 74915b0882SArnaldo Carvalho de Melo const unsigned long *src2, int nbits) 75915b0882SArnaldo Carvalho de Melo { 76915b0882SArnaldo Carvalho de Melo if (small_const_nbits(nbits)) 77915b0882SArnaldo Carvalho de Melo *dst = *src1 | *src2; 78915b0882SArnaldo Carvalho de Melo else 79915b0882SArnaldo Carvalho de Melo __bitmap_or(dst, src1, src2, nbits); 80915b0882SArnaldo Carvalho de Melo } 81915b0882SArnaldo Carvalho de Melo 82915b0882SArnaldo Carvalho de Melo /** 83915b0882SArnaldo Carvalho de Melo * test_and_set_bit - Set a bit and return its old value 84915b0882SArnaldo Carvalho de Melo * @nr: Bit to set 85915b0882SArnaldo Carvalho de Melo * @addr: Address to count from 86915b0882SArnaldo Carvalho de Melo */ 87915b0882SArnaldo Carvalho de Melo static inline int test_and_set_bit(int nr, unsigned long *addr) 88915b0882SArnaldo Carvalho de Melo { 89915b0882SArnaldo Carvalho de Melo unsigned long mask = BIT_MASK(nr); 90915b0882SArnaldo Carvalho de Melo unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); 91915b0882SArnaldo Carvalho de Melo unsigned long old; 92915b0882SArnaldo Carvalho de Melo 93915b0882SArnaldo Carvalho de Melo old = *p; 94915b0882SArnaldo Carvalho de Melo *p = old | mask; 95915b0882SArnaldo Carvalho de Melo 96915b0882SArnaldo Carvalho de Melo return (old & mask) != 0; 97915b0882SArnaldo Carvalho de Melo } 98915b0882SArnaldo Carvalho de Melo 9998c03296SJiri Olsa /** 10098c03296SJiri Olsa * bitmap_alloc - Allocate bitmap 101*e2091cedSJiri Olsa * @nbits: Number of bits 10298c03296SJiri Olsa */ 10398c03296SJiri Olsa static inline unsigned long *bitmap_alloc(int nbits) 10498c03296SJiri Olsa { 10598c03296SJiri Olsa return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long)); 10698c03296SJiri Olsa } 10798c03296SJiri Olsa 108820d12b7SJiri Olsa /* 109820d12b7SJiri Olsa * bitmap_scnprintf - print bitmap list into buffer 110820d12b7SJiri Olsa * @bitmap: bitmap 111820d12b7SJiri Olsa * @nbits: size of bitmap 112820d12b7SJiri Olsa * @buf: buffer to store output 113820d12b7SJiri Olsa * @size: size of @buf 114820d12b7SJiri Olsa */ 115820d12b7SJiri Olsa size_t bitmap_scnprintf(unsigned long *bitmap, int nbits, 116820d12b7SJiri Olsa char *buf, size_t size); 117820d12b7SJiri Olsa 118741c74f5SJiri Olsa /** 119741c74f5SJiri Olsa * bitmap_and - Do logical and on bitmaps 120741c74f5SJiri Olsa * @dst: resulting bitmap 121741c74f5SJiri Olsa * @src1: operand 1 122741c74f5SJiri Olsa * @src2: operand 2 123741c74f5SJiri Olsa * @nbits: size of bitmap 124741c74f5SJiri Olsa */ 125741c74f5SJiri Olsa static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, 126741c74f5SJiri Olsa const unsigned long *src2, unsigned int nbits) 127741c74f5SJiri Olsa { 128741c74f5SJiri Olsa if (small_const_nbits(nbits)) 129741c74f5SJiri Olsa return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0; 130741c74f5SJiri Olsa return __bitmap_and(dst, src1, src2, nbits); 131741c74f5SJiri Olsa } 132741c74f5SJiri Olsa 133915b0882SArnaldo Carvalho de Melo #endif /* _PERF_BITOPS_H */ 134