aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c182
1 files changed, 113 insertions, 69 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 48e708381d44..ed2ae3b0cd06 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -253,33 +253,18 @@ int __bitmap_subset(const unsigned long *bitmap1,
253} 253}
254EXPORT_SYMBOL(__bitmap_subset); 254EXPORT_SYMBOL(__bitmap_subset);
255 255
256#if BITS_PER_LONG == 32
257int __bitmap_weight(const unsigned long *bitmap, int bits) 256int __bitmap_weight(const unsigned long *bitmap, int bits)
258{ 257{
259 int k, w = 0, lim = bits/BITS_PER_LONG; 258 int k, w = 0, lim = bits/BITS_PER_LONG;
260 259
261 for (k = 0; k < lim; k++) 260 for (k = 0; k < lim; k++)
262 w += hweight32(bitmap[k]); 261 w += hweight_long(bitmap[k]);
263 262
264 if (bits % BITS_PER_LONG) 263 if (bits % BITS_PER_LONG)
265 w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); 264 w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
266 265
267 return w; 266 return w;
268} 267}
269#else
270int __bitmap_weight(const unsigned long *bitmap, int bits)
271{
272 int k, w = 0, lim = bits/BITS_PER_LONG;
273
274 for (k = 0; k < lim; k++)
275 w += hweight64(bitmap[k]);
276
277 if (bits % BITS_PER_LONG)
278 w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
279
280 return w;
281}
282#endif
283EXPORT_SYMBOL(__bitmap_weight); 268EXPORT_SYMBOL(__bitmap_weight);
284 269
285/* 270/*
@@ -676,84 +661,143 @@ int bitmap_bitremap(int oldbit, const unsigned long *old,
676} 661}
677EXPORT_SYMBOL(bitmap_bitremap); 662EXPORT_SYMBOL(bitmap_bitremap);
678 663
679/** 664/*
680 * bitmap_find_free_region - find a contiguous aligned mem region 665 * Common code for bitmap_*_region() routines.
681 * @bitmap: an array of unsigned longs corresponding to the bitmap 666 * bitmap: array of unsigned longs corresponding to the bitmap
682 * @bits: number of bits in the bitmap 667 * pos: the beginning of the region
683 * @order: region size to find (size is actually 1<<order) 668 * order: region size (log base 2 of number of bits)
669 * reg_op: operation(s) to perform on that region of bitmap
684 * 670 *
685 * This is used to allocate a memory region from a bitmap. The idea is 671 * Can set, verify and/or release a region of bits in a bitmap,
686 * that the region has to be 1<<order sized and 1<<order aligned (this 672 * depending on which combination of REG_OP_* flag bits is set.
687 * makes the search algorithm much faster).
688 * 673 *
689 * The region is marked as set bits in the bitmap if a free one is 674 * A region of a bitmap is a sequence of bits in the bitmap, of
690 * found. 675 * some size '1 << order' (a power of two), aligned to that same
676 * '1 << order' power of two.
691 * 677 *
692 * Returns either beginning of region or negative error 678 * Returns 1 if REG_OP_ISFREE succeeds (region is all zero bits).
679 * Returns 0 in all other cases and reg_ops.
693 */ 680 */
694int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
695{
696 unsigned long mask;
697 int pages = 1 << order;
698 int i;
699 681
700 if(pages > BITS_PER_LONG) 682enum {
701 return -EINVAL; 683 REG_OP_ISFREE, /* true if region is all zero bits */
684 REG_OP_ALLOC, /* set all bits in region */
685 REG_OP_RELEASE, /* clear all bits in region */
686};
702 687
703 /* make a mask of the order */ 688static int __reg_op(unsigned long *bitmap, int pos, int order, int reg_op)
704 mask = (1ul << (pages - 1)); 689{
690 int nbits_reg; /* number of bits in region */
691 int index; /* index first long of region in bitmap */
692 int offset; /* bit offset region in bitmap[index] */
693 int nlongs_reg; /* num longs spanned by region in bitmap */
694 int nbitsinlong; /* num bits of region in each spanned long */
695 unsigned long mask; /* bitmask for one long of region */
696 int i; /* scans bitmap by longs */
697 int ret = 0; /* return value */
698
699 /*
700 * Either nlongs_reg == 1 (for small orders that fit in one long)
701 * or (offset == 0 && mask == ~0UL) (for larger multiword orders.)
702 */
703 nbits_reg = 1 << order;
704 index = pos / BITS_PER_LONG;
705 offset = pos - (index * BITS_PER_LONG);
706 nlongs_reg = BITS_TO_LONGS(nbits_reg);
707 nbitsinlong = min(nbits_reg, BITS_PER_LONG);
708
709 /*
710 * Can't do "mask = (1UL << nbitsinlong) - 1", as that
711 * overflows if nbitsinlong == BITS_PER_LONG.
712 */
713 mask = (1UL << (nbitsinlong - 1));
705 mask += mask - 1; 714 mask += mask - 1;
715 mask <<= offset;
706 716
707 /* run up the bitmap pages bits at a time */ 717 switch (reg_op) {
708 for (i = 0; i < bits; i += pages) { 718 case REG_OP_ISFREE:
709 int index = i/BITS_PER_LONG; 719 for (i = 0; i < nlongs_reg; i++) {
710 int offset = i - (index * BITS_PER_LONG); 720 if (bitmap[index + i] & mask)
711 if((bitmap[index] & (mask << offset)) == 0) { 721 goto done;
712 /* set region in bimap */
713 bitmap[index] |= (mask << offset);
714 return i;
715 } 722 }
723 ret = 1; /* all bits in region free (zero) */
724 break;
725
726 case REG_OP_ALLOC:
727 for (i = 0; i < nlongs_reg; i++)
728 bitmap[index + i] |= mask;
729 break;
730
731 case REG_OP_RELEASE:
732 for (i = 0; i < nlongs_reg; i++)
733 bitmap[index + i] &= ~mask;
734 break;
716 } 735 }
717 return -ENOMEM; 736done:
737 return ret;
738}
739
740/**
741 * bitmap_find_free_region - find a contiguous aligned mem region
742 * @bitmap: array of unsigned longs corresponding to the bitmap
743 * @bits: number of bits in the bitmap
744 * @order: region size (log base 2 of number of bits) to find
745 *
746 * Find a region of free (zero) bits in a @bitmap of @bits bits and
747 * allocate them (set them to one). Only consider regions of length
748 * a power (@order) of two, aligned to that power of two, which
749 * makes the search algorithm much faster.
750 *
751 * Return the bit offset in bitmap of the allocated region,
752 * or -errno on failure.
753 */
754int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
755{
756 int pos; /* scans bitmap by regions of size order */
757
758 for (pos = 0; pos < bits; pos += (1 << order))
759 if (__reg_op(bitmap, pos, order, REG_OP_ISFREE))
760 break;
761 if (pos == bits)
762 return -ENOMEM;
763 __reg_op(bitmap, pos, order, REG_OP_ALLOC);
764 return pos;
718} 765}
719EXPORT_SYMBOL(bitmap_find_free_region); 766EXPORT_SYMBOL(bitmap_find_free_region);
720 767
721/** 768/**
722 * bitmap_release_region - release allocated bitmap region 769 * bitmap_release_region - release allocated bitmap region
723 * @bitmap: a pointer to the bitmap 770 * @bitmap: array of unsigned longs corresponding to the bitmap
724 * @pos: the beginning of the region 771 * @pos: beginning of bit region to release
725 * @order: the order of the bits to release (number is 1<<order) 772 * @order: region size (log base 2 of number of bits) to release
726 * 773 *
727 * This is the complement to __bitmap_find_free_region and releases 774 * This is the complement to __bitmap_find_free_region and releases
728 * the found region (by clearing it in the bitmap). 775 * the found region (by clearing it in the bitmap).
776 *
777 * No return value.
729 */ 778 */
730void bitmap_release_region(unsigned long *bitmap, int pos, int order) 779void bitmap_release_region(unsigned long *bitmap, int pos, int order)
731{ 780{
732 int pages = 1 << order; 781 __reg_op(bitmap, pos, order, REG_OP_RELEASE);
733 unsigned long mask = (1ul << (pages - 1));
734 int index = pos/BITS_PER_LONG;
735 int offset = pos - (index * BITS_PER_LONG);
736 mask += mask - 1;
737 bitmap[index] &= ~(mask << offset);
738} 782}
739EXPORT_SYMBOL(bitmap_release_region); 783EXPORT_SYMBOL(bitmap_release_region);
740 784
785/**
786 * bitmap_allocate_region - allocate bitmap region
787 * @bitmap: array of unsigned longs corresponding to the bitmap
788 * @pos: beginning of bit region to allocate
789 * @order: region size (log base 2 of number of bits) to allocate
790 *
791 * Allocate (set bits in) a specified region of a bitmap.
792 *
793 * Return 0 on success, or -EBUSY if specified region wasn't
794 * free (not all bits were zero).
795 */
741int bitmap_allocate_region(unsigned long *bitmap, int pos, int order) 796int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
742{ 797{
743 int pages = 1 << order; 798 if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
744 unsigned long mask = (1ul << (pages - 1));
745 int index = pos/BITS_PER_LONG;
746 int offset = pos - (index * BITS_PER_LONG);
747
748 /* We don't do regions of pages > BITS_PER_LONG. The
749 * algorithm would be a simple look for multiple zeros in the
750 * array, but there's no driver today that needs this. If you
751 * trip this BUG(), you get to code it... */
752 BUG_ON(pages > BITS_PER_LONG);
753 mask += mask - 1;
754 if (bitmap[index] & (mask << offset))
755 return -EBUSY; 799 return -EBUSY;
756 bitmap[index] |= (mask << offset); 800 __reg_op(bitmap, pos, order, REG_OP_ALLOC);
757 return 0; 801 return 0;
758} 802}
759EXPORT_SYMBOL(bitmap_allocate_region); 803EXPORT_SYMBOL(bitmap_allocate_region);