bitop.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #include <linux/compiler.h>
  2. #include <linux/types.h>
  3. #include <asm/intrinsics.h>
  4. #include <linux/module.h>
  5. #include <linux/bitops.h>
  6. /*
  7. * Find next zero bit in a bitmap reasonably efficiently..
  8. */
  9. int __find_next_zero_bit (const void *addr, unsigned long size, unsigned long offset)
  10. {
  11. unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  12. unsigned long result = offset & ~63UL;
  13. unsigned long tmp;
  14. if (offset >= size)
  15. return size;
  16. size -= result;
  17. offset &= 63UL;
  18. if (offset) {
  19. tmp = *(p++);
  20. tmp |= ~0UL >> (64-offset);
  21. if (size < 64)
  22. goto found_first;
  23. if (~tmp)
  24. goto found_middle;
  25. size -= 64;
  26. result += 64;
  27. }
  28. while (size & ~63UL) {
  29. if (~(tmp = *(p++)))
  30. goto found_middle;
  31. result += 64;
  32. size -= 64;
  33. }
  34. if (!size)
  35. return result;
  36. tmp = *p;
  37. found_first:
  38. tmp |= ~0UL << size;
  39. if (tmp == ~0UL) /* any bits zero? */
  40. return result + size; /* nope */
  41. found_middle:
  42. return result + ffz(tmp);
  43. }
  44. EXPORT_SYMBOL(__find_next_zero_bit);
  45. /*
  46. * Find next bit in a bitmap reasonably efficiently..
  47. */
  48. int __find_next_bit(const void *addr, unsigned long size, unsigned long offset)
  49. {
  50. unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  51. unsigned long result = offset & ~63UL;
  52. unsigned long tmp;
  53. if (offset >= size)
  54. return size;
  55. size -= result;
  56. offset &= 63UL;
  57. if (offset) {
  58. tmp = *(p++);
  59. tmp &= ~0UL << offset;
  60. if (size < 64)
  61. goto found_first;
  62. if (tmp)
  63. goto found_middle;
  64. size -= 64;
  65. result += 64;
  66. }
  67. while (size & ~63UL) {
  68. if ((tmp = *(p++)))
  69. goto found_middle;
  70. result += 64;
  71. size -= 64;
  72. }
  73. if (!size)
  74. return result;
  75. tmp = *p;
  76. found_first:
  77. tmp &= ~0UL >> (64-size);
  78. if (tmp == 0UL) /* Are any bits set? */
  79. return result + size; /* Nope. */
  80. found_middle:
  81. return result + __ffs(tmp);
  82. }
  83. EXPORT_SYMBOL(__find_next_bit);