diff options
Diffstat (limited to 'lib/bitmap.c')
| -rw-r--r-- | lib/bitmap.c | 240 | 
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);   *   @dst : destination bitmap   *   @src : source bitmap   *   @shift : shift by this many bits - *   @bits : bitmap size, in bits + *   @nbits : bitmap size, in bits   *   * Shifting right (dividing) means moving bits in the MS -> LS bit   * direction.  Zeros are fed into the vacated MS positions and the   * LS bits shifted off the bottom are lost.   */ -void __bitmap_shift_right(unsigned long *dst, -			const unsigned long *src, int shift, int bits) +void __bitmap_shift_right(unsigned long *dst, const unsigned long *src, +			unsigned shift, unsigned nbits)  { -	int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG; -	int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; -	unsigned long mask = (1UL << left) - 1; +	unsigned k, lim = BITS_TO_LONGS(nbits); +	unsigned off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; +	unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);  	for (k = 0; off + k < lim; ++k) {  		unsigned long upper, lower; @@ -127,17 +127,15 @@ void __bitmap_shift_right(unsigned long *dst,  			upper = 0;  		else {  			upper = src[off + k + 1]; -			if (off + k + 1 == lim - 1 && left) +			if (off + k + 1 == lim - 1)  				upper &= mask; +			upper <<= (BITS_PER_LONG - rem);  		}  		lower = src[off + k]; -		if (left && off + k == lim - 1) +		if (off + k == lim - 1)  			lower &= mask; -		dst[k] = lower >> rem; -		if (rem) -			dst[k] |= upper << (BITS_PER_LONG - rem); -		if (left && k == lim - 1) -			dst[k] &= mask; +		lower >>= rem; +		dst[k] = lower | upper;  	}  	if (off)  		memset(&dst[lim - off], 0, off*sizeof(unsigned long)); @@ -150,18 +148,19 @@ EXPORT_SYMBOL(__bitmap_shift_right);   *   @dst : destination bitmap   *   @src : source bitmap   *   @shift : shift by this many bits - *   @bits : bitmap size, in bits + *   @nbits : bitmap size, in bits   *   * Shifting left (multiplying) means moving bits in the LS -> MS   * direction.  Zeros are fed into the vacated LS bit positions   * and those MS bits shifted off the top are lost.   */ -void __bitmap_shift_left(unsigned long *dst, -			const unsigned long *src, int shift, int bits) +void __bitmap_shift_left(unsigned long *dst, const unsigned long *src, +			unsigned int shift, unsigned int nbits)  { -	int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG; -	int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG; +	int k; +	unsigned int lim = BITS_TO_LONGS(nbits); +	unsigned int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;  	for (k = lim - off - 1; k >= 0; --k) {  		unsigned long upper, lower; @@ -170,17 +169,11 @@ void __bitmap_shift_left(unsigned long *dst,  		 * word below and make them the bottom rem bits of result.  		 */  		if (rem && k > 0) -			lower = src[k - 1]; +			lower = src[k - 1] >> (BITS_PER_LONG - rem);  		else  			lower = 0; -		upper = src[k]; -		if (left && k == lim - 1) -			upper &= (1UL << left) - 1; -		dst[k + off] = upper << rem; -		if (rem) -			dst[k + off] |= lower >> (BITS_PER_LONG - rem); -		if (left && k + off == lim - 1) -			dst[k + off] &= (1UL << left) - 1; +		upper = src[k] << rem; +		dst[k + off] = lower | upper;  	}  	if (off)  		memset(dst, 0, off*sizeof(unsigned long)); @@ -377,45 +370,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);  #define BASEDEC 10		/* fancier cpuset lists input in decimal */  /** - * bitmap_scnprintf - convert bitmap to an ASCII hex string. - * @buf: byte buffer into which string is placed - * @buflen: reserved size of @buf, in bytes - * @maskp: pointer to bitmap to convert - * @nmaskbits: size of bitmap, in bits - * - * Exactly @nmaskbits bits are displayed.  Hex digits are grouped into - * comma-separated sets of eight digits per set.  Returns the number of - * characters which were written to *buf, excluding the trailing \0. - */ -int bitmap_scnprintf(char *buf, unsigned int buflen, -	const unsigned long *maskp, int nmaskbits) -{ -	int i, word, bit, len = 0; -	unsigned long val; -	const char *sep = ""; -	int chunksz; -	u32 chunkmask; - -	chunksz = nmaskbits & (CHUNKSZ - 1); -	if (chunksz == 0) -		chunksz = CHUNKSZ; - -	i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ; -	for (; i >= 0; i -= CHUNKSZ) { -		chunkmask = ((1ULL << chunksz) - 1); -		word = i / BITS_PER_LONG; -		bit = i % BITS_PER_LONG; -		val = (maskp[word] >> bit) & chunkmask; -		len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep, -			(chunksz+3)/4, val); -		chunksz = CHUNKSZ; -		sep = ","; -	} -	return len; -} -EXPORT_SYMBOL(bitmap_scnprintf); - -/**   * __bitmap_parse - convert an ASCII hex string into a bitmap.   * @buf: pointer to buffer containing string.   * @buflen: buffer size in bytes.  If string is smaller than this @@ -528,65 +482,6 @@ int bitmap_parse_user(const char __user *ubuf,  }  EXPORT_SYMBOL(bitmap_parse_user); -/* - * bscnl_emit(buf, buflen, rbot, rtop, bp) - * - * Helper routine for bitmap_scnlistprintf().  Write decimal number - * or range to buf, suppressing output past buf+buflen, with optional - * comma-prefix.  Return len of what was written to *buf, excluding the - * trailing \0. - */ -static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len) -{ -	if (len > 0) -		len += scnprintf(buf + len, buflen - len, ","); -	if (rbot == rtop) -		len += scnprintf(buf + len, buflen - len, "%d", rbot); -	else -		len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop); -	return len; -} - -/** - * bitmap_scnlistprintf - convert bitmap to list format ASCII string - * @buf: byte buffer into which string is placed - * @buflen: reserved size of @buf, in bytes - * @maskp: pointer to bitmap to convert - * @nmaskbits: size of bitmap, in bits - * - * Output format is a comma-separated list of decimal numbers and - * ranges.  Consecutively set bits are shown as two hyphen-separated - * decimal numbers, the smallest and largest bit numbers set in - * the range.  Output format is compatible with the format - * accepted as input by bitmap_parselist(). - * - * The return value is the number of characters which were written to *buf - * excluding the trailing '\0', as per ISO C99's scnprintf. - */ -int bitmap_scnlistprintf(char *buf, unsigned int buflen, -	const unsigned long *maskp, int nmaskbits) -{ -	int len = 0; -	/* current bit is 'cur', most recently seen range is [rbot, rtop] */ -	int cur, rbot, rtop; - -	if (buflen == 0) -		return 0; -	buf[0] = 0; - -	rbot = cur = find_first_bit(maskp, nmaskbits); -	while (cur < nmaskbits) { -		rtop = cur; -		cur = find_next_bit(maskp, nmaskbits, cur+1); -		if (cur >= nmaskbits || cur > rtop + 1) { -			len = bscnl_emit(buf, buflen, rbot, rtop, len); -			rbot = cur; -		} -	} -	return len; -} -EXPORT_SYMBOL(bitmap_scnlistprintf); -  /**   * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string   * @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,  	int n = 0;  	if (len > 1) { -		n = list ? bitmap_scnlistprintf(buf, len, maskp, nmaskbits) : -			   bitmap_scnprintf(buf, len, maskp, nmaskbits); +		n = list ? scnprintf(buf, len, "%*pbl", nmaskbits, maskp) : +			   scnprintf(buf, len, "%*pb", nmaskbits, maskp);  		buf[n++] = '\n';  		buf[n] = '\0';  	} @@ -744,10 +639,10 @@ EXPORT_SYMBOL(bitmap_parselist_user);  /**   * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap   *	@buf: pointer to a bitmap - *	@pos: a bit position in @buf (0 <= @pos < @bits) - *	@bits: number of valid bit positions in @buf + *	@pos: a bit position in @buf (0 <= @pos < @nbits) + *	@nbits: number of valid bit positions in @buf   * - * Map the bit at position @pos in @buf (of length @bits) to the + * Map the bit at position @pos in @buf (of length @nbits) to the   * ordinal of which set bit it is.  If it is not set or if @pos   * is not a valid bit position, map to -1.   * @@ -759,56 +654,40 @@ EXPORT_SYMBOL(bitmap_parselist_user);   *   * The bit positions 0 through @bits are valid positions in @buf.   */ -static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) +static int bitmap_pos_to_ord(const unsigned long *buf, unsigned int pos, unsigned int nbits)  { -	int i, ord; - -	if (pos < 0 || pos >= bits || !test_bit(pos, buf)) +	if (pos >= nbits || !test_bit(pos, buf))  		return -1; -	i = find_first_bit(buf, bits); -	ord = 0; -	while (i < pos) { -		i = find_next_bit(buf, bits, i + 1); -	     	ord++; -	} -	BUG_ON(i != pos); - -	return ord; +	return __bitmap_weight(buf, pos);  }  /**   * bitmap_ord_to_pos - find position of n-th set bit in bitmap   *	@buf: pointer to bitmap   *	@ord: ordinal bit position (n-th set bit, n >= 0) - *	@bits: number of valid bit positions in @buf + *	@nbits: number of valid bit positions in @buf   *   * Map the ordinal offset of bit @ord in @buf to its position in @buf. - * Value of @ord should be in range 0 <= @ord < weight(buf), else - * results are undefined. + * Value of @ord should be in range 0 <= @ord < weight(buf). If @ord + * >= weight(buf), returns @nbits.   *   * If for example, just bits 4 through 7 are set in @buf, then @ord   * values 0 through 3 will get mapped to 4 through 7, respectively, - * and all other @ord values return undefined values.  When @ord value 3 + * and all other @ord values returns @nbits.  When @ord value 3   * gets mapped to (returns) @pos value 7 in this example, that means   * that the 3rd set bit (starting with 0th) is at position 7 in @buf.   * - * The bit positions 0 through @bits are valid positions in @buf. + * The bit positions 0 through @nbits-1 are valid positions in @buf.   */ -int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits) +unsigned int bitmap_ord_to_pos(const unsigned long *buf, unsigned int ord, unsigned int nbits)  { -	int pos = 0; - -	if (ord >= 0 && ord < bits) { -		int i; +	unsigned int pos; -		for (i = find_first_bit(buf, bits); -		     i < bits && ord > 0; -		     i = find_next_bit(buf, bits, i + 1)) -	     		ord--; -		if (i < bits && ord == 0) -			pos = i; -	} +	for (pos = find_first_bit(buf, nbits); +	     pos < nbits && ord; +	     pos = find_next_bit(buf, nbits, pos + 1)) +		ord--;  	return pos;  } @@ -819,7 +698,7 @@ int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)   *	@src: subset to be remapped   *	@old: defines domain of map   *	@new: defines range of map - *	@bits: number of bits in each of these bitmaps + *	@nbits: number of bits in each of these bitmaps   *   * Let @old and @new define a mapping of bit positions, such that   * 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)   */  void bitmap_remap(unsigned long *dst, const unsigned long *src,  		const unsigned long *old, const unsigned long *new, -		int bits) +		unsigned int nbits)  { -	int oldbit, w; +	unsigned int oldbit, w;  	if (dst == src)		/* following doesn't handle inplace remaps */  		return; -	bitmap_zero(dst, bits); +	bitmap_zero(dst, nbits); -	w = bitmap_weight(new, bits); -	for_each_set_bit(oldbit, src, bits) { -	     	int n = bitmap_pos_to_ord(old, oldbit, bits); +	w = bitmap_weight(new, nbits); +	for_each_set_bit(oldbit, src, nbits) { +		int n = bitmap_pos_to_ord(old, oldbit, nbits);  		if (n < 0 || w == 0)  			set_bit(oldbit, dst);	/* identity map */  		else -			set_bit(bitmap_ord_to_pos(new, n % w, bits), dst); +			set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst);  	}  }  EXPORT_SYMBOL(bitmap_remap); @@ -1006,9 +885,9 @@ EXPORT_SYMBOL(bitmap_bitremap);   * All bits in @dst not set by the above rule are cleared.   */  void bitmap_onto(unsigned long *dst, const unsigned long *orig, -			const unsigned long *relmap, int bits) +			const unsigned long *relmap, unsigned int bits)  { -	int n, m;       	/* same meaning as in above comment */ +	unsigned int n, m;	/* same meaning as in above comment */  	if (dst == orig)	/* following doesn't handle inplace mappings */  		return; @@ -1039,22 +918,22 @@ EXPORT_SYMBOL(bitmap_onto);   *	@dst: resulting smaller bitmap   *	@orig: original larger bitmap   *	@sz: specified size - *	@bits: number of bits in each of these bitmaps + *	@nbits: number of bits in each of these bitmaps   *   * For each bit oldbit in @orig, set bit oldbit mod @sz in @dst.   * Clear all other bits in @dst.  See further the comment and   * Example [2] for bitmap_onto() for why and how to use this.   */  void bitmap_fold(unsigned long *dst, const unsigned long *orig, -			int sz, int bits) +			unsigned int sz, unsigned int nbits)  { -	int oldbit; +	unsigned int oldbit;  	if (dst == orig)	/* following doesn't handle inplace mappings */  		return; -	bitmap_zero(dst, bits); +	bitmap_zero(dst, nbits); -	for_each_set_bit(oldbit, orig, bits) +	for_each_set_bit(oldbit, orig, nbits)  		set_bit(oldbit % sz, dst);  }  EXPORT_SYMBOL(bitmap_fold); @@ -1207,16 +1086,17 @@ EXPORT_SYMBOL(bitmap_allocate_region);   *   * Require nbits % BITS_PER_LONG == 0.   */ -void bitmap_copy_le(void *dst, const unsigned long *src, int nbits) +#ifdef __BIG_ENDIAN +void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits)  { -	unsigned long *d = dst; -	int i; +	unsigned int i;  	for (i = 0; i < nbits/BITS_PER_LONG; i++) {  		if (BITS_PER_LONG == 64) -			d[i] = cpu_to_le64(src[i]); +			dst[i] = cpu_to_le64(src[i]);  		else -			d[i] = cpu_to_le32(src[i]); +			dst[i] = cpu_to_le32(src[i]);  	}  }  EXPORT_SYMBOL(bitmap_copy_le); +#endif |