aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c166
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}
512EXPORT_SYMBOL(bitmap_parselist); 512EXPORT_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 */
532static 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 */
566static 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 */
622void 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}
644EXPORT_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 */
672int 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}
678EXPORT_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