xref: /freebsd/sys/contrib/ck/include/ck_bitmap.h (revision 4f9d94bf6491250b649f5bc931b6d93e68373005)
1*1fb62fb0SOlivier Houchard /*
2*1fb62fb0SOlivier Houchard  * Copyright 2012-2015 Samy Al Bahra.
3*1fb62fb0SOlivier Houchard  * Copyright 2012-2014 AppNexus, Inc.
4*1fb62fb0SOlivier Houchard  * Copyright 2014 Paul Khuong.
5*1fb62fb0SOlivier Houchard  * All rights reserved.
6*1fb62fb0SOlivier Houchard  *
7*1fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
8*1fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
9*1fb62fb0SOlivier Houchard  * are met:
10*1fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
11*1fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
12*1fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
13*1fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
14*1fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
15*1fb62fb0SOlivier Houchard  *
16*1fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*1fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*1fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*1fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*1fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*1fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*1fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*1fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*1fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*1fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*1fb62fb0SOlivier Houchard  * SUCH DAMAGE.
27*1fb62fb0SOlivier Houchard  */
28*1fb62fb0SOlivier Houchard 
29*1fb62fb0SOlivier Houchard #ifndef CK_BITMAP_H
30*1fb62fb0SOlivier Houchard #define CK_BITMAP_H
31*1fb62fb0SOlivier Houchard 
32*1fb62fb0SOlivier Houchard #include <ck_cc.h>
33*1fb62fb0SOlivier Houchard #include <ck_limits.h>
34*1fb62fb0SOlivier Houchard #include <ck_pr.h>
35*1fb62fb0SOlivier Houchard #include <ck_stdint.h>
36*1fb62fb0SOlivier Houchard #include <ck_stdbool.h>
37*1fb62fb0SOlivier Houchard #include <ck_stddef.h>
38*1fb62fb0SOlivier Houchard #include <ck_stdbool.h>
39*1fb62fb0SOlivier Houchard #include <ck_stddef.h>
40*1fb62fb0SOlivier Houchard #include <ck_string.h>
41*1fb62fb0SOlivier Houchard 
42*1fb62fb0SOlivier Houchard #if !defined(CK_F_PR_LOAD_UINT) || !defined(CK_F_PR_STORE_UINT) || \
43*1fb62fb0SOlivier Houchard     !defined(CK_F_PR_AND_UINT) || !defined(CK_F_PR_OR_UINT) || \
44*1fb62fb0SOlivier Houchard     !defined(CK_F_CC_CTZ)
45*1fb62fb0SOlivier Houchard #error "ck_bitmap is not supported on your platform."
46*1fb62fb0SOlivier Houchard #endif
47*1fb62fb0SOlivier Houchard 
48*1fb62fb0SOlivier Houchard #define CK_BITMAP_BLOCK 	(sizeof(unsigned int) * CHAR_BIT)
49*1fb62fb0SOlivier Houchard #define CK_BITMAP_OFFSET(i)	((i) % CK_BITMAP_BLOCK)
50*1fb62fb0SOlivier Houchard #define CK_BITMAP_BIT(i)	(1U << CK_BITMAP_OFFSET(i))
51*1fb62fb0SOlivier Houchard #define CK_BITMAP_PTR(x, i)	((x) + ((i) / CK_BITMAP_BLOCK))
52*1fb62fb0SOlivier Houchard #define CK_BITMAP_BLOCKS(n)	(((n) + CK_BITMAP_BLOCK - 1) / CK_BITMAP_BLOCK)
53*1fb62fb0SOlivier Houchard 
54*1fb62fb0SOlivier Houchard #define CK_BITMAP_INSTANCE(n_entries)					\
55*1fb62fb0SOlivier Houchard 	union {								\
56*1fb62fb0SOlivier Houchard 		struct {						\
57*1fb62fb0SOlivier Houchard 			unsigned int n_bits;				\
58*1fb62fb0SOlivier Houchard 			unsigned int map[CK_BITMAP_BLOCKS(n_entries)];	\
59*1fb62fb0SOlivier Houchard 		} content;						\
60*1fb62fb0SOlivier Houchard 		struct ck_bitmap bitmap;				\
61*1fb62fb0SOlivier Houchard 	}
62*1fb62fb0SOlivier Houchard 
63*1fb62fb0SOlivier Houchard #define CK_BITMAP_ITERATOR_INIT(a, b) \
64*1fb62fb0SOlivier Houchard 	ck_bitmap_iterator_init((a), &(b)->bitmap)
65*1fb62fb0SOlivier Houchard 
66*1fb62fb0SOlivier Houchard #define CK_BITMAP_INIT(a, b, c) \
67*1fb62fb0SOlivier Houchard 	ck_bitmap_init(&(a)->bitmap, (b), (c))
68*1fb62fb0SOlivier Houchard 
69*1fb62fb0SOlivier Houchard #define CK_BITMAP_NEXT(a, b, c) \
70*1fb62fb0SOlivier Houchard 	ck_bitmap_next(&(a)->bitmap, (b), (c))
71*1fb62fb0SOlivier Houchard 
72*1fb62fb0SOlivier Houchard #define CK_BITMAP_SET(a, b) \
73*1fb62fb0SOlivier Houchard 	ck_bitmap_set(&(a)->bitmap, (b))
74*1fb62fb0SOlivier Houchard 
75*1fb62fb0SOlivier Houchard #define CK_BITMAP_BTS(a, b) \
76*1fb62fb0SOlivier Houchard 	ck_bitmap_bts(&(a)->bitmap, (b))
77*1fb62fb0SOlivier Houchard 
78*1fb62fb0SOlivier Houchard #define CK_BITMAP_RESET(a, b) \
79*1fb62fb0SOlivier Houchard 	ck_bitmap_reset(&(a)->bitmap, (b))
80*1fb62fb0SOlivier Houchard 
81*1fb62fb0SOlivier Houchard #define CK_BITMAP_TEST(a, b) \
82*1fb62fb0SOlivier Houchard 	ck_bitmap_test(&(a)->bitmap, (b))
83*1fb62fb0SOlivier Houchard 
84*1fb62fb0SOlivier Houchard #define CK_BITMAP_UNION(a, b) \
85*1fb62fb0SOlivier Houchard 	ck_bitmap_union(&(a)->bitmap, &(b)->bitmap)
86*1fb62fb0SOlivier Houchard 
87*1fb62fb0SOlivier Houchard #define CK_BITMAP_INTERSECTION(a, b) \
88*1fb62fb0SOlivier Houchard 	ck_bitmap_intersection(&(a)->bitmap, &(b)->bitmap)
89*1fb62fb0SOlivier Houchard 
90*1fb62fb0SOlivier Houchard #define CK_BITMAP_INTERSECTION_NEGATE(a, b) \
91*1fb62fb0SOlivier Houchard 	ck_bitmap_intersection_negate(&(a)->bitmap, &(b)->bitmap)
92*1fb62fb0SOlivier Houchard 
93*1fb62fb0SOlivier Houchard #define CK_BITMAP_CLEAR(a) \
94*1fb62fb0SOlivier Houchard 	ck_bitmap_clear(&(a)->bitmap)
95*1fb62fb0SOlivier Houchard 
96*1fb62fb0SOlivier Houchard #define CK_BITMAP_EMPTY(a, b) \
97*1fb62fb0SOlivier Houchard 	ck_bitmap_empty(&(a)->bitmap, b)
98*1fb62fb0SOlivier Houchard 
99*1fb62fb0SOlivier Houchard #define CK_BITMAP_FULL(a, b) \
100*1fb62fb0SOlivier Houchard 	ck_bitmap_full(&(a)->bitmap, b)
101*1fb62fb0SOlivier Houchard 
102*1fb62fb0SOlivier Houchard #define CK_BITMAP_COUNT(a, b) \
103*1fb62fb0SOlivier Houchard 	ck_bitmap_count(&(a)->bitmap, b)
104*1fb62fb0SOlivier Houchard 
105*1fb62fb0SOlivier Houchard #define CK_BITMAP_COUNT_INTERSECT(a, b, c) \
106*1fb62fb0SOlivier Houchard 	ck_bitmap_count_intersect(&(a)->bitmap, b, c)
107*1fb62fb0SOlivier Houchard 
108*1fb62fb0SOlivier Houchard #define CK_BITMAP_BITS(a) \
109*1fb62fb0SOlivier Houchard 	ck_bitmap_bits(&(a)->bitmap)
110*1fb62fb0SOlivier Houchard 
111*1fb62fb0SOlivier Houchard #define CK_BITMAP_BUFFER(a) \
112*1fb62fb0SOlivier Houchard 	ck_bitmap_buffer(&(a)->bitmap)
113*1fb62fb0SOlivier Houchard 
114*1fb62fb0SOlivier Houchard #define CK_BITMAP(a) \
115*1fb62fb0SOlivier Houchard 	(&(a)->bitmap)
116*1fb62fb0SOlivier Houchard 
117*1fb62fb0SOlivier Houchard struct ck_bitmap {
118*1fb62fb0SOlivier Houchard 	unsigned int n_bits;
119*1fb62fb0SOlivier Houchard 	unsigned int map[];
120*1fb62fb0SOlivier Houchard };
121*1fb62fb0SOlivier Houchard typedef struct ck_bitmap ck_bitmap_t;
122*1fb62fb0SOlivier Houchard 
123*1fb62fb0SOlivier Houchard struct ck_bitmap_iterator {
124*1fb62fb0SOlivier Houchard 	unsigned int cache;
125*1fb62fb0SOlivier Houchard 	unsigned int n_block;
126*1fb62fb0SOlivier Houchard 	unsigned int n_limit;
127*1fb62fb0SOlivier Houchard };
128*1fb62fb0SOlivier Houchard typedef struct ck_bitmap_iterator ck_bitmap_iterator_t;
129*1fb62fb0SOlivier Houchard 
130*1fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_bitmap_base(unsigned int n_bits)131*1fb62fb0SOlivier Houchard ck_bitmap_base(unsigned int n_bits)
132*1fb62fb0SOlivier Houchard {
133*1fb62fb0SOlivier Houchard 
134*1fb62fb0SOlivier Houchard 	return CK_BITMAP_BLOCKS(n_bits) * sizeof(unsigned int);
135*1fb62fb0SOlivier Houchard }
136*1fb62fb0SOlivier Houchard 
137*1fb62fb0SOlivier Houchard /*
138*1fb62fb0SOlivier Houchard  * Returns the required number of bytes for a ck_bitmap_t object supporting the
139*1fb62fb0SOlivier Houchard  * specified number of bits.
140*1fb62fb0SOlivier Houchard  */
141*1fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_bitmap_size(unsigned int n_bits)142*1fb62fb0SOlivier Houchard ck_bitmap_size(unsigned int n_bits)
143*1fb62fb0SOlivier Houchard {
144*1fb62fb0SOlivier Houchard 
145*1fb62fb0SOlivier Houchard 	return ck_bitmap_base(n_bits) + sizeof(struct ck_bitmap);
146*1fb62fb0SOlivier Houchard }
147*1fb62fb0SOlivier Houchard 
148*1fb62fb0SOlivier Houchard /*
149*1fb62fb0SOlivier Houchard  * Returns total number of bits in specified bitmap.
150*1fb62fb0SOlivier Houchard  */
151*1fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_bitmap_bits(const struct ck_bitmap * bitmap)152*1fb62fb0SOlivier Houchard ck_bitmap_bits(const struct ck_bitmap *bitmap)
153*1fb62fb0SOlivier Houchard {
154*1fb62fb0SOlivier Houchard 
155*1fb62fb0SOlivier Houchard 	return bitmap->n_bits;
156*1fb62fb0SOlivier Houchard }
157*1fb62fb0SOlivier Houchard 
158*1fb62fb0SOlivier Houchard /*
159*1fb62fb0SOlivier Houchard  * Returns a pointer to the bit buffer associated
160*1fb62fb0SOlivier Houchard  * with the specified bitmap.
161*1fb62fb0SOlivier Houchard  */
162*1fb62fb0SOlivier Houchard CK_CC_INLINE static void *
ck_bitmap_buffer(struct ck_bitmap * bitmap)163*1fb62fb0SOlivier Houchard ck_bitmap_buffer(struct ck_bitmap *bitmap)
164*1fb62fb0SOlivier Houchard {
165*1fb62fb0SOlivier Houchard 
166*1fb62fb0SOlivier Houchard 	return bitmap->map;
167*1fb62fb0SOlivier Houchard }
168*1fb62fb0SOlivier Houchard 
169*1fb62fb0SOlivier Houchard /*
170*1fb62fb0SOlivier Houchard  * Sets the bit at the offset specified in the second argument.
171*1fb62fb0SOlivier Houchard  */
172*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_set(struct ck_bitmap * bitmap,unsigned int n)173*1fb62fb0SOlivier Houchard ck_bitmap_set(struct ck_bitmap *bitmap, unsigned int n)
174*1fb62fb0SOlivier Houchard {
175*1fb62fb0SOlivier Houchard 
176*1fb62fb0SOlivier Houchard 	ck_pr_or_uint(CK_BITMAP_PTR(bitmap->map, n), CK_BITMAP_BIT(n));
177*1fb62fb0SOlivier Houchard 	return;
178*1fb62fb0SOlivier Houchard }
179*1fb62fb0SOlivier Houchard 
180*1fb62fb0SOlivier Houchard /*
181*1fb62fb0SOlivier Houchard  * Performs a test-and-set operation at the offset specified in the
182*1fb62fb0SOlivier Houchard  * second argument.
183*1fb62fb0SOlivier Houchard  * Returns true if the bit at the specified offset was already set,
184*1fb62fb0SOlivier Houchard  * false otherwise.
185*1fb62fb0SOlivier Houchard  */
186*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_bitmap_bts(struct ck_bitmap * bitmap,unsigned int n)187*1fb62fb0SOlivier Houchard ck_bitmap_bts(struct ck_bitmap *bitmap, unsigned int n)
188*1fb62fb0SOlivier Houchard {
189*1fb62fb0SOlivier Houchard 
190*1fb62fb0SOlivier Houchard 	return ck_pr_bts_uint(CK_BITMAP_PTR(bitmap->map, n),
191*1fb62fb0SOlivier Houchard 	    CK_BITMAP_OFFSET(n));
192*1fb62fb0SOlivier Houchard }
193*1fb62fb0SOlivier Houchard 
194*1fb62fb0SOlivier Houchard /*
195*1fb62fb0SOlivier Houchard  * Resets the bit at the offset specified in the second argument.
196*1fb62fb0SOlivier Houchard  */
197*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_reset(struct ck_bitmap * bitmap,unsigned int n)198*1fb62fb0SOlivier Houchard ck_bitmap_reset(struct ck_bitmap *bitmap, unsigned int n)
199*1fb62fb0SOlivier Houchard {
200*1fb62fb0SOlivier Houchard 
201*1fb62fb0SOlivier Houchard 	ck_pr_and_uint(CK_BITMAP_PTR(bitmap->map, n), ~CK_BITMAP_BIT(n));
202*1fb62fb0SOlivier Houchard 	return;
203*1fb62fb0SOlivier Houchard }
204*1fb62fb0SOlivier Houchard 
205*1fb62fb0SOlivier Houchard /*
206*1fb62fb0SOlivier Houchard  * Determines whether the bit at offset specified in the
207*1fb62fb0SOlivier Houchard  * second argument is set.
208*1fb62fb0SOlivier Houchard  */
209*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_bitmap_test(const struct ck_bitmap * bitmap,unsigned int n)210*1fb62fb0SOlivier Houchard ck_bitmap_test(const struct ck_bitmap *bitmap, unsigned int n)
211*1fb62fb0SOlivier Houchard {
212*1fb62fb0SOlivier Houchard 	unsigned int block;
213*1fb62fb0SOlivier Houchard 
214*1fb62fb0SOlivier Houchard 	block = ck_pr_load_uint(CK_BITMAP_PTR(bitmap->map, n));
215*1fb62fb0SOlivier Houchard 	return block & CK_BITMAP_BIT(n);
216*1fb62fb0SOlivier Houchard }
217*1fb62fb0SOlivier Houchard 
218*1fb62fb0SOlivier Houchard /*
219*1fb62fb0SOlivier Houchard  * Combines bits from second bitmap into the first bitmap. This is not a
220*1fb62fb0SOlivier Houchard  * linearized operation with respect to the complete bitmap.
221*1fb62fb0SOlivier Houchard  */
222*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_union(struct ck_bitmap * dst,const struct ck_bitmap * src)223*1fb62fb0SOlivier Houchard ck_bitmap_union(struct ck_bitmap *dst, const struct ck_bitmap *src)
224*1fb62fb0SOlivier Houchard {
225*1fb62fb0SOlivier Houchard 	unsigned int n;
226*1fb62fb0SOlivier Houchard 	unsigned int n_buckets = dst->n_bits;
227*1fb62fb0SOlivier Houchard 
228*1fb62fb0SOlivier Houchard 	if (src->n_bits < dst->n_bits)
229*1fb62fb0SOlivier Houchard 		n_buckets = src->n_bits;
230*1fb62fb0SOlivier Houchard 
231*1fb62fb0SOlivier Houchard 	n_buckets = CK_BITMAP_BLOCKS(n_buckets);
232*1fb62fb0SOlivier Houchard 	for (n = 0; n < n_buckets; n++) {
233*1fb62fb0SOlivier Houchard 		ck_pr_or_uint(&dst->map[n],
234*1fb62fb0SOlivier Houchard 		    ck_pr_load_uint(&src->map[n]));
235*1fb62fb0SOlivier Houchard 	}
236*1fb62fb0SOlivier Houchard 
237*1fb62fb0SOlivier Houchard 	return;
238*1fb62fb0SOlivier Houchard }
239*1fb62fb0SOlivier Houchard 
240*1fb62fb0SOlivier Houchard /*
241*1fb62fb0SOlivier Houchard  * Intersects bits from second bitmap into the first bitmap. This is
242*1fb62fb0SOlivier Houchard  * not a linearized operation with respect to the complete bitmap.
243*1fb62fb0SOlivier Houchard  * Any trailing bit in dst is cleared.
244*1fb62fb0SOlivier Houchard  */
245*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_intersection(struct ck_bitmap * dst,const struct ck_bitmap * src)246*1fb62fb0SOlivier Houchard ck_bitmap_intersection(struct ck_bitmap *dst, const struct ck_bitmap *src)
247*1fb62fb0SOlivier Houchard {
248*1fb62fb0SOlivier Houchard 	unsigned int n;
249*1fb62fb0SOlivier Houchard 	unsigned int n_buckets = dst->n_bits;
250*1fb62fb0SOlivier Houchard 	unsigned int n_intersect = n_buckets;
251*1fb62fb0SOlivier Houchard 
252*1fb62fb0SOlivier Houchard 	if (src->n_bits < n_intersect)
253*1fb62fb0SOlivier Houchard 		n_intersect = src->n_bits;
254*1fb62fb0SOlivier Houchard 
255*1fb62fb0SOlivier Houchard 	n_buckets = CK_BITMAP_BLOCKS(n_buckets);
256*1fb62fb0SOlivier Houchard 	n_intersect = CK_BITMAP_BLOCKS(n_intersect);
257*1fb62fb0SOlivier Houchard 	for (n = 0; n < n_intersect; n++) {
258*1fb62fb0SOlivier Houchard 		ck_pr_and_uint(&dst->map[n],
259*1fb62fb0SOlivier Houchard 		    ck_pr_load_uint(&src->map[n]));
260*1fb62fb0SOlivier Houchard 	}
261*1fb62fb0SOlivier Houchard 
262*1fb62fb0SOlivier Houchard 	for (; n < n_buckets; n++)
263*1fb62fb0SOlivier Houchard 		ck_pr_store_uint(&dst->map[n], 0);
264*1fb62fb0SOlivier Houchard 
265*1fb62fb0SOlivier Houchard 	return;
266*1fb62fb0SOlivier Houchard }
267*1fb62fb0SOlivier Houchard 
268*1fb62fb0SOlivier Houchard /*
269*1fb62fb0SOlivier Houchard  * Intersects the complement of bits from second bitmap into the first
270*1fb62fb0SOlivier Houchard  * bitmap. This is not a linearized operation with respect to the
271*1fb62fb0SOlivier Houchard  * complete bitmap.  Any trailing bit in dst is left as is.
272*1fb62fb0SOlivier Houchard  */
273*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_intersection_negate(struct ck_bitmap * dst,const struct ck_bitmap * src)274*1fb62fb0SOlivier Houchard ck_bitmap_intersection_negate(struct ck_bitmap *dst,
275*1fb62fb0SOlivier Houchard     const struct ck_bitmap *src)
276*1fb62fb0SOlivier Houchard {
277*1fb62fb0SOlivier Houchard 	unsigned int n;
278*1fb62fb0SOlivier Houchard 	unsigned int n_intersect = dst->n_bits;
279*1fb62fb0SOlivier Houchard 
280*1fb62fb0SOlivier Houchard 	if (src->n_bits < n_intersect)
281*1fb62fb0SOlivier Houchard 		n_intersect = src->n_bits;
282*1fb62fb0SOlivier Houchard 
283*1fb62fb0SOlivier Houchard 	n_intersect = CK_BITMAP_BLOCKS(n_intersect);
284*1fb62fb0SOlivier Houchard 	for (n = 0; n < n_intersect; n++) {
285*1fb62fb0SOlivier Houchard 		ck_pr_and_uint(&dst->map[n],
286*1fb62fb0SOlivier Houchard 		    (~ck_pr_load_uint(&src->map[n])));
287*1fb62fb0SOlivier Houchard 	}
288*1fb62fb0SOlivier Houchard 
289*1fb62fb0SOlivier Houchard 	return;
290*1fb62fb0SOlivier Houchard }
291*1fb62fb0SOlivier Houchard 
292*1fb62fb0SOlivier Houchard /*
293*1fb62fb0SOlivier Houchard  * Resets all bits in the provided bitmap. This is not a linearized
294*1fb62fb0SOlivier Houchard  * operation in ck_bitmap.
295*1fb62fb0SOlivier Houchard  */
296*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_clear(struct ck_bitmap * bitmap)297*1fb62fb0SOlivier Houchard ck_bitmap_clear(struct ck_bitmap *bitmap)
298*1fb62fb0SOlivier Houchard {
299*1fb62fb0SOlivier Houchard 	unsigned int i;
300*1fb62fb0SOlivier Houchard 	unsigned int n_buckets = ck_bitmap_base(bitmap->n_bits) /
301*1fb62fb0SOlivier Houchard 	    sizeof(unsigned int);
302*1fb62fb0SOlivier Houchard 
303*1fb62fb0SOlivier Houchard 	for (i = 0; i < n_buckets; i++)
304*1fb62fb0SOlivier Houchard 		ck_pr_store_uint(&bitmap->map[i], 0);
305*1fb62fb0SOlivier Houchard 
306*1fb62fb0SOlivier Houchard 	return;
307*1fb62fb0SOlivier Houchard }
308*1fb62fb0SOlivier Houchard 
309*1fb62fb0SOlivier Houchard /*
310*1fb62fb0SOlivier Houchard  * Returns true if the first limit bits in bitmap are cleared.  If
311*1fb62fb0SOlivier Houchard  * limit is greater than the bitmap size, limit is truncated to that
312*1fb62fb0SOlivier Houchard  * size.
313*1fb62fb0SOlivier Houchard  */
314*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_bitmap_empty(const ck_bitmap_t * bitmap,unsigned int limit)315*1fb62fb0SOlivier Houchard ck_bitmap_empty(const ck_bitmap_t *bitmap, unsigned int limit)
316*1fb62fb0SOlivier Houchard {
317*1fb62fb0SOlivier Houchard 	unsigned int i, words, slop;
318*1fb62fb0SOlivier Houchard 
319*1fb62fb0SOlivier Houchard 	if (limit > bitmap->n_bits)
320*1fb62fb0SOlivier Houchard 		limit = bitmap->n_bits;
321*1fb62fb0SOlivier Houchard 
322*1fb62fb0SOlivier Houchard 	words = limit / CK_BITMAP_BLOCK;
323*1fb62fb0SOlivier Houchard 	slop = limit % CK_BITMAP_BLOCK;
324*1fb62fb0SOlivier Houchard 	for (i = 0; i < words; i++) {
325*1fb62fb0SOlivier Houchard 		if (ck_pr_load_uint(&bitmap->map[i]) != 0) {
326*1fb62fb0SOlivier Houchard 			return false;
327*1fb62fb0SOlivier Houchard 		}
328*1fb62fb0SOlivier Houchard 	}
329*1fb62fb0SOlivier Houchard 
330*1fb62fb0SOlivier Houchard 	if (slop > 0) {
331*1fb62fb0SOlivier Houchard 		unsigned int word;
332*1fb62fb0SOlivier Houchard 
333*1fb62fb0SOlivier Houchard 		word = ck_pr_load_uint(&bitmap->map[i]);
334*1fb62fb0SOlivier Houchard 		if ((word & ((1U << slop) - 1)) != 0)
335*1fb62fb0SOlivier Houchard 			return false;
336*1fb62fb0SOlivier Houchard 	}
337*1fb62fb0SOlivier Houchard 
338*1fb62fb0SOlivier Houchard 	return true;
339*1fb62fb0SOlivier Houchard }
340*1fb62fb0SOlivier Houchard 
341*1fb62fb0SOlivier Houchard /*
342*1fb62fb0SOlivier Houchard  * Returns true if the first limit bits in bitmap are set.  If limit
343*1fb62fb0SOlivier Houchard  * is greater than the bitmap size, limit is truncated to that size.
344*1fb62fb0SOlivier Houchard  */
345*1fb62fb0SOlivier Houchard CK_CC_UNUSED static bool
ck_bitmap_full(const ck_bitmap_t * bitmap,unsigned int limit)346*1fb62fb0SOlivier Houchard ck_bitmap_full(const ck_bitmap_t *bitmap, unsigned int limit)
347*1fb62fb0SOlivier Houchard {
348*1fb62fb0SOlivier Houchard 	unsigned int i, slop, words;
349*1fb62fb0SOlivier Houchard 
350*1fb62fb0SOlivier Houchard 	if (limit > bitmap->n_bits) {
351*1fb62fb0SOlivier Houchard 		limit = bitmap->n_bits;
352*1fb62fb0SOlivier Houchard 	}
353*1fb62fb0SOlivier Houchard 
354*1fb62fb0SOlivier Houchard 	words = limit / CK_BITMAP_BLOCK;
355*1fb62fb0SOlivier Houchard 	slop = limit % CK_BITMAP_BLOCK;
356*1fb62fb0SOlivier Houchard 	for (i = 0; i < words; i++) {
357*1fb62fb0SOlivier Houchard 		if (ck_pr_load_uint(&bitmap->map[i]) != -1U)
358*1fb62fb0SOlivier Houchard 			return false;
359*1fb62fb0SOlivier Houchard 	}
360*1fb62fb0SOlivier Houchard 
361*1fb62fb0SOlivier Houchard 	if (slop > 0) {
362*1fb62fb0SOlivier Houchard 		unsigned int word;
363*1fb62fb0SOlivier Houchard 
364*1fb62fb0SOlivier Houchard 		word = ~ck_pr_load_uint(&bitmap->map[i]);
365*1fb62fb0SOlivier Houchard 		if ((word & ((1U << slop) - 1)) != 0)
366*1fb62fb0SOlivier Houchard 			return false;
367*1fb62fb0SOlivier Houchard 	}
368*1fb62fb0SOlivier Houchard 	return true;
369*1fb62fb0SOlivier Houchard }
370*1fb62fb0SOlivier Houchard 
371*1fb62fb0SOlivier Houchard /*
372*1fb62fb0SOlivier Houchard  * Returns the number of set bit in bitmap, upto (and excluding)
373*1fb62fb0SOlivier Houchard  * limit.  If limit is greater than the bitmap size, it is truncated
374*1fb62fb0SOlivier Houchard  * to that size.
375*1fb62fb0SOlivier Houchard  */
376*1fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_bitmap_count(const ck_bitmap_t * bitmap,unsigned int limit)377*1fb62fb0SOlivier Houchard ck_bitmap_count(const ck_bitmap_t *bitmap, unsigned int limit)
378*1fb62fb0SOlivier Houchard {
379*1fb62fb0SOlivier Houchard 	unsigned int count, i, slop, words;
380*1fb62fb0SOlivier Houchard 
381*1fb62fb0SOlivier Houchard 	if (limit > bitmap->n_bits)
382*1fb62fb0SOlivier Houchard 		limit = bitmap->n_bits;
383*1fb62fb0SOlivier Houchard 
384*1fb62fb0SOlivier Houchard 	words = limit / CK_BITMAP_BLOCK;
385*1fb62fb0SOlivier Houchard 	slop = limit % CK_BITMAP_BLOCK;
386*1fb62fb0SOlivier Houchard 	for (i = 0, count = 0; i < words; i++)
387*1fb62fb0SOlivier Houchard 		count += ck_cc_popcount(ck_pr_load_uint(&bitmap->map[i]));
388*1fb62fb0SOlivier Houchard 
389*1fb62fb0SOlivier Houchard 	if (slop > 0) {
390*1fb62fb0SOlivier Houchard 		unsigned int word;
391*1fb62fb0SOlivier Houchard 
392*1fb62fb0SOlivier Houchard 		word = ck_pr_load_uint(&bitmap->map[i]);
393*1fb62fb0SOlivier Houchard 		count += ck_cc_popcount(word & ((1U << slop) - 1));
394*1fb62fb0SOlivier Houchard 	}
395*1fb62fb0SOlivier Houchard 	return count;
396*1fb62fb0SOlivier Houchard }
397*1fb62fb0SOlivier Houchard 
398*1fb62fb0SOlivier Houchard /*
399*1fb62fb0SOlivier Houchard  * Returns the number of set bit in the intersection of two bitmaps,
400*1fb62fb0SOlivier Houchard  * upto (and excluding) limit.  If limit is greater than either bitmap
401*1fb62fb0SOlivier Houchard  * size, it is truncated to the smallest.
402*1fb62fb0SOlivier Houchard  */
403*1fb62fb0SOlivier Houchard CK_CC_INLINE static unsigned int
ck_bitmap_count_intersect(const ck_bitmap_t * x,const ck_bitmap_t * y,unsigned int limit)404*1fb62fb0SOlivier Houchard ck_bitmap_count_intersect(const ck_bitmap_t *x, const ck_bitmap_t *y,
405*1fb62fb0SOlivier Houchard     unsigned int limit)
406*1fb62fb0SOlivier Houchard {
407*1fb62fb0SOlivier Houchard 	unsigned int count, i, slop, words;
408*1fb62fb0SOlivier Houchard 
409*1fb62fb0SOlivier Houchard 	if (limit > x->n_bits)
410*1fb62fb0SOlivier Houchard 		limit = x->n_bits;
411*1fb62fb0SOlivier Houchard 
412*1fb62fb0SOlivier Houchard 	if (limit > y->n_bits)
413*1fb62fb0SOlivier Houchard 		limit = y->n_bits;
414*1fb62fb0SOlivier Houchard 
415*1fb62fb0SOlivier Houchard 	words = limit / CK_BITMAP_BLOCK;
416*1fb62fb0SOlivier Houchard 	slop = limit % CK_BITMAP_BLOCK;
417*1fb62fb0SOlivier Houchard 	for (i = 0, count = 0; i < words; i++) {
418*1fb62fb0SOlivier Houchard 		unsigned int xi, yi;
419*1fb62fb0SOlivier Houchard 
420*1fb62fb0SOlivier Houchard 		xi = ck_pr_load_uint(&x->map[i]);
421*1fb62fb0SOlivier Houchard 		yi = ck_pr_load_uint(&y->map[i]);
422*1fb62fb0SOlivier Houchard 		count += ck_cc_popcount(xi & yi);
423*1fb62fb0SOlivier Houchard 	}
424*1fb62fb0SOlivier Houchard 
425*1fb62fb0SOlivier Houchard 	if (slop > 0) {
426*1fb62fb0SOlivier Houchard 		unsigned int word, xi, yi;
427*1fb62fb0SOlivier Houchard 
428*1fb62fb0SOlivier Houchard 		xi = ck_pr_load_uint(&x->map[i]);
429*1fb62fb0SOlivier Houchard 		yi = ck_pr_load_uint(&y->map[i]);
430*1fb62fb0SOlivier Houchard 		word = xi & yi;
431*1fb62fb0SOlivier Houchard 		count += ck_cc_popcount(word & ((1U << slop) - 1));
432*1fb62fb0SOlivier Houchard 	}
433*1fb62fb0SOlivier Houchard 	return count;
434*1fb62fb0SOlivier Houchard }
435*1fb62fb0SOlivier Houchard 
436*1fb62fb0SOlivier Houchard /*
437*1fb62fb0SOlivier Houchard  * Initializes a ck_bitmap pointing to a region of memory with
438*1fb62fb0SOlivier Houchard  * ck_bitmap_size(n_bits) bytes. Third argument determines whether
439*1fb62fb0SOlivier Houchard  * default bit value is 1 (true) or 0 (false).
440*1fb62fb0SOlivier Houchard  */
441*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_init(struct ck_bitmap * bitmap,unsigned int n_bits,bool set)442*1fb62fb0SOlivier Houchard ck_bitmap_init(struct ck_bitmap *bitmap,
443*1fb62fb0SOlivier Houchard 	       unsigned int n_bits,
444*1fb62fb0SOlivier Houchard 	       bool set)
445*1fb62fb0SOlivier Houchard {
446*1fb62fb0SOlivier Houchard 	unsigned int base = ck_bitmap_base(n_bits);
447*1fb62fb0SOlivier Houchard 
448*1fb62fb0SOlivier Houchard 	bitmap->n_bits = n_bits;
449*1fb62fb0SOlivier Houchard 	memset(bitmap->map, -(int)set, base);
450*1fb62fb0SOlivier Houchard 
451*1fb62fb0SOlivier Houchard 	if (set == true) {
452*1fb62fb0SOlivier Houchard 		unsigned int b = n_bits % CK_BITMAP_BLOCK;
453*1fb62fb0SOlivier Houchard 
454*1fb62fb0SOlivier Houchard 		if (b == 0)
455*1fb62fb0SOlivier Houchard 			return;
456*1fb62fb0SOlivier Houchard 
457*1fb62fb0SOlivier Houchard 		*CK_BITMAP_PTR(bitmap->map, n_bits - 1) &= (1U << b) - 1U;
458*1fb62fb0SOlivier Houchard 	}
459*1fb62fb0SOlivier Houchard 
460*1fb62fb0SOlivier Houchard 	return;
461*1fb62fb0SOlivier Houchard }
462*1fb62fb0SOlivier Houchard 
463*1fb62fb0SOlivier Houchard /*
464*1fb62fb0SOlivier Houchard  * Initialize iterator for use with provided bitmap.
465*1fb62fb0SOlivier Houchard  */
466*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_bitmap_iterator_init(struct ck_bitmap_iterator * i,const struct ck_bitmap * bitmap)467*1fb62fb0SOlivier Houchard ck_bitmap_iterator_init(struct ck_bitmap_iterator *i,
468*1fb62fb0SOlivier Houchard     const struct ck_bitmap *bitmap)
469*1fb62fb0SOlivier Houchard {
470*1fb62fb0SOlivier Houchard 
471*1fb62fb0SOlivier Houchard 	i->n_block = 0;
472*1fb62fb0SOlivier Houchard 	i->n_limit = CK_BITMAP_BLOCKS(bitmap->n_bits);
473*1fb62fb0SOlivier Houchard 	if (i->n_limit > 0) {
474*1fb62fb0SOlivier Houchard 		i->cache = ck_pr_load_uint(&bitmap->map[0]);
475*1fb62fb0SOlivier Houchard 	} else {
476*1fb62fb0SOlivier Houchard 		i->cache = 0;
477*1fb62fb0SOlivier Houchard 	}
478*1fb62fb0SOlivier Houchard 	return;
479*1fb62fb0SOlivier Houchard }
480*1fb62fb0SOlivier Houchard 
481*1fb62fb0SOlivier Houchard /*
482*1fb62fb0SOlivier Houchard  * Iterate to next bit.
483*1fb62fb0SOlivier Houchard  */
484*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_bitmap_next(const struct ck_bitmap * bitmap,struct ck_bitmap_iterator * i,unsigned int * bit)485*1fb62fb0SOlivier Houchard ck_bitmap_next(const struct ck_bitmap *bitmap,
486*1fb62fb0SOlivier Houchard 	       struct ck_bitmap_iterator *i,
487*1fb62fb0SOlivier Houchard 	       unsigned int *bit)
488*1fb62fb0SOlivier Houchard {
489*1fb62fb0SOlivier Houchard 	unsigned int cache = i->cache;
490*1fb62fb0SOlivier Houchard 	unsigned int n_block = i->n_block;
491*1fb62fb0SOlivier Houchard 	unsigned int n_limit = i->n_limit;
492*1fb62fb0SOlivier Houchard 
493*1fb62fb0SOlivier Houchard 	if (cache == 0) {
494*1fb62fb0SOlivier Houchard 		if (n_block >= n_limit)
495*1fb62fb0SOlivier Houchard 			return false;
496*1fb62fb0SOlivier Houchard 
497*1fb62fb0SOlivier Houchard 		for (n_block++; n_block < n_limit; n_block++) {
498*1fb62fb0SOlivier Houchard 			cache = ck_pr_load_uint(&bitmap->map[n_block]);
499*1fb62fb0SOlivier Houchard 			if (cache != 0)
500*1fb62fb0SOlivier Houchard 				goto non_zero;
501*1fb62fb0SOlivier Houchard 		}
502*1fb62fb0SOlivier Houchard 
503*1fb62fb0SOlivier Houchard 		i->cache = 0;
504*1fb62fb0SOlivier Houchard 		i->n_block = n_block;
505*1fb62fb0SOlivier Houchard 		return false;
506*1fb62fb0SOlivier Houchard 	}
507*1fb62fb0SOlivier Houchard 
508*1fb62fb0SOlivier Houchard non_zero:
509*1fb62fb0SOlivier Houchard 	*bit = CK_BITMAP_BLOCK * n_block + ck_cc_ctz(cache);
510*1fb62fb0SOlivier Houchard 	i->cache = cache & (cache - 1);
511*1fb62fb0SOlivier Houchard 	i->n_block = n_block;
512*1fb62fb0SOlivier Houchard 	return true;
513*1fb62fb0SOlivier Houchard }
514*1fb62fb0SOlivier Houchard 
515*1fb62fb0SOlivier Houchard #endif /* CK_BITMAP_H */
516