diff options
| -rw-r--r-- | include/linux/bitmap.h | 11 | ||||
| -rw-r--r-- | lib/bitmap.c | 81 | 
2 files changed, 92 insertions, 0 deletions
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 756d78b8c1c..daf8c480c78 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -42,6 +42,9 @@   * bitmap_empty(src, nbits)			Are all bits zero in *src?   * bitmap_full(src, nbits)			Are all bits set in *src?   * bitmap_weight(src, nbits)			Hamming Weight: number set bits + * bitmap_set(dst, pos, nbits)			Set specified bit area + * bitmap_clear(dst, pos, nbits)		Clear specified bit area + * bitmap_find_next_zero_area(buf, len, pos, n, mask)	Find bit free area   * bitmap_shift_right(dst, src, n, nbits)	*dst = *src >> n   * bitmap_shift_left(dst, src, n, nbits)	*dst = *src << n   * bitmap_remap(dst, src, old, new, nbits)	*dst = map(old, new)(src) @@ -108,6 +111,14 @@ extern int __bitmap_subset(const unsigned long *bitmap1,  			const unsigned long *bitmap2, int bits);  extern int __bitmap_weight(const unsigned long *bitmap, int bits); +extern void bitmap_set(unsigned long *map, int i, int len); +extern void bitmap_clear(unsigned long *map, int start, int nr); +extern unsigned long bitmap_find_next_zero_area(unsigned long *map, +					 unsigned long size, +					 unsigned long start, +					 unsigned int nr, +					 unsigned long align_mask); +  extern int bitmap_scnprintf(char *buf, unsigned int len,  			const unsigned long *src, int nbits);  extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user, diff --git a/lib/bitmap.c b/lib/bitmap.c index 702565821c9..11bf4975058 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -271,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)  }  EXPORT_SYMBOL(__bitmap_weight); +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) + +void bitmap_set(unsigned long *map, int start, int nr) +{ +	unsigned long *p = map + BIT_WORD(start); +	const int size = start + nr; +	int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); +	unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); + +	while (nr - bits_to_set >= 0) { +		*p |= mask_to_set; +		nr -= bits_to_set; +		bits_to_set = BITS_PER_LONG; +		mask_to_set = ~0UL; +		p++; +	} +	if (nr) { +		mask_to_set &= BITMAP_LAST_WORD_MASK(size); +		*p |= mask_to_set; +	} +} +EXPORT_SYMBOL(bitmap_set); + +void bitmap_clear(unsigned long *map, int start, int nr) +{ +	unsigned long *p = map + BIT_WORD(start); +	const int size = start + nr; +	int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); +	unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); + +	while (nr - bits_to_clear >= 0) { +		*p &= ~mask_to_clear; +		nr -= bits_to_clear; +		bits_to_clear = BITS_PER_LONG; +		mask_to_clear = ~0UL; +		p++; +	} +	if (nr) { +		mask_to_clear &= BITMAP_LAST_WORD_MASK(size); +		*p &= ~mask_to_clear; +	} +} +EXPORT_SYMBOL(bitmap_clear); + +/* + * bitmap_find_next_zero_area - find a contiguous aligned zero area + * @map: The address to base the search on + * @size: The bitmap size in bits + * @start: The bitnumber to start searching at + * @nr: The number of zeroed bits we're looking for + * @align_mask: Alignment mask for zero area + * + * The @align_mask should be one less than a power of 2; the effect is that + * the bit offset of all zero areas this function finds is multiples of that + * power of 2. A @align_mask of 0 means no alignment is required. + */ +unsigned long bitmap_find_next_zero_area(unsigned long *map, +					 unsigned long size, +					 unsigned long start, +					 unsigned int nr, +					 unsigned long align_mask) +{ +	unsigned long index, end, i; +again: +	index = find_next_zero_bit(map, size, start); + +	/* Align allocation */ +	index = __ALIGN_MASK(index, align_mask); + +	end = index + nr; +	if (end > size) +		return end; +	i = find_next_bit(map, end, index); +	if (i < end) { +		start = i + 1; +		goto again; +	} +	return index; +} +EXPORT_SYMBOL(bitmap_find_next_zero_area); +  /*   * Bitmap printing & parsing functions: first version by Bill Irwin,   * second version by Paul Jackson, third by Joe Korty.  |