diff options
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r-- | lib/bitmap.c | 115 |
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 | } |
180 | EXPORT_SYMBOL(__bitmap_shift_left); | 180 | EXPORT_SYMBOL(__bitmap_shift_left); |
181 | 181 | ||
182 | void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, | 182 | int __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 | } |
191 | EXPORT_SYMBOL(__bitmap_and); | 193 | EXPORT_SYMBOL(__bitmap_and); |
192 | 194 | ||
@@ -212,14 +214,16 @@ void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1, | |||
212 | } | 214 | } |
213 | EXPORT_SYMBOL(__bitmap_xor); | 215 | EXPORT_SYMBOL(__bitmap_xor); |
214 | 216 | ||
215 | void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, | 217 | int __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 | } |
224 | EXPORT_SYMBOL(__bitmap_andnot); | 228 | EXPORT_SYMBOL(__bitmap_andnot); |
225 | 229 | ||
@@ -267,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits) | |||
267 | } | 271 | } |
268 | EXPORT_SYMBOL(__bitmap_weight); | 272 | EXPORT_SYMBOL(__bitmap_weight); |
269 | 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 | |||
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, | |||
402 | EXPORT_SYMBOL(__bitmap_parse); | 486 | EXPORT_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) | |||
534 | EXPORT_SYMBOL(bitmap_parselist); | 618 | EXPORT_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 | } |
857 | EXPORT_SYMBOL(bitmap_fold); | 936 | EXPORT_SYMBOL(bitmap_fold); |