aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c240
1 files changed, 60 insertions, 180 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 324ea9eab8c1..d456f4c15a9f 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -104,18 +104,18 @@ EXPORT_SYMBOL(__bitmap_complement);
104 * @dst : destination bitmap 104 * @dst : destination bitmap
105 * @src : source bitmap 105 * @src : source bitmap
106 * @shift : shift by this many bits 106 * @shift : shift by this many bits
107 * @bits : bitmap size, in bits 107 * @nbits : bitmap size, in bits
108 * 108 *
109 * Shifting right (dividing) means moving bits in the MS -> LS bit 109 * Shifting right (dividing) means moving bits in the MS -> LS bit
110 * direction. Zeros are fed into the vacated MS positions and the 110 * direction. Zeros are fed into the vacated MS positions and the
111 * LS bits shifted off the bottom are lost. 111 * LS bits shifted off the bottom are lost.
112 */ 112 */
113void __bitmap_shift_right(unsigned long *dst, 113void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
114 const unsigned long *src, int shift, int bits) 114 unsigned shift, unsigned nbits)
115{ 115{
116 int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG; 116 unsigned k, lim = BITS_TO_LONGS(nbits);
117 int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; 117 unsigned off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
118 unsigned long mask = (1UL << left) - 1; 118 unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);
119 for (k = 0; off + k < lim; ++k) { 119 for (k = 0; off + k < lim; ++k) {
120 unsigned long upper, lower; 120 unsigned long upper, lower;
121 121
@@ -127,17 +127,15 @@ void __bitmap_shift_right(unsigned long *dst,
127 upper = 0; 127 upper = 0;
128 else { 128 else {
129 upper = src[off + k + 1]; 129 upper = src[off + k + 1];
130 if (off + k + 1 == lim - 1 && left) 130 if (off + k + 1 == lim - 1)
131 upper &= mask; 131 upper &= mask;
132 upper <<= (BITS_PER_LONG - rem);
132 } 133 }
133 lower = src[off + k]; 134 lower = src[off + k];
134 if (left && off + k == lim - 1) 135 if (off + k == lim - 1)
135 lower &= mask; 136 lower &= mask;
136 dst[k] = lower >> rem; 137 lower >>= rem;
137 if (rem) 138 dst[k] = lower | upper;
138 dst[k] |= upper << (BITS_PER_LONG - rem);
139 if (left && k == lim - 1)
140 dst[k] &= mask;
141 } 139 }
142 if (off) 140 if (off)
143 memset(&dst[lim - off], 0, off*sizeof(unsigned long)); 141 memset(&dst[lim - off], 0, off*sizeof(unsigned long));
@@ -150,18 +148,19 @@ EXPORT_SYMBOL(__bitmap_shift_right);
150 * @dst : destination bitmap 148 * @dst : destination bitmap
151 * @src : source bitmap 149 * @src : source bitmap
152 * @shift : shift by this many bits 150 * @shift : shift by this many bits
153 * @bits : bitmap size, in bits 151 * @nbits : bitmap size, in bits
154 * 152 *
155 * Shifting left (multiplying) means moving bits in the LS -> MS 153 * Shifting left (multiplying) means moving bits in the LS -> MS
156 * direction. Zeros are fed into the vacated LS bit positions 154 * direction. Zeros are fed into the vacated LS bit positions
157 * and those MS bits shifted off the top are lost. 155 * and those MS bits shifted off the top are lost.
158 */ 156 */
159 157
160void __bitmap_shift_left(unsigned long *dst, 158void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
161 const unsigned long *src, int shift, int bits) 159 unsigned int shift, unsigned int nbits)
162{ 160{
163 int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG; 161 int k;
164 int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; 162 unsigned int lim = BITS_TO_LONGS(nbits);
163 unsigned int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
165 for (k = lim - off - 1; k >= 0; --k) { 164 for (k = lim - off - 1; k >= 0; --k) {
166 unsigned long upper, lower; 165 unsigned long upper, lower;
167 166
@@ -170,17 +169,11 @@ void __bitmap_shift_left(unsigned long *dst,
170 * word below and make them the bottom rem bits of result. 169 * word below and make them the bottom rem bits of result.
171 */ 170 */
172 if (rem && k > 0) 171 if (rem && k > 0)
173 lower = src[k - 1]; 172 lower = src[k - 1] >> (BITS_PER_LONG - rem);
174 else 173 else
175 lower = 0; 174 lower = 0;
176 upper = src[k]; 175 upper = src[k] << rem;
177 if (left && k == lim - 1) 176 dst[k + off] = lower | upper;
178 upper &= (1UL << left) - 1;
179 dst[k + off] = upper << rem;
180 if (rem)
181 dst[k + off] |= lower >> (BITS_PER_LONG - rem);
182 if (left && k + off == lim - 1)
183 dst[k + off] &= (1UL << left) - 1;
184 } 177 }
185 if (off) 178 if (off)
186 memset(dst, 0, off*sizeof(unsigned long)); 179 memset(dst, 0, off*sizeof(unsigned long));
@@ -377,45 +370,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
377#define BASEDEC 10 /* fancier cpuset lists input in decimal */ 370#define BASEDEC 10 /* fancier cpuset lists input in decimal */
378 371
379/** 372/**
380 * bitmap_scnprintf - convert bitmap to an ASCII hex string.
381 * @buf: byte buffer into which string is placed
382 * @buflen: reserved size of @buf, in bytes
383 * @maskp: pointer to bitmap to convert
384 * @nmaskbits: size of bitmap, in bits
385 *
386 * Exactly @nmaskbits bits are displayed. Hex digits are grouped into
387 * comma-separated sets of eight digits per set. Returns the number of
388 * characters which were written to *buf, excluding the trailing \0.
389 */
390int bitmap_scnprintf(char *buf, unsigned int buflen,
391 const unsigned long *maskp, int nmaskbits)
392{
393 int i, word, bit, len = 0;
394 unsigned long val;
395 const char *sep = "";
396 int chunksz;
397 u32 chunkmask;
398
399 chunksz = nmaskbits & (CHUNKSZ - 1);
400 if (chunksz == 0)
401 chunksz = CHUNKSZ;
402
403 i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
404 for (; i >= 0; i -= CHUNKSZ) {
405 chunkmask = ((1ULL << chunksz) - 1);
406 word = i / BITS_PER_LONG;
407 bit = i % BITS_PER_LONG;
408 val = (maskp[word] >> bit) & chunkmask;
409 len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
410 (chunksz+3)/4, val);
411 chunksz = CHUNKSZ;
412 sep = ",";
413 }
414 return len;
415}
416EXPORT_SYMBOL(bitmap_scnprintf);
417
418/**
419 * __bitmap_parse - convert an ASCII hex string into a bitmap. 373 * __bitmap_parse - convert an ASCII hex string into a bitmap.
420 * @buf: pointer to buffer containing string. 374 * @buf: pointer to buffer containing string.
421 * @buflen: buffer size in bytes. If string is smaller than this 375 * @buflen: buffer size in bytes. If string is smaller than this
@@ -528,65 +482,6 @@ int bitmap_parse_user(const char __user *ubuf,
528} 482}
529EXPORT_SYMBOL(bitmap_parse_user); 483EXPORT_SYMBOL(bitmap_parse_user);
530 484
531/*
532 * bscnl_emit(buf, buflen, rbot, rtop, bp)
533 *
534 * Helper routine for bitmap_scnlistprintf(). Write decimal number
535 * or range to buf, suppressing output past buf+buflen, with optional
536 * comma-prefix. Return len of what was written to *buf, excluding the
537 * trailing \0.
538 */
539static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
540{
541 if (len > 0)
542 len += scnprintf(buf + len, buflen - len, ",");
543 if (rbot == rtop)
544 len += scnprintf(buf + len, buflen - len, "%d", rbot);
545 else
546 len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
547 return len;
548}
549
550/**
551 * bitmap_scnlistprintf - convert bitmap to list format ASCII string
552 * @buf: byte buffer into which string is placed
553 * @buflen: reserved size of @buf, in bytes
554 * @maskp: pointer to bitmap to convert
555 * @nmaskbits: size of bitmap, in bits
556 *
557 * Output format is a comma-separated list of decimal numbers and
558 * ranges. Consecutively set bits are shown as two hyphen-separated
559 * decimal numbers, the smallest and largest bit numbers set in
560 * the range. Output format is compatible with the format
561 * accepted as input by bitmap_parselist().
562 *
563 * The return value is the number of characters which were written to *buf
564 * excluding the trailing '\0', as per ISO C99's scnprintf.
565 */
566int bitmap_scnlistprintf(char *buf, unsigned int buflen,
567 const unsigned long *maskp, int nmaskbits)
568{
569 int len = 0;
570 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
571 int cur, rbot, rtop;
572
573 if (buflen == 0)
574 return 0;
575 buf[0] = 0;
576
577 rbot = cur = find_first_bit(maskp, nmaskbits);
578 while (cur < nmaskbits) {
579 rtop = cur;
580 cur = find_next_bit(maskp, nmaskbits, cur+1);
581 if (cur >= nmaskbits || cur > rtop + 1) {
582 len = bscnl_emit(buf, buflen, rbot, rtop, len);
583 rbot = cur;
584 }
585 }
586 return len;
587}
588EXPORT_SYMBOL(bitmap_scnlistprintf);
589
590/** 485/**
591 * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string 486 * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string
592 * @list: indicates whether the bitmap must be list 487 * @list: indicates whether the bitmap must be list
@@ -605,8 +500,8 @@ int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
605 int n = 0; 500 int n = 0;
606 501
607 if (len > 1) { 502 if (len > 1) {
608 n = list ? bitmap_scnlistprintf(buf, len, maskp, nmaskbits) : 503 n = list ? scnprintf(buf, len, "%*pbl", nmaskbits, maskp) :
609 bitmap_scnprintf(buf, len, maskp, nmaskbits); 504 scnprintf(buf, len, "%*pb", nmaskbits, maskp);
610 buf[n++] = '\n'; 505 buf[n++] = '\n';
611 buf[n] = '\0'; 506 buf[n] = '\0';
612 } 507 }
@@ -744,10 +639,10 @@ EXPORT_SYMBOL(bitmap_parselist_user);
744/** 639/**
745 * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap 640 * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
746 * @buf: pointer to a bitmap 641 * @buf: pointer to a bitmap
747 * @pos: a bit position in @buf (0 <= @pos < @bits) 642 * @pos: a bit position in @buf (0 <= @pos < @nbits)
748 * @bits: number of valid bit positions in @buf 643 * @nbits: number of valid bit positions in @buf
749 * 644 *
750 * Map the bit at position @pos in @buf (of length @bits) to the 645 * Map the bit at position @pos in @buf (of length @nbits) to the
751 * ordinal of which set bit it is. If it is not set or if @pos 646 * ordinal of which set bit it is. If it is not set or if @pos
752 * is not a valid bit position, map to -1. 647 * is not a valid bit position, map to -1.
753 * 648 *
@@ -759,56 +654,40 @@ EXPORT_SYMBOL(bitmap_parselist_user);
759 * 654 *
760 * The bit positions 0 through @bits are valid positions in @buf. 655 * The bit positions 0 through @bits are valid positions in @buf.
761 */ 656 */
762static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) 657static int bitmap_pos_to_ord(const unsigned long *buf, unsigned int pos, unsigned int nbits)
763{ 658{
764 int i, ord; 659 if (pos >= nbits || !test_bit(pos, buf))
765
766 if (pos < 0 || pos >= bits || !test_bit(pos, buf))
767 return -1; 660 return -1;
768 661
769 i = find_first_bit(buf, bits); 662 return __bitmap_weight(buf, pos);
770 ord = 0;
771 while (i < pos) {
772 i = find_next_bit(buf, bits, i + 1);
773 ord++;
774 }
775 BUG_ON(i != pos);
776
777 return ord;
778} 663}
779 664
780/** 665/**
781 * bitmap_ord_to_pos - find position of n-th set bit in bitmap 666 * bitmap_ord_to_pos - find position of n-th set bit in bitmap
782 * @buf: pointer to bitmap 667 * @buf: pointer to bitmap
783 * @ord: ordinal bit position (n-th set bit, n >= 0) 668 * @ord: ordinal bit position (n-th set bit, n >= 0)
784 * @bits: number of valid bit positions in @buf 669 * @nbits: number of valid bit positions in @buf
785 * 670 *
786 * Map the ordinal offset of bit @ord in @buf to its position in @buf. 671 * Map the ordinal offset of bit @ord in @buf to its position in @buf.
787 * Value of @ord should be in range 0 <= @ord < weight(buf), else 672 * Value of @ord should be in range 0 <= @ord < weight(buf). If @ord
788 * results are undefined. 673 * >= weight(buf), returns @nbits.
789 * 674 *
790 * If for example, just bits 4 through 7 are set in @buf, then @ord 675 * If for example, just bits 4 through 7 are set in @buf, then @ord
791 * values 0 through 3 will get mapped to 4 through 7, respectively, 676 * values 0 through 3 will get mapped to 4 through 7, respectively,
792 * and all other @ord values return undefined values. When @ord value 3 677 * and all other @ord values returns @nbits. When @ord value 3
793 * gets mapped to (returns) @pos value 7 in this example, that means 678 * gets mapped to (returns) @pos value 7 in this example, that means
794 * that the 3rd set bit (starting with 0th) is at position 7 in @buf. 679 * that the 3rd set bit (starting with 0th) is at position 7 in @buf.
795 * 680 *
796 * The bit positions 0 through @bits are valid positions in @buf. 681 * The bit positions 0 through @nbits-1 are valid positions in @buf.
797 */ 682 */
798int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits) 683unsigned int bitmap_ord_to_pos(const unsigned long *buf, unsigned int ord, unsigned int nbits)
799{ 684{
800 int pos = 0; 685 unsigned int pos;
801
802 if (ord >= 0 && ord < bits) {
803 int i;
804 686
805 for (i = find_first_bit(buf, bits); 687 for (pos = find_first_bit(buf, nbits);
806 i < bits && ord > 0; 688 pos < nbits && ord;
807 i = find_next_bit(buf, bits, i + 1)) 689 pos = find_next_bit(buf, nbits, pos + 1))
808 ord--; 690 ord--;
809 if (i < bits && ord == 0)
810 pos = i;
811 }
812 691
813 return pos; 692 return pos;
814} 693}
@@ -819,7 +698,7 @@ int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
819 * @src: subset to be remapped 698 * @src: subset to be remapped
820 * @old: defines domain of map 699 * @old: defines domain of map
821 * @new: defines range of map 700 * @new: defines range of map
822 * @bits: number of bits in each of these bitmaps 701 * @nbits: number of bits in each of these bitmaps
823 * 702 *
824 * Let @old and @new define a mapping of bit positions, such that 703 * Let @old and @new define a mapping of bit positions, such that
825 * whatever position is held by the n-th set bit in @old is mapped 704 * whatever position is held by the n-th set bit in @old is mapped
@@ -847,22 +726,22 @@ int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
847 */ 726 */
848void bitmap_remap(unsigned long *dst, const unsigned long *src, 727void bitmap_remap(unsigned long *dst, const unsigned long *src,
849 const unsigned long *old, const unsigned long *new, 728 const unsigned long *old, const unsigned long *new,
850 int bits) 729 unsigned int nbits)
851{ 730{
852 int oldbit, w; 731 unsigned int oldbit, w;
853 732
854 if (dst == src) /* following doesn't handle inplace remaps */ 733 if (dst == src) /* following doesn't handle inplace remaps */
855 return; 734 return;
856 bitmap_zero(dst, bits); 735 bitmap_zero(dst, nbits);
857 736
858 w = bitmap_weight(new, bits); 737 w = bitmap_weight(new, nbits);
859 for_each_set_bit(oldbit, src, bits) { 738 for_each_set_bit(oldbit, src, nbits) {
860 int n = bitmap_pos_to_ord(old, oldbit, bits); 739 int n = bitmap_pos_to_ord(old, oldbit, nbits);
861 740
862 if (n < 0 || w == 0) 741 if (n < 0 || w == 0)
863 set_bit(oldbit, dst); /* identity map */ 742 set_bit(oldbit, dst); /* identity map */
864 else 743 else
865 set_bit(bitmap_ord_to_pos(new, n % w, bits), dst); 744 set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst);
866 } 745 }
867} 746}
868EXPORT_SYMBOL(bitmap_remap); 747EXPORT_SYMBOL(bitmap_remap);
@@ -1006,9 +885,9 @@ EXPORT_SYMBOL(bitmap_bitremap);
1006 * All bits in @dst not set by the above rule are cleared. 885 * All bits in @dst not set by the above rule are cleared.
1007 */ 886 */
1008void bitmap_onto(unsigned long *dst, const unsigned long *orig, 887void bitmap_onto(unsigned long *dst, const unsigned long *orig,
1009 const unsigned long *relmap, int bits) 888 const unsigned long *relmap, unsigned int bits)
1010{ 889{
1011 int n, m; /* same meaning as in above comment */ 890 unsigned int n, m; /* same meaning as in above comment */
1012 891
1013 if (dst == orig) /* following doesn't handle inplace mappings */ 892 if (dst == orig) /* following doesn't handle inplace mappings */
1014 return; 893 return;
@@ -1039,22 +918,22 @@ EXPORT_SYMBOL(bitmap_onto);
1039 * @dst: resulting smaller bitmap 918 * @dst: resulting smaller bitmap
1040 * @orig: original larger bitmap 919 * @orig: original larger bitmap
1041 * @sz: specified size 920 * @sz: specified size
1042 * @bits: number of bits in each of these bitmaps 921 * @nbits: number of bits in each of these bitmaps
1043 * 922 *
1044 * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst. 923 * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst.
1045 * Clear all other bits in @dst. See further the comment and 924 * Clear all other bits in @dst. See further the comment and
1046 * Example [2] for bitmap_onto() for why and how to use this. 925 * Example [2] for bitmap_onto() for why and how to use this.
1047 */ 926 */
1048void bitmap_fold(unsigned long *dst, const unsigned long *orig, 927void bitmap_fold(unsigned long *dst, const unsigned long *orig,
1049 int sz, int bits) 928 unsigned int sz, unsigned int nbits)
1050{ 929{
1051 int oldbit; 930 unsigned int oldbit;
1052 931
1053 if (dst == orig) /* following doesn't handle inplace mappings */ 932 if (dst == orig) /* following doesn't handle inplace mappings */
1054 return; 933 return;
1055 bitmap_zero(dst, bits); 934 bitmap_zero(dst, nbits);
1056 935
1057 for_each_set_bit(oldbit, orig, bits) 936 for_each_set_bit(oldbit, orig, nbits)
1058 set_bit(oldbit % sz, dst); 937 set_bit(oldbit % sz, dst);
1059} 938}
1060EXPORT_SYMBOL(bitmap_fold); 939EXPORT_SYMBOL(bitmap_fold);
@@ -1207,16 +1086,17 @@ EXPORT_SYMBOL(bitmap_allocate_region);
1207 * 1086 *
1208 * Require nbits % BITS_PER_LONG == 0. 1087 * Require nbits % BITS_PER_LONG == 0.
1209 */ 1088 */
1210void bitmap_copy_le(void *dst, const unsigned long *src, int nbits) 1089#ifdef __BIG_ENDIAN
1090void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits)
1211{ 1091{
1212 unsigned long *d = dst; 1092 unsigned int i;
1213 int i;
1214 1093
1215 for (i = 0; i < nbits/BITS_PER_LONG; i++) { 1094 for (i = 0; i < nbits/BITS_PER_LONG; i++) {
1216 if (BITS_PER_LONG == 64) 1095 if (BITS_PER_LONG == 64)
1217 d[i] = cpu_to_le64(src[i]); 1096 dst[i] = cpu_to_le64(src[i]);
1218 else 1097 else
1219 d[i] = cpu_to_le32(src[i]); 1098 dst[i] = cpu_to_le32(src[i]);
1220 } 1099 }
1221} 1100}
1222EXPORT_SYMBOL(bitmap_copy_le); 1101EXPORT_SYMBOL(bitmap_copy_le);
1102#endif