xref: /linux-6.15/tools/include/linux/bitmap.h (revision 82114e45)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
24ade0818SYury Norov #ifndef _TOOLS_LINUX_BITMAP_H
34ade0818SYury Norov #define _TOOLS_LINUX_BITMAP_H
4915b0882SArnaldo Carvalho de Melo 
5915b0882SArnaldo Carvalho de Melo #include <string.h>
610a04ff0SAlexander Lobakin #include <linux/align.h>
7915b0882SArnaldo Carvalho de Melo #include <linux/bitops.h>
84ade0818SYury Norov #include <linux/find.h>
998c03296SJiri Olsa #include <stdlib.h>
10c68a2aabSMatthew Wilcox #include <linux/kernel.h>
11915b0882SArnaldo Carvalho de Melo 
12915b0882SArnaldo Carvalho de Melo #define DECLARE_BITMAP(name,bits) \
13915b0882SArnaldo Carvalho de Melo 	unsigned long name[BITS_TO_LONGS(bits)]
14915b0882SArnaldo Carvalho de Melo 
154e23eeebSLinus Torvalds unsigned int __bitmap_weight(const unsigned long *bitmap, int bits);
16915b0882SArnaldo Carvalho de Melo void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
17915b0882SArnaldo Carvalho de Melo 		 const unsigned long *bitmap2, int bits);
18e2863a78SYury Norov bool __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
19741c74f5SJiri Olsa 		 const unsigned long *bitmap2, unsigned int bits);
20005f1700SKees Cook bool __bitmap_equal(const unsigned long *bitmap1,
218812ad41SAlexey Budankov 		    const unsigned long *bitmap2, unsigned int bits);
22*82114e45SWei Yang void __bitmap_set(unsigned long *map, unsigned int start, int len);
23692a68eeSWei Yang void __bitmap_clear(unsigned long *map, unsigned int start, int len);
24005f1700SKees Cook bool __bitmap_intersects(const unsigned long *bitmap1,
25f20510d5SAlexey Bayduraev 			 const unsigned long *bitmap2, unsigned int bits);
26915b0882SArnaldo Carvalho de Melo 
27915b0882SArnaldo Carvalho de Melo #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
28a719101fSYury Norov #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
29915b0882SArnaldo Carvalho de Melo 
30a37fbe66SAlexander Lobakin #define bitmap_size(nbits)	(ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE)
31a37fbe66SAlexander Lobakin 
bitmap_zero(unsigned long * dst,unsigned int nbits)32e5b9252dSYury Norov static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
33915b0882SArnaldo Carvalho de Melo {
34915b0882SArnaldo Carvalho de Melo 	if (small_const_nbits(nbits))
35915b0882SArnaldo Carvalho de Melo 		*dst = 0UL;
36915b0882SArnaldo Carvalho de Melo 	else {
37a37fbe66SAlexander Lobakin 		memset(dst, 0, bitmap_size(nbits));
38915b0882SArnaldo Carvalho de Melo 	}
39915b0882SArnaldo Carvalho de Melo }
40915b0882SArnaldo Carvalho de Melo 
bitmap_fill(unsigned long * dst,unsigned int nbits)41b328daf3SMatthew Wilcox static inline void bitmap_fill(unsigned long *dst, unsigned int nbits)
42b328daf3SMatthew Wilcox {
43b328daf3SMatthew Wilcox 	unsigned int nlongs = BITS_TO_LONGS(nbits);
44b328daf3SMatthew Wilcox 	if (!small_const_nbits(nbits)) {
45b328daf3SMatthew Wilcox 		unsigned int len = (nlongs - 1) * sizeof(unsigned long);
46b328daf3SMatthew Wilcox 		memset(dst, 0xff,  len);
47b328daf3SMatthew Wilcox 	}
48b328daf3SMatthew Wilcox 	dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
49b328daf3SMatthew Wilcox }
50b328daf3SMatthew Wilcox 
bitmap_empty(const unsigned long * src,unsigned int nbits)51e2863a78SYury Norov static inline bool bitmap_empty(const unsigned long *src, unsigned int nbits)
52b328daf3SMatthew Wilcox {
53b328daf3SMatthew Wilcox 	if (small_const_nbits(nbits))
54b328daf3SMatthew Wilcox 		return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
55b328daf3SMatthew Wilcox 
56b328daf3SMatthew Wilcox 	return find_first_bit(src, nbits) == nbits;
57b328daf3SMatthew Wilcox }
58b328daf3SMatthew Wilcox 
bitmap_full(const unsigned long * src,unsigned int nbits)59e2863a78SYury Norov static inline bool bitmap_full(const unsigned long *src, unsigned int nbits)
60b328daf3SMatthew Wilcox {
61b328daf3SMatthew Wilcox 	if (small_const_nbits(nbits))
62b328daf3SMatthew Wilcox 		return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
63b328daf3SMatthew Wilcox 
64b328daf3SMatthew Wilcox 	return find_first_zero_bit(src, nbits) == nbits;
65b328daf3SMatthew Wilcox }
66b328daf3SMatthew Wilcox 
bitmap_weight(const unsigned long * src,unsigned int nbits)674e23eeebSLinus Torvalds static inline unsigned int bitmap_weight(const unsigned long *src, unsigned int nbits)
68915b0882SArnaldo Carvalho de Melo {
69915b0882SArnaldo Carvalho de Melo 	if (small_const_nbits(nbits))
70915b0882SArnaldo Carvalho de Melo 		return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
71915b0882SArnaldo Carvalho de Melo 	return __bitmap_weight(src, nbits);
72915b0882SArnaldo Carvalho de Melo }
73915b0882SArnaldo Carvalho de Melo 
bitmap_or(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,unsigned int nbits)74915b0882SArnaldo Carvalho de Melo static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
75e5b9252dSYury Norov 			     const unsigned long *src2, unsigned int nbits)
76915b0882SArnaldo Carvalho de Melo {
77915b0882SArnaldo Carvalho de Melo 	if (small_const_nbits(nbits))
78915b0882SArnaldo Carvalho de Melo 		*dst = *src1 | *src2;
79915b0882SArnaldo Carvalho de Melo 	else
80915b0882SArnaldo Carvalho de Melo 		__bitmap_or(dst, src1, src2, nbits);
81915b0882SArnaldo Carvalho de Melo }
82915b0882SArnaldo Carvalho de Melo 
bitmap_alloc(unsigned int nbits,gfp_t flags __maybe_unused)83*82114e45SWei Yang static inline unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags __maybe_unused)
84*82114e45SWei Yang {
85*82114e45SWei Yang 	return malloc(bitmap_size(nbits));
86*82114e45SWei Yang }
87*82114e45SWei Yang 
88915b0882SArnaldo Carvalho de Melo /**
897fc5b571SAndy Shevchenko  * bitmap_zalloc - Allocate bitmap
90e2091cedSJiri Olsa  * @nbits: Number of bits
9198c03296SJiri Olsa  */
bitmap_zalloc(int nbits)927fc5b571SAndy Shevchenko static inline unsigned long *bitmap_zalloc(int nbits)
9398c03296SJiri Olsa {
94a37fbe66SAlexander Lobakin 	return calloc(1, bitmap_size(nbits));
9598c03296SJiri Olsa }
9698c03296SJiri Olsa 
97820d12b7SJiri Olsa /*
988812ad41SAlexey Budankov  * bitmap_free - Free bitmap
998812ad41SAlexey Budankov  * @bitmap: pointer to bitmap
1008812ad41SAlexey Budankov  */
bitmap_free(unsigned long * bitmap)1018812ad41SAlexey Budankov static inline void bitmap_free(unsigned long *bitmap)
1028812ad41SAlexey Budankov {
1038812ad41SAlexey Budankov 	free(bitmap);
1048812ad41SAlexey Budankov }
1058812ad41SAlexey Budankov 
1068812ad41SAlexey Budankov /*
107820d12b7SJiri Olsa  * bitmap_scnprintf - print bitmap list into buffer
108820d12b7SJiri Olsa  * @bitmap: bitmap
109820d12b7SJiri Olsa  * @nbits: size of bitmap
110820d12b7SJiri Olsa  * @buf: buffer to store output
111820d12b7SJiri Olsa  * @size: size of @buf
112820d12b7SJiri Olsa  */
113e5b9252dSYury Norov size_t bitmap_scnprintf(unsigned long *bitmap, unsigned int nbits,
114820d12b7SJiri Olsa 			char *buf, size_t size);
115820d12b7SJiri Olsa 
116741c74f5SJiri Olsa /**
117741c74f5SJiri Olsa  * bitmap_and - Do logical and on bitmaps
118741c74f5SJiri Olsa  * @dst: resulting bitmap
119741c74f5SJiri Olsa  * @src1: operand 1
120741c74f5SJiri Olsa  * @src2: operand 2
121741c74f5SJiri Olsa  * @nbits: size of bitmap
122741c74f5SJiri Olsa  */
bitmap_and(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,unsigned int nbits)123e2863a78SYury Norov static inline bool bitmap_and(unsigned long *dst, const unsigned long *src1,
124741c74f5SJiri Olsa 			     const unsigned long *src2, unsigned int nbits)
125741c74f5SJiri Olsa {
126741c74f5SJiri Olsa 	if (small_const_nbits(nbits))
127741c74f5SJiri Olsa 		return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0;
128741c74f5SJiri Olsa 	return __bitmap_and(dst, src1, src2, nbits);
129741c74f5SJiri Olsa }
130741c74f5SJiri Olsa 
1318812ad41SAlexey Budankov #ifdef __LITTLE_ENDIAN
1328812ad41SAlexey Budankov #define BITMAP_MEM_ALIGNMENT 8
1338812ad41SAlexey Budankov #else
1348812ad41SAlexey Budankov #define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long))
1358812ad41SAlexey Budankov #endif
1368812ad41SAlexey Budankov #define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
1378812ad41SAlexey Budankov 
bitmap_equal(const unsigned long * src1,const unsigned long * src2,unsigned int nbits)138005f1700SKees Cook static inline bool bitmap_equal(const unsigned long *src1,
1398812ad41SAlexey Budankov 				const unsigned long *src2, unsigned int nbits)
1408812ad41SAlexey Budankov {
1418812ad41SAlexey Budankov 	if (small_const_nbits(nbits))
1428812ad41SAlexey Budankov 		return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
1438812ad41SAlexey Budankov 	if (__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
1448812ad41SAlexey Budankov 	    IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
1458812ad41SAlexey Budankov 		return !memcmp(src1, src2, nbits / 8);
1468812ad41SAlexey Budankov 	return __bitmap_equal(src1, src2, nbits);
1478812ad41SAlexey Budankov }
1488812ad41SAlexey Budankov 
bitmap_intersects(const unsigned long * src1,const unsigned long * src2,unsigned int nbits)149005f1700SKees Cook static inline bool bitmap_intersects(const unsigned long *src1,
150005f1700SKees Cook 				     const unsigned long *src2,
151005f1700SKees Cook 				     unsigned int nbits)
152f20510d5SAlexey Bayduraev {
153f20510d5SAlexey Bayduraev 	if (small_const_nbits(nbits))
154f20510d5SAlexey Bayduraev 		return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
155f20510d5SAlexey Bayduraev 	else
156f20510d5SAlexey Bayduraev 		return __bitmap_intersects(src1, src2, nbits);
157f20510d5SAlexey Bayduraev }
158f20510d5SAlexey Bayduraev 
bitmap_set(unsigned long * map,unsigned int start,unsigned int nbits)159*82114e45SWei Yang static inline void bitmap_set(unsigned long *map, unsigned int start, unsigned int nbits)
160*82114e45SWei Yang {
161*82114e45SWei Yang 	if (__builtin_constant_p(nbits) && nbits == 1)
162*82114e45SWei Yang 		__set_bit(start, map);
163*82114e45SWei Yang 	else if (small_const_nbits(start + nbits))
164*82114e45SWei Yang 		*map |= GENMASK(start + nbits - 1, start);
165*82114e45SWei Yang 	else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
166*82114e45SWei Yang 		 IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
167*82114e45SWei Yang 		 __builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
168*82114e45SWei Yang 		 IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
169*82114e45SWei Yang 		memset((char *)map + start / 8, 0xff, nbits / 8);
170*82114e45SWei Yang 	else
171*82114e45SWei Yang 		__bitmap_set(map, start, nbits);
172*82114e45SWei Yang }
173*82114e45SWei Yang 
bitmap_clear(unsigned long * map,unsigned int start,unsigned int nbits)174692a68eeSWei Yang static inline void bitmap_clear(unsigned long *map, unsigned int start,
175692a68eeSWei Yang 			       unsigned int nbits)
176692a68eeSWei Yang {
177692a68eeSWei Yang 	if (__builtin_constant_p(nbits) && nbits == 1)
178692a68eeSWei Yang 		__clear_bit(start, map);
179692a68eeSWei Yang 	else if (small_const_nbits(start + nbits))
180692a68eeSWei Yang 		*map &= ~GENMASK(start + nbits - 1, start);
181692a68eeSWei Yang 	else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
182692a68eeSWei Yang 		 IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
183692a68eeSWei Yang 		 __builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
184692a68eeSWei Yang 		 IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
185692a68eeSWei Yang 		memset((char *)map + start / 8, 0, nbits / 8);
186692a68eeSWei Yang 	else
187692a68eeSWei Yang 		__bitmap_clear(map, start, nbits);
188692a68eeSWei Yang }
1894ade0818SYury Norov #endif /* _TOOLS_LINUX_BITMAP_H */
190