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