1/** 2 * \file 3 * \brief General Numa functions 4 * 5 */ 6 7/* 8 * Copyright (c) 2014, ETH Zurich. 9 * All rights reserved. 10 * 11 * This file is distributed under the terms in the attached LICENSE file. 12 * If you do not find this file, copies can be found by writing to: 13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 14 */ 15 16#include <barrelfish/barrelfish.h> 17 18#include <bitmap.h> 19 20///< the bitmap data type to store the bitmap elements 21typedef uint32_t bitmap_data_t; 22 23///< helper macro for 24#define BITMAP_BITS_PER_ELEMENT (8 * sizeof(bitmap_data_t)) 25 26///< helper macro for determining the number of 27#define BITMAP_DATA_SIZE(nbits) \ 28 ((nbits + (BITMAP_BITS_PER_ELEMENT-1)) / BITMAP_BITS_PER_ELEMENT) 29 30 31 32/** 33 * \brief bitmap struct internal representation 34 */ 35struct bitmap 36{ 37 uint32_t nbits; ///< the number of bits this bitmap has 38 uint32_t weight; ///< caches the number of set bits 39 uint32_t first; ///< caches the position of the first bit 40 uint32_t last; ///< caches the number of the last bit 41 bitmap_data_t *data; ///< stores the bit map 42}; 43 44/* 45 * ============================================================================= 46 * bitmap allocation and free 47 * ============================================================================= 48 */ 49 50/** 51 * \brief allocates a new bitmap of a given size 52 * 53 * \param nbits size of the bitmap 54 * 55 * \return pointer to the allocated bitmap on success 56 * NULL on failure 57 */ 58struct bitmap *bitmap_alloc(uint32_t nbits) 59{ 60 struct bitmap *bm = calloc(1, sizeof(*bm) + BITMAP_DATA_SIZE(nbits)); 61 if (bm == NULL) { 62 return 0; 63 } 64 65 bm->nbits = nbits; 66 bm->data = (bitmap_data_t *)(bm + 1); 67 68 return bm; 69} 70 71/** 72 * \brief frees the resources of a bitmap 73 * 74 * \param bm bitmap to be freed 75 */ 76void bitmap_free(struct bitmap *bm) 77{ 78 if (bm) { 79 free(bm); 80 } 81} 82 83/* 84 * ============================================================================= 85 * bitmap intput and output 86 * ============================================================================= 87 */ 88 89/** 90 * \brief formats the contents of the bitmap into the outbut buffer 91 * 92 * \param outbuf buffer to hold the output data 93 * \param length length of the output buffer 94 * \param bm bitmap to format 95 * \param hex flag to enable hexadecimal formatted output 96 * 97 * \return number of bytes written into the buffer 98 */ 99size_t bitmap_format(char *outbuf, size_t length, struct bitmap *bm, uint8_t hex) 100{ 101 assert(!"NYI"); 102 return 0; 103} 104 105/** 106 * \brief parses an input string and stores it into the bitmap 107 * 108 * \param outbm bitmap to store the parsed data into 109 * \param inbuf input string buffer 110 * \param length length of the input string buffer 111 * \param hex parse input as hex 112 * 113 * \return number of bytes parsed from the input string 114 */ 115size_t bitmap_parse(struct bitmap *outbm, char *inbuf, size_t length, uint8_t hex) 116{ 117 assert(!"NYI"); 118 return 0; 119} 120 121/** 122 * \brief serializes the bitmap into a buffer 123 * 124 * \param dest buffer to store the serialized bitmap 125 * \param length lenght ouf the buffer 126 * \param bm bitmap to serialize 127 * 128 * \return 129 */ 130errval_t bitmap_serialize(void *dest, size_t length, const struct bitmap *bm) 131{ 132 assert(!"NYI"); 133 return SYS_ERR_OK; 134} 135 136/** 137 * \brief deserializes a bitmap form a buffer 138 * 139 * \param bm bitmap to store the serialized data 140 * \param src source buffer to read the serialized data from 141 * \param length length of the source buffer 142 * 143 * \return SYS_ERR_OK on success 144 * errval on failure 145 */ 146errval_t bitmap_deserialize(struct bitmap *bm, const void *src, size_t length) 147{ 148 assert(!"NYI"); 149 return SYS_ERR_OK; 150} 151 152/* 153 * ============================================================================= 154 * meta information queries 155 * ============================================================================= 156 */ 157 158/** 159 * \brief returns the number of bytes in the bitmap data representation 160 * 161 * \param bm bitmap to determine the bytes for 162 * 163 * \return size of the bitmap in bytes 164 */ 165uint32_t bitmap_get_nbytes(const struct bitmap *bm) 166{ 167 return (bitmap_bit_t)(BITMAP_DATA_SIZE(bm->nbits) * sizeof(bitmap_data_t)); 168} 169 170/** 171 * \brief gets the number of bits of this bitmap 172 * 173 * \param bm the bitmap 174 * 175 * \return size of the bitmap in bits 176 */ 177uint32_t bitmap_get_nbits(const struct bitmap *bm) 178{ 179 return bm->nbits; 180} 181 182/** 183 * \brief gets the weight of the bit map i.e. number of set bits 184 * 185 * \param bm the bitmap 186 * 187 * \return number of set bits 188 */ 189uint32_t bitmap_get_weight(const struct bitmap *bm) 190{ 191 return bm->weight; 192} 193 194/** 195 * \brief returns a pointer to the raw bitmap 196 * 197 * \param bm the bitmap 198 * 199 * \returns Pointer to the raw bitmap 200 */ 201void *bitmap_raw(struct bitmap *bm) 202{ 203 return bm->data; 204} 205 206/* 207 * ============================================================================= 208 * bitmap queries 209 * ============================================================================= 210 */ 211 212/** 213 * \brief ckecks if a given bit is set 214 * 215 * \param bm bitmap to check 216 * \param i index of the bit 217 * 218 * \return TRUE iff the bit is set 219 * FALSE otherwise (also if bit index exceeds bitmap size) 220 */ 221bool bitmap_is_bit_set(const struct bitmap *bm, bitmap_bit_t i) 222{ 223 if (i < bm->nbits) { 224 bitmap_data_t data = bm->data[i/BITMAP_BITS_PER_ELEMENT]; 225 return (data >> (i % BITMAP_BITS_PER_ELEMENT)) & 1; 226 } else { 227 return 0; 228 } 229} 230 231/** 232 * \brief ckecks if a given bit is cleare 233 * 234 * \param bm bitmap to check 235 * \param i index of the bit 236 * 237 * \return TRUE iff the bit is clear 238 * FALSE otherwise 239 */ 240bool bitmap_is_bit_clear(const struct bitmap *bm, bitmap_bit_t i) 241{ 242 return !bitmap_is_bit_set(bm, i); 243} 244 245/** 246 * \brief checks if all bits are set 247 * 248 * \param bm bitmap to check 249 * 250 * \return TRUE iff all bits are set 251 * FALSE otherwise 252 */ 253bool bitmap_is_all_set(const struct bitmap *bm) 254{ 255 return (bm->weight == bm->nbits); 256} 257 258/** 259 * \brief checks if all bits are clear 260 * 261 * \param bm bitmap to check 262 * 263 * \return TRUE iff all bits are clear 264 * FALSE otherwise 265 */ 266bool bitmap_is_all_clear(const struct bitmap *bm) 267{ 268 return (bm->weight == 0); 269} 270 271/** 272 * \brief returns the bit number of the first set 273 * 274 * \param bm bitmap to get the first set bit 275 * 276 * \returns index of the first bit 277 * BITMAP_BIT_NONE if there is no bit set 278 */ 279bitmap_bit_t bitmap_get_first(const struct bitmap *bm) 280{ 281 if (bm->weight) { 282 return bm->first; 283 } 284 return BITMAP_BIT_NONE; 285} 286 287 288/** 289 * \brief returns the bit number of the last set 290 * 291 * \param bm bitmap to get the last set bit 292 * 293 * \returns index of the last bit 294 * BITMAP_BIT_NONE if there is no bit set 295 */ 296bitmap_bit_t bitmap_get_last(const struct bitmap *bm) 297{ 298 if (bm->weight) { 299 return bm->last; 300 } 301 return BITMAP_BIT_NONE; 302} 303 304/** 305 * \brief gets the index of the next bit set 306 * 307 * \param bm the bitmap to check 308 * \param i bit to start checking from (not inclusive) 309 * 310 * \return index of the next set bit 311 * BITMAP_BIT_NONE if none is set 312 */ 313bitmap_bit_t bitmap_get_next(const struct bitmap *bm, bitmap_bit_t i) 314{ 315 for (bitmap_bit_t k = i+1; k < bm->nbits; ++k) { 316 if (bitmap_is_bit_set(bm, k)) { 317 return k; 318 } 319 } 320 return BITMAP_BIT_NONE; 321} 322 323/** 324 * \brief gets the index of the previous bit set 325 * 326 * \param bm the bitmap to check 327 * \param i index of the bit to check 328 * 329 * \return index of the next set bit 330 * BITMAP_BIT_NONE if none is set 331 */ 332bitmap_bit_t bitmap_get_prev(const struct bitmap *bm, bitmap_bit_t i) 333{ 334 if (i < bm->nbits) { 335 for (bitmap_bit_t k = i-1; k >= 0; --k) { 336 if (bitmap_is_bit_set(bm, k)) { 337 return k; 338 } 339 } 340 } 341 342 return BITMAP_BIT_NONE; 343} 344 345/* 346 * ============================================================================= 347 * Bitmap Manipulations 348 * ============================================================================= 349 */ 350 351/** 352 * \brief sets a bit in the bitmap 353 * 354 * \param bm bitmap to set the bit 355 * \param i index of the bit to set 356 */ 357void bitmap_set_bit(struct bitmap *bm, bitmap_bit_t i) 358{ 359 if (i < bm->nbits) { 360 bitmap_data_t data = bm->data[i/BITMAP_BITS_PER_ELEMENT]; 361 bitmap_data_t mask = (1UL << (i % BITMAP_BITS_PER_ELEMENT)); 362 if (!(mask & data)) { 363 /* bit was cleared so set it */ 364 data |= (1UL << (i % BITMAP_BITS_PER_ELEMENT)); 365 bm->data[i/BITMAP_BITS_PER_ELEMENT] = data; 366 if (bm->weight) { 367 if (bm->last < i) { 368 bm->last = i; 369 } else if (bm->first > i) { 370 bm->first = i; 371 } 372 } else { 373 bm->first = i; 374 bm->last = i; 375 } 376 bm->weight++; 377 } 378 } 379} 380 381/** 382 * \brief clears a bit in the bitmap 383 * 384 * \param bm bitmap to set the bit 385 * \param i index of the bit to clear 386 */ 387void bitmap_clear_bit(struct bitmap *bm, bitmap_bit_t i) 388{ 389 if (i < bm->nbits) { 390 bitmap_data_t data = bm->data[i/BITMAP_BITS_PER_ELEMENT]; 391 bitmap_data_t mask = 1UL << (i % BITMAP_BITS_PER_ELEMENT); 392 if (data & mask) { 393 /* bit was set so clear it */ 394 bm->weight--; 395 data &= ~(mask); 396 bm->data[i/BITMAP_BITS_PER_ELEMENT] = data; 397 if (bm->weight) { 398 if (bm->last == i) { 399 bm->last = bitmap_get_prev(bm, i); 400 } else if (bm->first == i) { 401 bm->first = bitmap_get_next(bm, i); 402 } 403 } else { 404 bm->first = BITMAP_BIT_NONE; 405 bm->last = BITMAP_BIT_NONE; 406 } 407 } 408 } 409} 410 411/** 412 * \brief sets all the bits in the bitmap 413 * 414 * \param bm bitmap to set all bits 415 */ 416void bitmap_set_all(struct bitmap *bm) 417{ 418 memset(bm->data, 0xFF, bitmap_get_nbytes(bm)); 419 bm->weight = bm->nbits; 420 bm->last = bm->nbits - 1; 421 bm->first = 0; 422} 423 424/** 425 * \brief clears all the bits in the bitmap 426 * 427 * \param bm bitmap to clear all bits 428 */ 429void bitmap_clear_all(struct bitmap *bm) 430{ 431 memset(bm->data, 0, bitmap_get_nbytes(bm)); 432 bm->weight = 0; 433 bm->first = BITMAP_BIT_NONE; 434 bm->last = BITMAP_BIT_NONE; 435} 436 437/** 438 * \brief sets a range of bits in the bitmap 439 * 440 * \param bm bitmap to set the range 441 * \param from start of the range (including) 442 * \param to end of the range (including) 443 */ 444void bitmap_set_range(struct bitmap *bm, bitmap_bit_t from, bitmap_bit_t to) 445{ 446 if (to > bm->nbits) { 447 to = bm->nbits - 1; 448 } 449 for (bitmap_bit_t i = from; i <= to; ++i) { 450 bitmap_set_bit(bm, i); 451 } 452} 453 454/** 455 * \brief sets a range of bits in the bitmap 456 * 457 * \param bm bitmap to set the range 458 * \param from start of the range (including) 459 * \param to end of the range (including) 460 */ 461void bitmap_clear_range(struct bitmap *bm, bitmap_bit_t from, bitmap_bit_t to) 462{ 463 if (to > bm->nbits) { 464 to = bm->nbits - 1; 465 } 466 for (bitmap_bit_t i = from; i <= to; ++i) { 467 bitmap_clear_bit(bm, i); 468 } 469} 470 471/** 472 * \brief clears the bitmap except for the given range 473 * 474 * \param bm bitmap to set the range 475 * \param from start of the range (including) 476 * \param to end of the range (including) 477 */ 478void bitmap_keep_range(struct bitmap *bm, uint32_t from, uint32_t to) 479{ 480 if (from != 0) { 481 bitmap_clear_range(bm, 0, from - 1); 482 } 483 484 if (to != bm->nbits - 1) { 485 bitmap_clear_range(bm, to, bm->nbits); 486 } 487} 488 489/** 490 * \brief copies one bitmap onto another 491 * 492 * \param to bitmap to copy into 493 * \param from bitmap to copy from 494 * 495 * only the minimum number of bits in both bitmaps are copied. If the source is 496 * smaller than the destination remaining bits are cleared 497 */ 498void bitmap_copy(struct bitmap *to, const struct bitmap *from) 499{ 500 bitmap_clear_all(to); 501 bitmap_bit_t nbytes; 502 if (to->nbits < from->nbits) { 503 nbytes = bitmap_get_nbytes(to); 504 } else { 505 nbytes = bitmap_get_nbytes(from); 506 } 507 memcpy(to->data, from->data, nbytes); 508 509 /* TODO: set the meta information */ 510 assert(!"NYI? setting meta information"); 511} 512 513 514/* 515 * ============================================================================= 516 * Bitmap Comparisons 517 * ============================================================================= 518 */ 519 520/** 521 * \brief determines if two bitmaps are equal 522 * 523 * \param bm1 the first bitmap 524 * \param bm2 the second bitmap 525 * 526 * \return TRUE if the two bitmaps are equal 527 * FALSE otherwise 528 */ 529bool bitmap_equal(const struct bitmap *bm1, const struct bitmap *bm2) 530{ 531 /* the pointers are equal */ 532 if (bm1 == bm2) { 533 return 1; 534 } 535 /* the sizes do not match, not equal */ 536 if (bm1->nbits != bm2->nbits) { 537 return 0; 538 } 539 540 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm1->nbits); 541 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(bm2->nbits); 542 543 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 544 if (i < src_bytes) { 545 if (bm1->data[i] != bm2->data[i]) { 546 return 0; 547 } 548 } 549 } 550 551 return 1; 552} 553 554/** 555 * \brief determines if one bitmask is a subset of the other 556 * 557 * \param haystack the original bitmap 558 * \param needle the potential subset bitmap 559 * 560 * \return TRUE if the second bitmap is a subset of the other 561 * FALSE otherwise 562 */ 563bool bitmap_subset(const struct bitmap *haystack, const struct bitmap *needle) 564{ 565 assert(!"NYI"); 566 return 0; 567} 568 569/** 570 * \brief determines if two bitmaps are disjoint i.e. not sharing a set bit 571 * 572 * \param bm1 the first bitmap 573 * \param bm2 the second bitmap 574 * 575 * \return TRUE if the two bitmaps are disjoint 576 * FALSE otherwise 577 */ 578bool bitmap_disjoint(const struct bitmap *bm1, const struct bitmap *bm2) 579{ 580 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm1->nbits); 581 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(bm2->nbits); 582 583 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 584 if (i < src_bytes) { 585 if (bm1->data[i] & bm2->data[i]) { 586 return 0; 587 } 588 } 589 } 590 591 return 1; 592} 593 594/** 595 * \brief determines if two bitmaps are intersecting i.e. sharing a set bit 596 * 597 * \param bm1 the first bitmap 598 * \param bm2 the second bitmap 599 * 600 * \return TRUE if the two bitmaps are equal 601 * FALSE otherwise 602 */ 603bool bitmap_intersects(const struct bitmap *bm1, const struct bitmap *bm2) 604{ 605 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm1->nbits); 606 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(bm2->nbits); 607 608 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 609 if (i < src_bytes) { 610 if (bm1->data[i] & bm2->data[i]) { 611 return 1; 612 } 613 } 614 } 615 616 return 0; 617} 618 619/* 620 * ============================================================================= 621 * Bitmap Operations 622 * ============================================================================= 623 */ 624 625/** 626 * \brief computes the complement to the bitmap 627 * 628 * \param bm the bitmap 629 */ 630void bitmap_complement(struct bitmap *bm) 631{ 632 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(bm->nbits) - 1; 633 634 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 635 bm->data[i] = ~bm->data[i]; 636 } 637 638 for (bitmap_bit_t i = (dst_bytes * sizeof(bitmap_data_t)); i < bm->nbits; ++i) { 639 if (bitmap_is_bit_set(bm, i)) { 640 bitmap_clear_bit(bm, i); 641 } else { 642 bitmap_set_bit(bm, i); 643 } 644 } 645} 646 647/** 648 * \brief performs a right shift operation on the bitmap 649 * 650 * \param bm the bitmap 651 * \param n number of bits to shift 652 */ 653void bitmap_shift_right(struct bitmap *bm, bitmap_bit_t n) 654{ 655 assert(!"NYI"); 656} 657 658/** 659 * \brief performs a left shift operation on the bitmap 660 * 661 * \param bm the bitmap 662 * \param n number of bits to shift 663 */ 664void bitmap_shift_left(struct bitmap *bm, bitmap_bit_t n) 665{ 666 assert(!"NYI"); 667} 668 669/** 670 * \brief performs a logical AND operation between two bitmaps 671 * 672 * \param dst destination to store the new bitmap 673 * \param src source bitmap 674 * 675 * dst = dst AND src 676 */ 677void bitmap_and(struct bitmap *dst, const struct bitmap *src) 678{ 679 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits); 680 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits); 681 682 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 683 if (i < src_bytes) { 684 dst->data[i] = ~(dst->data[i] & src->data[i]); 685 } else { 686 dst->data[i] = 0; 687 } 688 } 689} 690 691/** 692 * \brief performs a logical NAND operation between two bitmaps 693 * 694 * \param dst destination to store the new bitmap 695 * \param src source bitmap 696 * 697 * dst = dst NAND src 698 */ 699void bitmap_nand(struct bitmap *dst, const struct bitmap *src) 700{ 701 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits); 702 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits); 703 704 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 705 if (i < src_bytes) { 706 dst->data[i] = ~(dst->data[i] & src->data[i]); 707 } else { 708 dst->data[i] = ~((bitmap_data_t)0); 709 } 710 } 711} 712 713/** 714 * \brief performs a logical OR operation between two bitmaps 715 * 716 * \param dst destination to store the new bitmap 717 * \param src source bitmap 718 * 719 * dst = dst OR src 720 */ 721void bitmap_or(struct bitmap *dst, const struct bitmap *src) 722{ 723 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits); 724 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits); 725 726 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 727 if (i < src_bytes) { 728 dst->data[i] = (dst->data[i] | src->data[i]); 729 } 730 } 731} 732 733/** 734 * \brief performs a logical AND operation between two bitmaps 735 * 736 * \param dst destination to store the new bitmap 737 * \param src source bitmap 738 * 739 * dst = dst XOR src 740 */ 741void bitmap_xor(struct bitmap *dst, const struct bitmap *src) 742{ 743 bitmap_bit_t dst_bytes = BITMAP_DATA_SIZE(dst->nbits); 744 bitmap_bit_t src_bytes = BITMAP_DATA_SIZE(dst->nbits); 745 746 for (bitmap_bit_t i = 0; i < dst_bytes; ++i) { 747 if (i < src_bytes) { 748 dst->data[i] = (dst->data[i] ^ src->data[i]); 749 } 750 } 751} 752 753/* 754 * ============================================================================= 755 * Bitmap Debug 756 * ============================================================================= 757 */ 758 759void bitmap_dump(const struct bitmap *bm) 760{ 761 uint8_t *data = (uint8_t *)(bm->data); 762 763 debug_printf("dumping contents of bitmap %p\n", bm); 764 debug_printf("----------------------------------\n"); 765 for (uint32_t i = 0; i < bitmap_get_nbytes(bm); i += 4) { 766 debug_printf("bytes %u-%u: [%02x] [%02x] [%02x] [%02x]\n", 767 i, i+3, data[i], data[i+1], data[i+2], data[i+3]); 768 } 769 debug_printf("----------------------------------\n"); 770} 771