diff options
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r-- | lib/bitmap.c | 100 |
1 files changed, 88 insertions, 12 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index 702565821c99..ffb78c916ccd 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
@@ -271,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) | |||
271 | } | 271 | } |
272 | EXPORT_SYMBOL(__bitmap_weight); | 272 | EXPORT_SYMBOL(__bitmap_weight); |
273 | 273 | ||
274 | #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) | ||
275 | |||
276 | void 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 | } | ||
295 | EXPORT_SYMBOL(bitmap_set); | ||
296 | |||
297 | void 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 | } | ||
316 | EXPORT_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 | */ | ||
330 | unsigned 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; | ||
337 | again: | ||
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 | } | ||
353 | EXPORT_SYMBOL(bitmap_find_next_zero_area); | ||
354 | |||
274 | /* | 355 | /* |
275 | * Bitmap printing & parsing functions: first version by Bill Irwin, | 356 | * Bitmap printing & parsing functions: first version by Bill Irwin, |
276 | * second version by Paul Jackson, third by Joe Korty. | 357 | * second version by Paul Jackson, third by Joe Korty. |
@@ -406,7 +487,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen, | |||
406 | EXPORT_SYMBOL(__bitmap_parse); | 487 | EXPORT_SYMBOL(__bitmap_parse); |
407 | 488 | ||
408 | /** | 489 | /** |
409 | * bitmap_parse_user() | 490 | * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap |
410 | * | 491 | * |
411 | * @ubuf: pointer to user buffer containing string. | 492 | * @ubuf: pointer to user buffer containing string. |
412 | * @ulen: buffer size in bytes. If string is smaller than this | 493 | * @ulen: buffer size in bytes. If string is smaller than this |
@@ -538,7 +619,7 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits) | |||
538 | EXPORT_SYMBOL(bitmap_parselist); | 619 | EXPORT_SYMBOL(bitmap_parselist); |
539 | 620 | ||
540 | /** | 621 | /** |
541 | * bitmap_pos_to_ord(buf, pos, bits) | 622 | * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap |
542 | * @buf: pointer to a bitmap | 623 | * @buf: pointer to a bitmap |
543 | * @pos: a bit position in @buf (0 <= @pos < @bits) | 624 | * @pos: a bit position in @buf (0 <= @pos < @bits) |
544 | * @bits: number of valid bit positions in @buf | 625 | * @bits: number of valid bit positions in @buf |
@@ -574,7 +655,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) | |||
574 | } | 655 | } |
575 | 656 | ||
576 | /** | 657 | /** |
577 | * bitmap_ord_to_pos(buf, ord, bits) | 658 | * bitmap_ord_to_pos - find position of n-th set bit in bitmap |
578 | * @buf: pointer to bitmap | 659 | * @buf: pointer to bitmap |
579 | * @ord: ordinal bit position (n-th set bit, n >= 0) | 660 | * @ord: ordinal bit position (n-th set bit, n >= 0) |
580 | * @bits: number of valid bit positions in @buf | 661 | * @bits: number of valid bit positions in @buf |
@@ -652,10 +733,9 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src, | |||
652 | bitmap_zero(dst, bits); | 733 | bitmap_zero(dst, bits); |
653 | 734 | ||
654 | w = bitmap_weight(new, bits); | 735 | w = bitmap_weight(new, bits); |
655 | for (oldbit = find_first_bit(src, bits); | 736 | for_each_set_bit(oldbit, src, bits) { |
656 | oldbit < bits; | ||
657 | oldbit = find_next_bit(src, bits, oldbit + 1)) { | ||
658 | int n = bitmap_pos_to_ord(old, oldbit, bits); | 737 | int n = bitmap_pos_to_ord(old, oldbit, bits); |
738 | |||
659 | if (n < 0 || w == 0) | 739 | if (n < 0 || w == 0) |
660 | set_bit(oldbit, dst); /* identity map */ | 740 | set_bit(oldbit, dst); /* identity map */ |
661 | else | 741 | else |
@@ -822,9 +902,7 @@ void bitmap_onto(unsigned long *dst, const unsigned long *orig, | |||
822 | */ | 902 | */ |
823 | 903 | ||
824 | m = 0; | 904 | m = 0; |
825 | for (n = find_first_bit(relmap, bits); | 905 | for_each_set_bit(n, relmap, bits) { |
826 | n < bits; | ||
827 | n = find_next_bit(relmap, bits, n + 1)) { | ||
828 | /* m == bitmap_pos_to_ord(relmap, n, bits) */ | 906 | /* m == bitmap_pos_to_ord(relmap, n, bits) */ |
829 | if (test_bit(m, orig)) | 907 | if (test_bit(m, orig)) |
830 | set_bit(n, dst); | 908 | set_bit(n, dst); |
@@ -853,9 +931,7 @@ void bitmap_fold(unsigned long *dst, const unsigned long *orig, | |||
853 | return; | 931 | return; |
854 | bitmap_zero(dst, bits); | 932 | bitmap_zero(dst, bits); |
855 | 933 | ||
856 | for (oldbit = find_first_bit(orig, bits); | 934 | for_each_set_bit(oldbit, orig, bits) |
857 | oldbit < bits; | ||
858 | oldbit = find_next_bit(orig, bits, oldbit + 1)) | ||
859 | set_bit(oldbit % sz, dst); | 935 | set_bit(oldbit % sz, dst); |
860 | } | 936 | } |
861 | EXPORT_SYMBOL(bitmap_fold); | 937 | EXPORT_SYMBOL(bitmap_fold); |