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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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