aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c100
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}
272EXPORT_SYMBOL(__bitmap_weight); 272EXPORT_SYMBOL(__bitmap_weight);
273 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
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,
406EXPORT_SYMBOL(__bitmap_parse); 487EXPORT_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)
538EXPORT_SYMBOL(bitmap_parselist); 619EXPORT_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}
861EXPORT_SYMBOL(bitmap_fold); 937EXPORT_SYMBOL(bitmap_fold);