find.c 1.9 KB

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