diff options
Diffstat (limited to 'lib/bitmap.c')
| -rw-r--r-- | lib/bitmap.c | 100 |
1 files changed, 88 insertions, 12 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index 702565821c99..ffb78c916ccd 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
| @@ -271,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) | |||
| 271 | } | 271 | } |
| 272 | EXPORT_SYMBOL(__bitmap_weight); | 272 | EXPORT_SYMBOL(__bitmap_weight); |
| 273 | 273 | ||
| 274 | #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) | ||
| 275 | |||
| 276 | void bitmap_set(unsigned long *map, int start, int nr) | ||
| 277 | { | ||
| 278 | unsigned long *p = map + BIT_WORD(start); | ||
| 279 | const int size = start + nr; | ||
| 280 | int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); | ||
| 281 | unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); | ||
| 282 | |||
| 283 | while (nr - bits_to_set >= 0) { | ||
| 284 | *p |= mask_to_set; | ||
| 285 | nr -= bits_to_set; | ||
| 286 | bits_to_set = BITS_PER_LONG; | ||
| 287 | mask_to_set = ~0UL; | ||
| 288 | p++; | ||
| 289 | } | ||
| 290 | if (nr) { | ||
| 291 | mask_to_set &= BITMAP_LAST_WORD_MASK(size); | ||
| 292 | *p |= mask_to_set; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | EXPORT_SYMBOL(bitmap_set); | ||
| 296 | |||
| 297 | void bitmap_clear(unsigned long *map, int start, int nr) | ||
| 298 | { | ||
| 299 | unsigned long *p = map + BIT_WORD(start); | ||
| 300 | const int size = start + nr; | ||
| 301 | int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); | ||
| 302 | unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); | ||
| 303 | |||
| 304 | while (nr - bits_to_clear >= 0) { | ||
| 305 | *p &= ~mask_to_clear; | ||
| 306 | nr -= bits_to_clear; | ||
| 307 | bits_to_clear = BITS_PER_LONG; | ||
| 308 | mask_to_clear = ~0UL; | ||
| 309 | p++; | ||
| 310 | } | ||
| 311 | if (nr) { | ||
| 312 | mask_to_clear &= BITMAP_LAST_WORD_MASK(size); | ||
| 313 | *p &= ~mask_to_clear; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | EXPORT_SYMBOL(bitmap_clear); | ||
| 317 | |||
| 318 | /* | ||
| 319 | * bitmap_find_next_zero_area - find a contiguous aligned zero area | ||
| 320 | * @map: The address to base the search on | ||
| 321 | * @size: The bitmap size in bits | ||
| 322 | * @start: The bitnumber to start searching at | ||
| 323 | * @nr: The number of zeroed bits we're looking for | ||
| 324 | * @align_mask: Alignment mask for zero area | ||
| 325 | * | ||
| 326 | * The @align_mask should be one less than a power of 2; the effect is that | ||
| 327 | * the bit offset of all zero areas this function finds is multiples of that | ||
| 328 | * power of 2. A @align_mask of 0 means no alignment is required. | ||
| 329 | */ | ||
| 330 | unsigned long bitmap_find_next_zero_area(unsigned long *map, | ||
| 331 | unsigned long size, | ||
| 332 | unsigned long start, | ||
| 333 | unsigned int nr, | ||
| 334 | unsigned long align_mask) | ||
| 335 | { | ||
| 336 | unsigned long index, end, i; | ||
| 337 | again: | ||
| 338 | index = find_next_zero_bit(map, size, start); | ||
| 339 | |||
| 340 | /* Align allocation */ | ||
| 341 | index = __ALIGN_MASK(index, align_mask); | ||
| 342 | |||
| 343 | end = index + nr; | ||
| 344 | if (end > size) | ||
| 345 | return end; | ||
| 346 | i = find_next_bit(map, end, index); | ||
| 347 | if (i < end) { | ||
| 348 | start = i + 1; | ||
| 349 | goto again; | ||
| 350 | } | ||
| 351 | return index; | ||
| 352 | } | ||
| 353 | EXPORT_SYMBOL(bitmap_find_next_zero_area); | ||
| 354 | |||
| 274 | /* | 355 | /* |
| 275 | * Bitmap printing & parsing functions: first version by Bill Irwin, | 356 | * Bitmap printing & parsing functions: first version by Bill Irwin, |
| 276 | * second version by Paul Jackson, third by Joe Korty. | 357 | * second version by Paul Jackson, third by Joe Korty. |
| @@ -406,7 +487,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen, | |||
| 406 | EXPORT_SYMBOL(__bitmap_parse); | 487 | EXPORT_SYMBOL(__bitmap_parse); |
| 407 | 488 | ||
| 408 | /** | 489 | /** |
| 409 | * bitmap_parse_user() | 490 | * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap |
| 410 | * | 491 | * |
| 411 | * @ubuf: pointer to user buffer containing string. | 492 | * @ubuf: pointer to user buffer containing string. |
| 412 | * @ulen: buffer size in bytes. If string is smaller than this | 493 | * @ulen: buffer size in bytes. If string is smaller than this |
| @@ -538,7 +619,7 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits) | |||
| 538 | EXPORT_SYMBOL(bitmap_parselist); | 619 | EXPORT_SYMBOL(bitmap_parselist); |
| 539 | 620 | ||
| 540 | /** | 621 | /** |
| 541 | * bitmap_pos_to_ord(buf, pos, bits) | 622 | * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap |
| 542 | * @buf: pointer to a bitmap | 623 | * @buf: pointer to a bitmap |
| 543 | * @pos: a bit position in @buf (0 <= @pos < @bits) | 624 | * @pos: a bit position in @buf (0 <= @pos < @bits) |
| 544 | * @bits: number of valid bit positions in @buf | 625 | * @bits: number of valid bit positions in @buf |
| @@ -574,7 +655,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) | |||
| 574 | } | 655 | } |
| 575 | 656 | ||
| 576 | /** | 657 | /** |
| 577 | * bitmap_ord_to_pos(buf, ord, bits) | 658 | * bitmap_ord_to_pos - find position of n-th set bit in bitmap |
| 578 | * @buf: pointer to bitmap | 659 | * @buf: pointer to bitmap |
| 579 | * @ord: ordinal bit position (n-th set bit, n >= 0) | 660 | * @ord: ordinal bit position (n-th set bit, n >= 0) |
| 580 | * @bits: number of valid bit positions in @buf | 661 | * @bits: number of valid bit positions in @buf |
| @@ -652,10 +733,9 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src, | |||
| 652 | bitmap_zero(dst, bits); | 733 | bitmap_zero(dst, bits); |
| 653 | 734 | ||
| 654 | w = bitmap_weight(new, bits); | 735 | w = bitmap_weight(new, bits); |
| 655 | for (oldbit = find_first_bit(src, bits); | 736 | for_each_set_bit(oldbit, src, bits) { |
| 656 | oldbit < bits; | ||
| 657 | oldbit = find_next_bit(src, bits, oldbit + 1)) { | ||
| 658 | int n = bitmap_pos_to_ord(old, oldbit, bits); | 737 | int n = bitmap_pos_to_ord(old, oldbit, bits); |
| 738 | |||
| 659 | if (n < 0 || w == 0) | 739 | if (n < 0 || w == 0) |
| 660 | set_bit(oldbit, dst); /* identity map */ | 740 | set_bit(oldbit, dst); /* identity map */ |
| 661 | else | 741 | else |
| @@ -822,9 +902,7 @@ void bitmap_onto(unsigned long *dst, const unsigned long *orig, | |||
| 822 | */ | 902 | */ |
| 823 | 903 | ||
| 824 | m = 0; | 904 | m = 0; |
| 825 | for (n = find_first_bit(relmap, bits); | 905 | for_each_set_bit(n, relmap, bits) { |
| 826 | n < bits; | ||
| 827 | n = find_next_bit(relmap, bits, n + 1)) { | ||
| 828 | /* m == bitmap_pos_to_ord(relmap, n, bits) */ | 906 | /* m == bitmap_pos_to_ord(relmap, n, bits) */ |
| 829 | if (test_bit(m, orig)) | 907 | if (test_bit(m, orig)) |
| 830 | set_bit(n, dst); | 908 | set_bit(n, dst); |
| @@ -853,9 +931,7 @@ void bitmap_fold(unsigned long *dst, const unsigned long *orig, | |||
| 853 | return; | 931 | return; |
| 854 | bitmap_zero(dst, bits); | 932 | bitmap_zero(dst, bits); |
| 855 | 933 | ||
| 856 | for (oldbit = find_first_bit(orig, bits); | 934 | for_each_set_bit(oldbit, orig, bits) |
| 857 | oldbit < bits; | ||
| 858 | oldbit = find_next_bit(orig, bits, oldbit + 1)) | ||
| 859 | set_bit(oldbit % sz, dst); | 935 | set_bit(oldbit % sz, dst); |
| 860 | } | 936 | } |
| 861 | EXPORT_SYMBOL(bitmap_fold); | 937 | EXPORT_SYMBOL(bitmap_fold); |
