diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bitmap.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index fb9371fdd44a..23d3b1147fe9 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
@@ -511,6 +511,172 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits) | |||
511 | } | 511 | } |
512 | EXPORT_SYMBOL(bitmap_parselist); | 512 | EXPORT_SYMBOL(bitmap_parselist); |
513 | 513 | ||
514 | /* | ||
515 | * bitmap_pos_to_ord(buf, pos, bits) | ||
516 | * @buf: pointer to a bitmap | ||
517 | * @pos: a bit position in @buf (0 <= @pos < @bits) | ||
518 | * @bits: number of valid bit positions in @buf | ||
519 | * | ||
520 | * Map the bit at position @pos in @buf (of length @bits) to the | ||
521 | * ordinal of which set bit it is. If it is not set or if @pos | ||
522 | * is not a valid bit position, map to zero (0). | ||
523 | * | ||
524 | * If for example, just bits 4 through 7 are set in @buf, then @pos | ||
525 | * values 4 through 7 will get mapped to 0 through 3, respectively, | ||
526 | * and other @pos values will get mapped to 0. When @pos value 7 | ||
527 | * gets mapped to (returns) @ord value 3 in this example, that means | ||
528 | * that bit 7 is the 3rd (starting with 0th) set bit in @buf. | ||
529 | * | ||
530 | * The bit positions 0 through @bits are valid positions in @buf. | ||
531 | */ | ||
532 | static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) | ||
533 | { | ||
534 | int ord = 0; | ||
535 | |||
536 | if (pos >= 0 && pos < bits) { | ||
537 | int i; | ||
538 | |||
539 | for (i = find_first_bit(buf, bits); | ||
540 | i < pos; | ||
541 | i = find_next_bit(buf, bits, i + 1)) | ||
542 | ord++; | ||
543 | if (i > pos) | ||
544 | ord = 0; | ||
545 | } | ||
546 | return ord; | ||
547 | } | ||
548 | |||
549 | /** | ||
550 | * bitmap_ord_to_pos(buf, ord, bits) | ||
551 | * @buf: pointer to bitmap | ||
552 | * @ord: ordinal bit position (n-th set bit, n >= 0) | ||
553 | * @bits: number of valid bit positions in @buf | ||
554 | * | ||
555 | * Map the ordinal offset of bit @ord in @buf to its position in @buf. | ||
556 | * If @ord is not the ordinal offset of a set bit in @buf, map to zero (0). | ||
557 | * | ||
558 | * If for example, just bits 4 through 7 are set in @buf, then @ord | ||
559 | * values 0 through 3 will get mapped to 4 through 7, respectively, | ||
560 | * and all other @ord valuds will get mapped to 0. When @ord value 3 | ||
561 | * gets mapped to (returns) @pos value 7 in this example, that means | ||
562 | * that the 3rd set bit (starting with 0th) is at position 7 in @buf. | ||
563 | * | ||
564 | * The bit positions 0 through @bits are valid positions in @buf. | ||
565 | */ | ||
566 | static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits) | ||
567 | { | ||
568 | int pos = 0; | ||
569 | |||
570 | if (ord >= 0 && ord < bits) { | ||
571 | int i; | ||
572 | |||
573 | for (i = find_first_bit(buf, bits); | ||
574 | i < bits && ord > 0; | ||
575 | i = find_next_bit(buf, bits, i + 1)) | ||
576 | ord--; | ||
577 | if (i < bits && ord == 0) | ||
578 | pos = i; | ||
579 | } | ||
580 | |||
581 | return pos; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap | ||
586 | * @src: subset to be remapped | ||
587 | * @dst: remapped result | ||
588 | * @old: defines domain of map | ||
589 | * @new: defines range of map | ||
590 | * @bits: number of bits in each of these bitmaps | ||
591 | * | ||
592 | * Let @old and @new define a mapping of bit positions, such that | ||
593 | * whatever position is held by the n-th set bit in @old is mapped | ||
594 | * to the n-th set bit in @new. In the more general case, allowing | ||
595 | * for the possibility that the weight 'w' of @new is less than the | ||
596 | * weight of @old, map the position of the n-th set bit in @old to | ||
597 | * the position of the m-th set bit in @new, where m == n % w. | ||
598 | * | ||
599 | * If either of the @old and @new bitmaps are empty, or if@src and @dst | ||
600 | * point to the same location, then this routine does nothing. | ||
601 | * | ||
602 | * The positions of unset bits in @old are mapped to the position of | ||
603 | * the first set bit in @new. | ||
604 | * | ||
605 | * Apply the above specified mapping to @src, placing the result in | ||
606 | * @dst, clearing any bits previously set in @dst. | ||
607 | * | ||
608 | * The resulting value of @dst will have either the same weight as | ||
609 | * @src, or less weight in the general case that the mapping wasn't | ||
610 | * injective due to the weight of @new being less than that of @old. | ||
611 | * The resulting value of @dst will never have greater weight than | ||
612 | * that of @src, except perhaps in the case that one of the above | ||
613 | * conditions was not met and this routine just returned. | ||
614 | * | ||
615 | * For example, lets say that @old has bits 4 through 7 set, and | ||
616 | * @new has bits 12 through 15 set. This defines the mapping of bit | ||
617 | * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other | ||
618 | * bit positions to 12 (the first set bit in @new. So if say @src | ||
619 | * comes into this routine with bits 1, 5 and 7 set, then @dst should | ||
620 | * leave with bits 12, 13 and 15 set. | ||
621 | */ | ||
622 | void bitmap_remap(unsigned long *dst, const unsigned long *src, | ||
623 | const unsigned long *old, const unsigned long *new, | ||
624 | int bits) | ||
625 | { | ||
626 | int s; | ||
627 | |||
628 | if (bitmap_weight(old, bits) == 0) | ||
629 | return; | ||
630 | if (bitmap_weight(new, bits) == 0) | ||
631 | return; | ||
632 | if (dst == src) /* following doesn't handle inplace remaps */ | ||
633 | return; | ||
634 | |||
635 | bitmap_zero(dst, bits); | ||
636 | for (s = find_first_bit(src, bits); | ||
637 | s < bits; | ||
638 | s = find_next_bit(src, bits, s + 1)) { | ||
639 | int x = bitmap_pos_to_ord(old, s, bits); | ||
640 | int y = bitmap_ord_to_pos(new, x, bits); | ||
641 | set_bit(y, dst); | ||
642 | } | ||
643 | } | ||
644 | EXPORT_SYMBOL(bitmap_remap); | ||
645 | |||
646 | /** | ||
647 | * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit | ||
648 | * @oldbit - bit position to be mapped | ||
649 | * @old: defines domain of map | ||
650 | * @new: defines range of map | ||
651 | * @bits: number of bits in each of these bitmaps | ||
652 | * | ||
653 | * Let @old and @new define a mapping of bit positions, such that | ||
654 | * whatever position is held by the n-th set bit in @old is mapped | ||
655 | * to the n-th set bit in @new. In the more general case, allowing | ||
656 | * for the possibility that the weight 'w' of @new is less than the | ||
657 | * weight of @old, map the position of the n-th set bit in @old to | ||
658 | * the position of the m-th set bit in @new, where m == n % w. | ||
659 | * | ||
660 | * The positions of unset bits in @old are mapped to the position of | ||
661 | * the first set bit in @new. | ||
662 | * | ||
663 | * Apply the above specified mapping to bit position @oldbit, returning | ||
664 | * the new bit position. | ||
665 | * | ||
666 | * For example, lets say that @old has bits 4 through 7 set, and | ||
667 | * @new has bits 12 through 15 set. This defines the mapping of bit | ||
668 | * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other | ||
669 | * bit positions to 12 (the first set bit in @new. So if say @oldbit | ||
670 | * is 5, then this routine returns 13. | ||
671 | */ | ||
672 | int bitmap_bitremap(int oldbit, const unsigned long *old, | ||
673 | const unsigned long *new, int bits) | ||
674 | { | ||
675 | int x = bitmap_pos_to_ord(old, oldbit, bits); | ||
676 | return bitmap_ord_to_pos(new, x, bits); | ||
677 | } | ||
678 | EXPORT_SYMBOL(bitmap_bitremap); | ||
679 | |||
514 | /** | 680 | /** |
515 | * bitmap_find_free_region - find a contiguous aligned mem region | 681 | * bitmap_find_free_region - find a contiguous aligned mem region |
516 | * @bitmap: an array of unsigned longs corresponding to the bitmap | 682 | * @bitmap: an array of unsigned longs corresponding to the bitmap |