aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
authorPaul Jackson <pj@sgi.com>2006-01-08 04:01:46 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:13:42 -0500
commit96b7f34143c2c823a6a750fcb758fc66c44945d2 (patch)
treea17cadb13e4eeb555f32186579d5d174cf51796b /lib/bitmap.c
parent10cef6029502915bdb3cf0821d425cf9dc30c817 (diff)
[PATCH] cpuset: better bitmap remap defaults
Fix the default behaviour for the remap operators in bitmap, cpumask and nodemask. As previously submitted, the pair of masks <A, B> defined a map of the positions of the set bits in A to the corresponding bits in B. This is still true. The issue is how to map the other positions, corresponding to the unset (0) bits in A. As previously submitted, they were all mapped to the first set bit position in B, a constant map. When I tried to code per-vma mempolicy rebinding using these remap operators, I realized this was wrong. This patch changes the default to map all the unset bit positions in A to the same positions in B, the identity map. For example, if A has bits 4-7 set, and B has bits 9-12 set, then the map defined by the pair <A, B> maps each bit position in the first 32 bits as follows: 0 ==> 0 ... 3 ==> 3 4 ==> 9 ... 7 ==> 12 8 ==> 8 9 ==> 9 ... 31 ==> 31 This now corresponds to the typical behaviour desired when migrating pages and policies from one cpuset to another. The pages on nodes within the original cpuset, and the references in memory policies to nodes within the original cpuset, are migrated to the corresponding cpuset-relative nodes in the destination cpuset. Other pages and node references are left untouched. Signed-off-by: Paul Jackson <pj@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c89
1 files changed, 44 insertions, 45 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 23d3b1147fe9..48e708381d44 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -519,7 +519,7 @@ EXPORT_SYMBOL(bitmap_parselist);
519 * 519 *
520 * Map the bit at position @pos in @buf (of length @bits) to the 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 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). 522 * is not a valid bit position, map to -1.
523 * 523 *
524 * If for example, just bits 4 through 7 are set in @buf, then @pos 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, 525 * values 4 through 7 will get mapped to 0 through 3, respectively,
@@ -531,18 +531,19 @@ EXPORT_SYMBOL(bitmap_parselist);
531 */ 531 */
532static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) 532static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
533{ 533{
534 int ord = 0; 534 int i, ord;
535 535
536 if (pos >= 0 && pos < bits) { 536 if (pos < 0 || pos >= bits || !test_bit(pos, buf))
537 int i; 537 return -1;
538 538
539 for (i = find_first_bit(buf, bits); 539 i = find_first_bit(buf, bits);
540 i < pos; 540 ord = 0;
541 i = find_next_bit(buf, bits, i + 1)) 541 while (i < pos) {
542 ord++; 542 i = find_next_bit(buf, bits, i + 1);
543 if (i > pos) 543 ord++;
544 ord = 0;
545 } 544 }
545 BUG_ON(i != pos);
546
546 return ord; 547 return ord;
547} 548}
548 549
@@ -553,11 +554,12 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
553 * @bits: number of valid bit positions in @buf 554 * @bits: number of valid bit positions in @buf
554 * 555 *
555 * Map the ordinal offset of bit @ord in @buf to its position in @buf. 556 * 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 * Value of @ord should be in range 0 <= @ord < weight(buf), else
558 * results are undefined.
557 * 559 *
558 * If for example, just bits 4 through 7 are set in @buf, then @ord 560 * 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, 561 * 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 562 * and all other @ord values return undefined values. When @ord value 3
561 * gets mapped to (returns) @pos value 7 in this example, that means 563 * 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. 564 * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
563 * 565 *
@@ -583,8 +585,8 @@ static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
583 585
584/** 586/**
585 * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap 587 * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap
586 * @src: subset to be remapped
587 * @dst: remapped result 588 * @dst: remapped result
589 * @src: subset to be remapped
588 * @old: defines domain of map 590 * @old: defines domain of map
589 * @new: defines range of map 591 * @new: defines range of map
590 * @bits: number of bits in each of these bitmaps 592 * @bits: number of bits in each of these bitmaps
@@ -596,49 +598,42 @@ static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
596 * weight of @old, map the position of the n-th set bit in @old to 598 * 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. 599 * the position of the m-th set bit in @new, where m == n % w.
598 * 600 *
599 * If either of the @old and @new bitmaps are empty, or if@src and @dst 601 * If either of the @old and @new bitmaps are empty, or if @src and
600 * point to the same location, then this routine does nothing. 602 * @dst point to the same location, then this routine copies @src
603 * to @dst.
601 * 604 *
602 * The positions of unset bits in @old are mapped to the position of 605 * The positions of unset bits in @old are mapped to themselves
603 * the first set bit in @new. 606 * (the identify map).
604 * 607 *
605 * Apply the above specified mapping to @src, placing the result in 608 * Apply the above specified mapping to @src, placing the result in
606 * @dst, clearing any bits previously set in @dst. 609 * @dst, clearing any bits previously set in @dst.
607 * 610 *
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 611 * 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 612 * @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 613 * 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 614 * bit positions unchanged. So if say @src comes into this routine
619 * comes into this routine with bits 1, 5 and 7 set, then @dst should 615 * with bits 1, 5 and 7 set, then @dst should leave with bits 1,
620 * leave with bits 12, 13 and 15 set. 616 * 13 and 15 set.
621 */ 617 */
622void bitmap_remap(unsigned long *dst, const unsigned long *src, 618void bitmap_remap(unsigned long *dst, const unsigned long *src,
623 const unsigned long *old, const unsigned long *new, 619 const unsigned long *old, const unsigned long *new,
624 int bits) 620 int bits)
625{ 621{
626 int s; 622 int oldbit, w;
627 623
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 */ 624 if (dst == src) /* following doesn't handle inplace remaps */
633 return; 625 return;
634
635 bitmap_zero(dst, bits); 626 bitmap_zero(dst, bits);
636 for (s = find_first_bit(src, bits); 627
637 s < bits; 628 w = bitmap_weight(new, bits);
638 s = find_next_bit(src, bits, s + 1)) { 629 for (oldbit = find_first_bit(src, bits);
639 int x = bitmap_pos_to_ord(old, s, bits); 630 oldbit < bits;
640 int y = bitmap_ord_to_pos(new, x, bits); 631 oldbit = find_next_bit(src, bits, oldbit + 1)) {
641 set_bit(y, dst); 632 int n = bitmap_pos_to_ord(old, oldbit, bits);
633 if (n < 0 || w == 0)
634 set_bit(oldbit, dst); /* identity map */
635 else
636 set_bit(bitmap_ord_to_pos(new, n % w, bits), dst);
642 } 637 }
643} 638}
644EXPORT_SYMBOL(bitmap_remap); 639EXPORT_SYMBOL(bitmap_remap);
@@ -657,8 +652,8 @@ EXPORT_SYMBOL(bitmap_remap);
657 * weight of @old, map the position of the n-th set bit in @old to 652 * 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. 653 * the position of the m-th set bit in @new, where m == n % w.
659 * 654 *
660 * The positions of unset bits in @old are mapped to the position of 655 * The positions of unset bits in @old are mapped to themselves
661 * the first set bit in @new. 656 * (the identify map).
662 * 657 *
663 * Apply the above specified mapping to bit position @oldbit, returning 658 * Apply the above specified mapping to bit position @oldbit, returning
664 * the new bit position. 659 * the new bit position.
@@ -666,14 +661,18 @@ EXPORT_SYMBOL(bitmap_remap);
666 * For example, lets say that @old has bits 4 through 7 set, and 661 * 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 662 * @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 663 * 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 664 * bit positions unchanged. So if say @oldbit is 5, then this routine
670 * is 5, then this routine returns 13. 665 * returns 13.
671 */ 666 */
672int bitmap_bitremap(int oldbit, const unsigned long *old, 667int bitmap_bitremap(int oldbit, const unsigned long *old,
673 const unsigned long *new, int bits) 668 const unsigned long *new, int bits)
674{ 669{
675 int x = bitmap_pos_to_ord(old, oldbit, bits); 670 int w = bitmap_weight(new, bits);
676 return bitmap_ord_to_pos(new, x, bits); 671 int n = bitmap_pos_to_ord(old, oldbit, bits);
672 if (n < 0 || w == 0)
673 return oldbit;
674 else
675 return bitmap_ord_to_pos(new, n % w, bits);
677} 676}
678EXPORT_SYMBOL(bitmap_bitremap); 677EXPORT_SYMBOL(bitmap_bitremap);
679 678