find.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /*
  2. * MSB0 numbered special bitops handling.
  3. *
  4. * The bits are numbered:
  5. * |0..............63|64............127|128...........191|192...........255|
  6. *
  7. * The reason for this bit numbering is the fact that the hardware sets bits
  8. * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
  9. * from the 'wrong end'.
  10. */
  11. #include <linux/compiler.h>
  12. #include <linux/bitops.h>
  13. #include <linux/export.h>
  14. unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
  15. {
  16. const unsigned long *p = addr;
  17. unsigned long result = 0;
  18. unsigned long tmp;
  19. while (size & ~(BITS_PER_LONG - 1)) {
  20. if ((tmp = *(p++)))
  21. goto found;
  22. result += BITS_PER_LONG;
  23. size -= BITS_PER_LONG;
  24. }
  25. if (!size)
  26. return result;
  27. tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
  28. if (!tmp) /* Are any bits set? */
  29. return result + size; /* Nope. */
  30. found:
  31. return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
  32. }
  33. EXPORT_SYMBOL(find_first_bit_inv);
  34. unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
  35. unsigned long offset)
  36. {
  37. const unsigned long *p = addr + (offset / BITS_PER_LONG);
  38. unsigned long result = offset & ~(BITS_PER_LONG - 1);
  39. unsigned long tmp;
  40. if (offset >= size)
  41. return size;
  42. size -= result;
  43. offset %= BITS_PER_LONG;
  44. if (offset) {
  45. tmp = *(p++);
  46. tmp &= (~0UL >> offset);
  47. if (size < BITS_PER_LONG)
  48. goto found_first;
  49. if (tmp)
  50. goto found_middle;
  51. size -= BITS_PER_LONG;
  52. result += BITS_PER_LONG;
  53. }
  54. while (size & ~(BITS_PER_LONG-1)) {
  55. if ((tmp = *(p++)))
  56. goto found_middle;
  57. result += BITS_PER_LONG;
  58. size -= BITS_PER_LONG;
  59. }
  60. if (!size)
  61. return result;
  62. tmp = *p;
  63. found_first:
  64. tmp &= (~0UL << (BITS_PER_LONG - size));
  65. if (!tmp) /* Are any bits set? */
  66. return result + size; /* Nope. */
  67. found_middle:
  68. return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
  69. }
  70. EXPORT_SYMBOL(find_next_bit_inv);