18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _PERF_BITOPS_H 38c2ecf20Sopenharmony_ci#define _PERF_BITOPS_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <string.h> 68c2ecf20Sopenharmony_ci#include <linux/bitops.h> 78c2ecf20Sopenharmony_ci#include <stdlib.h> 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define DECLARE_BITMAP(name,bits) \ 118c2ecf20Sopenharmony_ci unsigned long name[BITS_TO_LONGS(bits)] 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciint __bitmap_weight(const unsigned long *bitmap, int bits); 148c2ecf20Sopenharmony_civoid __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 158c2ecf20Sopenharmony_ci const unsigned long *bitmap2, int bits); 168c2ecf20Sopenharmony_ciint __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, 178c2ecf20Sopenharmony_ci const unsigned long *bitmap2, unsigned int bits); 188c2ecf20Sopenharmony_ciint __bitmap_equal(const unsigned long *bitmap1, 198c2ecf20Sopenharmony_ci const unsigned long *bitmap2, unsigned int bits); 208c2ecf20Sopenharmony_civoid bitmap_clear(unsigned long *map, unsigned int start, int len); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define BITMAP_LAST_WORD_MASK(nbits) \ 258c2ecf20Sopenharmony_ci( \ 268c2ecf20Sopenharmony_ci ((nbits) % BITS_PER_LONG) ? \ 278c2ecf20Sopenharmony_ci (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ 288c2ecf20Sopenharmony_ci) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define small_const_nbits(nbits) \ 318c2ecf20Sopenharmony_ci (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic inline void bitmap_zero(unsigned long *dst, int nbits) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 368c2ecf20Sopenharmony_ci *dst = 0UL; 378c2ecf20Sopenharmony_ci else { 388c2ecf20Sopenharmony_ci int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); 398c2ecf20Sopenharmony_ci memset(dst, 0, len); 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic inline void bitmap_fill(unsigned long *dst, unsigned int nbits) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci unsigned int nlongs = BITS_TO_LONGS(nbits); 468c2ecf20Sopenharmony_ci if (!small_const_nbits(nbits)) { 478c2ecf20Sopenharmony_ci unsigned int len = (nlongs - 1) * sizeof(unsigned long); 488c2ecf20Sopenharmony_ci memset(dst, 0xff, len); 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits); 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic inline int bitmap_empty(const unsigned long *src, unsigned nbits) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 568c2ecf20Sopenharmony_ci return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return find_first_bit(src, nbits) == nbits; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic inline int bitmap_full(const unsigned long *src, unsigned int nbits) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 648c2ecf20Sopenharmony_ci return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return find_first_zero_bit(src, nbits) == nbits; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic inline int bitmap_weight(const unsigned long *src, int nbits) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 728c2ecf20Sopenharmony_ci return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)); 738c2ecf20Sopenharmony_ci return __bitmap_weight(src, nbits); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic inline void bitmap_or(unsigned long *dst, const unsigned long *src1, 778c2ecf20Sopenharmony_ci const unsigned long *src2, int nbits) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 808c2ecf20Sopenharmony_ci *dst = *src1 | *src2; 818c2ecf20Sopenharmony_ci else 828c2ecf20Sopenharmony_ci __bitmap_or(dst, src1, src2, nbits); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/** 868c2ecf20Sopenharmony_ci * test_and_set_bit - Set a bit and return its old value 878c2ecf20Sopenharmony_ci * @nr: Bit to set 888c2ecf20Sopenharmony_ci * @addr: Address to count from 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_cistatic inline int test_and_set_bit(int nr, unsigned long *addr) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(nr); 938c2ecf20Sopenharmony_ci unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); 948c2ecf20Sopenharmony_ci unsigned long old; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci old = *p; 978c2ecf20Sopenharmony_ci *p = old | mask; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci return (old & mask) != 0; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/** 1038c2ecf20Sopenharmony_ci * test_and_clear_bit - Clear a bit and return its old value 1048c2ecf20Sopenharmony_ci * @nr: Bit to clear 1058c2ecf20Sopenharmony_ci * @addr: Address to count from 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_cistatic inline int test_and_clear_bit(int nr, unsigned long *addr) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(nr); 1108c2ecf20Sopenharmony_ci unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); 1118c2ecf20Sopenharmony_ci unsigned long old; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci old = *p; 1148c2ecf20Sopenharmony_ci *p = old & ~mask; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return (old & mask) != 0; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/** 1208c2ecf20Sopenharmony_ci * bitmap_alloc - Allocate bitmap 1218c2ecf20Sopenharmony_ci * @nbits: Number of bits 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cistatic inline unsigned long *bitmap_alloc(int nbits) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long)); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* 1298c2ecf20Sopenharmony_ci * bitmap_free - Free bitmap 1308c2ecf20Sopenharmony_ci * @bitmap: pointer to bitmap 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic inline void bitmap_free(unsigned long *bitmap) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci free(bitmap); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* 1388c2ecf20Sopenharmony_ci * bitmap_scnprintf - print bitmap list into buffer 1398c2ecf20Sopenharmony_ci * @bitmap: bitmap 1408c2ecf20Sopenharmony_ci * @nbits: size of bitmap 1418c2ecf20Sopenharmony_ci * @buf: buffer to store output 1428c2ecf20Sopenharmony_ci * @size: size of @buf 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_cisize_t bitmap_scnprintf(unsigned long *bitmap, int nbits, 1458c2ecf20Sopenharmony_ci char *buf, size_t size); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/** 1488c2ecf20Sopenharmony_ci * bitmap_and - Do logical and on bitmaps 1498c2ecf20Sopenharmony_ci * @dst: resulting bitmap 1508c2ecf20Sopenharmony_ci * @src1: operand 1 1518c2ecf20Sopenharmony_ci * @src2: operand 2 1528c2ecf20Sopenharmony_ci * @nbits: size of bitmap 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_cistatic inline int bitmap_and(unsigned long *dst, const unsigned long *src1, 1558c2ecf20Sopenharmony_ci const unsigned long *src2, unsigned int nbits) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 1588c2ecf20Sopenharmony_ci return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0; 1598c2ecf20Sopenharmony_ci return __bitmap_and(dst, src1, src2, nbits); 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#ifdef __LITTLE_ENDIAN 1638c2ecf20Sopenharmony_ci#define BITMAP_MEM_ALIGNMENT 8 1648c2ecf20Sopenharmony_ci#else 1658c2ecf20Sopenharmony_ci#define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long)) 1668c2ecf20Sopenharmony_ci#endif 1678c2ecf20Sopenharmony_ci#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1) 1688c2ecf20Sopenharmony_ci#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic inline int bitmap_equal(const unsigned long *src1, 1718c2ecf20Sopenharmony_ci const unsigned long *src2, unsigned int nbits) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci if (small_const_nbits(nbits)) 1748c2ecf20Sopenharmony_ci return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); 1758c2ecf20Sopenharmony_ci if (__builtin_constant_p(nbits & BITMAP_MEM_MASK) && 1768c2ecf20Sopenharmony_ci IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT)) 1778c2ecf20Sopenharmony_ci return !memcmp(src1, src2, nbits / 8); 1788c2ecf20Sopenharmony_ci return __bitmap_equal(src1, src2, nbits); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci#endif /* _PERF_BITOPS_H */ 182