1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _TOOLS_LINUX_BITMAP_H
3 #define _TOOLS_LINUX_BITMAP_H
6 #include <linux/align.h>
7 #include <linux/bitops.h>
8 #include <linux/find.h>
10 #include <linux/kernel.h>
12 #define DECLARE_BITMAP(name,bits) \
13 unsigned long name[BITS_TO_LONGS(bits)]
15 unsigned int __bitmap_weight(const unsigned long *bitmap
, int bits
);
16 void __bitmap_or(unsigned long *dst
, const unsigned long *bitmap1
,
17 const unsigned long *bitmap2
, int bits
);
18 bool __bitmap_and(unsigned long *dst
, const unsigned long *bitmap1
,
19 const unsigned long *bitmap2
, unsigned int bits
);
20 bool __bitmap_equal(const unsigned long *bitmap1
,
21 const unsigned long *bitmap2
, unsigned int bits
);
22 void __bitmap_clear(unsigned long *map
, unsigned int start
, int len
);
23 bool __bitmap_intersects(const unsigned long *bitmap1
,
24 const unsigned long *bitmap2
, unsigned int bits
);
26 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
27 #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
29 #define bitmap_size(nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE)
31 static inline void bitmap_zero(unsigned long *dst
, unsigned int nbits
)
33 if (small_const_nbits(nbits
))
36 memset(dst
, 0, bitmap_size(nbits
));
40 static inline void bitmap_fill(unsigned long *dst
, unsigned int nbits
)
42 unsigned int nlongs
= BITS_TO_LONGS(nbits
);
43 if (!small_const_nbits(nbits
)) {
44 unsigned int len
= (nlongs
- 1) * sizeof(unsigned long);
45 memset(dst
, 0xff, len
);
47 dst
[nlongs
- 1] = BITMAP_LAST_WORD_MASK(nbits
);
50 static inline bool bitmap_empty(const unsigned long *src
, unsigned int nbits
)
52 if (small_const_nbits(nbits
))
53 return ! (*src
& BITMAP_LAST_WORD_MASK(nbits
));
55 return find_first_bit(src
, nbits
) == nbits
;
58 static inline bool bitmap_full(const unsigned long *src
, unsigned int nbits
)
60 if (small_const_nbits(nbits
))
61 return ! (~(*src
) & BITMAP_LAST_WORD_MASK(nbits
));
63 return find_first_zero_bit(src
, nbits
) == nbits
;
66 static inline unsigned int bitmap_weight(const unsigned long *src
, unsigned int nbits
)
68 if (small_const_nbits(nbits
))
69 return hweight_long(*src
& BITMAP_LAST_WORD_MASK(nbits
));
70 return __bitmap_weight(src
, nbits
);
73 static inline void bitmap_or(unsigned long *dst
, const unsigned long *src1
,
74 const unsigned long *src2
, unsigned int nbits
)
76 if (small_const_nbits(nbits
))
79 __bitmap_or(dst
, src1
, src2
, nbits
);
83 * bitmap_zalloc - Allocate bitmap
84 * @nbits: Number of bits
86 static inline unsigned long *bitmap_zalloc(int nbits
)
88 return calloc(1, bitmap_size(nbits
));
92 * bitmap_free - Free bitmap
93 * @bitmap: pointer to bitmap
95 static inline void bitmap_free(unsigned long *bitmap
)
101 * bitmap_scnprintf - print bitmap list into buffer
103 * @nbits: size of bitmap
104 * @buf: buffer to store output
105 * @size: size of @buf
107 size_t bitmap_scnprintf(unsigned long *bitmap
, unsigned int nbits
,
108 char *buf
, size_t size
);
111 * bitmap_and - Do logical and on bitmaps
112 * @dst: resulting bitmap
115 * @nbits: size of bitmap
117 static inline bool bitmap_and(unsigned long *dst
, const unsigned long *src1
,
118 const unsigned long *src2
, unsigned int nbits
)
120 if (small_const_nbits(nbits
))
121 return (*dst
= *src1
& *src2
& BITMAP_LAST_WORD_MASK(nbits
)) != 0;
122 return __bitmap_and(dst
, src1
, src2
, nbits
);
125 #ifdef __LITTLE_ENDIAN
126 #define BITMAP_MEM_ALIGNMENT 8
128 #define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long))
130 #define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
132 static inline bool bitmap_equal(const unsigned long *src1
,
133 const unsigned long *src2
, unsigned int nbits
)
135 if (small_const_nbits(nbits
))
136 return !((*src1
^ *src2
) & BITMAP_LAST_WORD_MASK(nbits
));
137 if (__builtin_constant_p(nbits
& BITMAP_MEM_MASK
) &&
138 IS_ALIGNED(nbits
, BITMAP_MEM_ALIGNMENT
))
139 return !memcmp(src1
, src2
, nbits
/ 8);
140 return __bitmap_equal(src1
, src2
, nbits
);
143 static inline bool bitmap_intersects(const unsigned long *src1
,
144 const unsigned long *src2
,
147 if (small_const_nbits(nbits
))
148 return ((*src1
& *src2
) & BITMAP_LAST_WORD_MASK(nbits
)) != 0;
150 return __bitmap_intersects(src1
, src2
, nbits
);
153 static inline void bitmap_clear(unsigned long *map
, unsigned int start
,
156 if (__builtin_constant_p(nbits
) && nbits
== 1)
157 __clear_bit(start
, map
);
158 else if (small_const_nbits(start
+ nbits
))
159 *map
&= ~GENMASK(start
+ nbits
- 1, start
);
160 else if (__builtin_constant_p(start
& BITMAP_MEM_MASK
) &&
161 IS_ALIGNED(start
, BITMAP_MEM_ALIGNMENT
) &&
162 __builtin_constant_p(nbits
& BITMAP_MEM_MASK
) &&
163 IS_ALIGNED(nbits
, BITMAP_MEM_ALIGNMENT
))
164 memset((char *)map
+ start
/ 8, 0, nbits
/ 8);
166 __bitmap_clear(map
, start
, nbits
);
168 #endif /* _TOOLS_LINUX_BITMAP_H */