aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c115
1 files changed, 97 insertions, 18 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 35a1f7ff414..741fae905ae 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -179,14 +179,16 @@ void __bitmap_shift_left(unsigned long *dst,
179} 179}
180EXPORT_SYMBOL(__bitmap_shift_left); 180EXPORT_SYMBOL(__bitmap_shift_left);
181 181
182void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, 182int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
183 const unsigned long *bitmap2, int bits) 183 const unsigned long *bitmap2, int bits)
184{ 184{
185 int k; 185 int k;
186 int nr = BITS_TO_LONGS(bits); 186 int nr = BITS_TO_LONGS(bits);
187 unsigned long result = 0;
187 188
188 for (k = 0; k < nr; k++) 189 for (k = 0; k < nr; k++)
189 dst[k] = bitmap1[k] & bitmap2[k]; 190 result |= (dst[k] = bitmap1[k] & bitmap2[k]);
191 return result != 0;
190} 192}
191EXPORT_SYMBOL(__bitmap_and); 193EXPORT_SYMBOL(__bitmap_and);
192 194
@@ -212,14 +214,16 @@ void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
212} 214}
213EXPORT_SYMBOL(__bitmap_xor); 215EXPORT_SYMBOL(__bitmap_xor);
214 216
215void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, 217int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
216 const unsigned long *bitmap2, int bits) 218 const unsigned long *bitmap2, int bits)
217{ 219{
218 int k; 220 int k;
219 int nr = BITS_TO_LONGS(bits); 221 int nr = BITS_TO_LONGS(bits);
222 unsigned long result = 0;
220 223
221 for (k = 0; k < nr; k++) 224 for (k = 0; k < nr; k++)
222 dst[k] = bitmap1[k] & ~bitmap2[k]; 225 result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
226 return result != 0;
223} 227}
224EXPORT_SYMBOL(__bitmap_andnot); 228EXPORT_SYMBOL(__bitmap_andnot);
225 229
@@ -267,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
267} 271}
268EXPORT_SYMBOL(__bitmap_weight); 272EXPORT_SYMBOL(__bitmap_weight);
269 273
274#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
275
276void bitmap_set(unsigned long *map, int start, int nr)
277{
278 unsigned long *p = map + BIT_WORD(start);
279 const int size = start + nr;
280 int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
281 unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
282
283 while (nr - bits_to_set >= 0) {
284 *p |= mask_to_set;
285 nr -= bits_to_set;
286 bits_to_set = BITS_PER_LONG;
287 mask_to_set = ~0UL;
288 p++;
289 }
290 if (nr) {
291 mask_to_set &= BITMAP_LAST_WORD_MASK(size);
292 *p |= mask_to_set;
293 }
294}
295EXPORT_SYMBOL(bitmap_set);
296
297void bitmap_clear(unsigned long *map, int start, int nr)
298{
299 unsigned long *p = map + BIT_WORD(start);
300 const int size = start + nr;
301 int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
302 unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
303
304 while (nr - bits_to_clear >= 0) {
305 *p &= ~mask_to_clear;
306 nr -= bits_to_clear;
307 bits_to_clear = BITS_PER_LONG;
308 mask_to_clear = ~0UL;
309 p++;
310 }
311 if (nr) {
312 mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
313 *p &= ~mask_to_clear;
314 }
315}
316EXPORT_SYMBOL(bitmap_clear);
317
318/*
319 * bitmap_find_next_zero_area - find a contiguous aligned zero area
320 * @map: The address to base the search on
321 * @size: The bitmap size in bits
322 * @start: The bitnumber to start searching at
323 * @nr: The number of zeroed bits we're looking for
324 * @align_mask: Alignment mask for zero area
325 *
326 * The @align_mask should be one less than a power of 2; the effect is that
327 * the bit offset of all zero areas this function finds is multiples of that
328 * power of 2. A @align_mask of 0 means no alignment is required.
329 */
330unsigned long bitmap_find_next_zero_area(unsigned long *map,
331 unsigned long size,
332 unsigned long start,
333 unsigned int nr,
334 unsigned long align_mask)
335{
336 unsigned long index, end, i;
337again:
338 index = find_next_zero_bit(map, size, start);
339
340 /* Align allocation */
341 index = __ALIGN_MASK(index, align_mask);
342
343 end = index + nr;
344 if (end > size)
345 return end;
346 i = find_next_bit(map, end, index);
347 if (i < end) {
348 start = i + 1;
349 goto again;
350 }
351 return index;
352}
353EXPORT_SYMBOL(bitmap_find_next_zero_area);
354
270/* 355/*
271 * Bitmap printing & parsing functions: first version by Bill Irwin, 356 * Bitmap printing & parsing functions: first version by Bill Irwin,
272 * second version by Paul Jackson, third by Joe Korty. 357 * second version by Paul Jackson, third by Joe Korty.
@@ -274,7 +359,6 @@ EXPORT_SYMBOL(__bitmap_weight);
274 359
275#define CHUNKSZ 32 360#define CHUNKSZ 32
276#define nbits_to_hold_value(val) fls(val) 361#define nbits_to_hold_value(val) fls(val)
277#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
278#define BASEDEC 10 /* fancier cpuset lists input in decimal */ 362#define BASEDEC 10 /* fancier cpuset lists input in decimal */
279 363
280/** 364/**
@@ -381,7 +465,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
381 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) 465 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
382 return -EOVERFLOW; 466 return -EOVERFLOW;
383 467
384 chunk = (chunk << 4) | unhex(c); 468 chunk = (chunk << 4) | hex_to_bin(c);
385 ndigits++; totaldigits++; 469 ndigits++; totaldigits++;
386 } 470 }
387 if (ndigits == 0) 471 if (ndigits == 0)
@@ -402,7 +486,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
402EXPORT_SYMBOL(__bitmap_parse); 486EXPORT_SYMBOL(__bitmap_parse);
403 487
404/** 488/**
405 * bitmap_parse_user() 489 * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap
406 * 490 *
407 * @ubuf: pointer to user buffer containing string. 491 * @ubuf: pointer to user buffer containing string.
408 * @ulen: buffer size in bytes. If string is smaller than this 492 * @ulen: buffer size in bytes. If string is smaller than this
@@ -534,7 +618,7 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
534EXPORT_SYMBOL(bitmap_parselist); 618EXPORT_SYMBOL(bitmap_parselist);
535 619
536/** 620/**
537 * bitmap_pos_to_ord(buf, pos, bits) 621 * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
538 * @buf: pointer to a bitmap 622 * @buf: pointer to a bitmap
539 * @pos: a bit position in @buf (0 <= @pos < @bits) 623 * @pos: a bit position in @buf (0 <= @pos < @bits)
540 * @bits: number of valid bit positions in @buf 624 * @bits: number of valid bit positions in @buf
@@ -570,7 +654,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
570} 654}
571 655
572/** 656/**
573 * bitmap_ord_to_pos(buf, ord, bits) 657 * bitmap_ord_to_pos - find position of n-th set bit in bitmap
574 * @buf: pointer to bitmap 658 * @buf: pointer to bitmap
575 * @ord: ordinal bit position (n-th set bit, n >= 0) 659 * @ord: ordinal bit position (n-th set bit, n >= 0)
576 * @bits: number of valid bit positions in @buf 660 * @bits: number of valid bit positions in @buf
@@ -648,10 +732,9 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src,
648 bitmap_zero(dst, bits); 732 bitmap_zero(dst, bits);
649 733
650 w = bitmap_weight(new, bits); 734 w = bitmap_weight(new, bits);
651 for (oldbit = find_first_bit(src, bits); 735 for_each_set_bit(oldbit, src, bits) {
652 oldbit < bits;
653 oldbit = find_next_bit(src, bits, oldbit + 1)) {
654 int n = bitmap_pos_to_ord(old, oldbit, bits); 736 int n = bitmap_pos_to_ord(old, oldbit, bits);
737
655 if (n < 0 || w == 0) 738 if (n < 0 || w == 0)
656 set_bit(oldbit, dst); /* identity map */ 739 set_bit(oldbit, dst); /* identity map */
657 else 740 else
@@ -818,9 +901,7 @@ void bitmap_onto(unsigned long *dst, const unsigned long *orig,
818 */ 901 */
819 902
820 m = 0; 903 m = 0;
821 for (n = find_first_bit(relmap, bits); 904 for_each_set_bit(n, relmap, bits) {
822 n < bits;
823 n = find_next_bit(relmap, bits, n + 1)) {
824 /* m == bitmap_pos_to_ord(relmap, n, bits) */ 905 /* m == bitmap_pos_to_ord(relmap, n, bits) */
825 if (test_bit(m, orig)) 906 if (test_bit(m, orig))
826 set_bit(n, dst); 907 set_bit(n, dst);
@@ -849,9 +930,7 @@ void bitmap_fold(unsigned long *dst, const unsigned long *orig,
849 return; 930 return;
850 bitmap_zero(dst, bits); 931 bitmap_zero(dst, bits);
851 932
852 for (oldbit = find_first_bit(orig, bits); 933 for_each_set_bit(oldbit, orig, bits)
853 oldbit < bits;
854 oldbit = find_next_bit(orig, bits, oldbit + 1))
855 set_bit(oldbit % sz, dst); 934 set_bit(oldbit % sz, dst);
856} 935}
857EXPORT_SYMBOL(bitmap_fold); 936EXPORT_SYMBOL(bitmap_fold);