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