find_next_bit.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* find_next_bit.c: fallback find next bit implementation
  2. *
  3. * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/bitops.h>
  12. #include <linux/module.h>
  13. #include <asm/types.h>
  14. #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
  15. /**
  16. * find_next_bit - find the next set bit in a memory region
  17. * @addr: The address to base the search on
  18. * @offset: The bitnumber to start searching at
  19. * @size: The maximum size to search
  20. */
  21. unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
  22. unsigned long offset)
  23. {
  24. const unsigned long *p = addr + BITOP_WORD(offset);
  25. unsigned long result = offset & ~(BITS_PER_LONG-1);
  26. unsigned long tmp;
  27. if (offset >= size)
  28. return size;
  29. size -= result;
  30. offset %= BITS_PER_LONG;
  31. if (offset) {
  32. tmp = *(p++);
  33. tmp &= (~0UL << offset);
  34. if (size < BITS_PER_LONG)
  35. goto found_first;
  36. if (tmp)
  37. goto found_middle;
  38. size -= BITS_PER_LONG;
  39. result += BITS_PER_LONG;
  40. }
  41. while (size & ~(BITS_PER_LONG-1)) {
  42. if ((tmp = *(p++)))
  43. goto found_middle;
  44. result += BITS_PER_LONG;
  45. size -= BITS_PER_LONG;
  46. }
  47. if (!size)
  48. return result;
  49. tmp = *p;
  50. found_first:
  51. tmp &= (~0UL >> (BITS_PER_LONG - size));
  52. if (tmp == 0UL) /* Are any bits set? */
  53. return result + size; /* Nope. */
  54. found_middle:
  55. return result + __ffs(tmp);
  56. }
  57. EXPORT_SYMBOL(find_next_bit);
  58. /*
  59. * This implementation of find_{first,next}_zero_bit was stolen from
  60. * Linus' asm-alpha/bitops.h.
  61. */
  62. unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
  63. unsigned long offset)
  64. {
  65. const unsigned long *p = addr + BITOP_WORD(offset);
  66. unsigned long result = offset & ~(BITS_PER_LONG-1);
  67. unsigned long tmp;
  68. if (offset >= size)
  69. return size;
  70. size -= result;
  71. offset %= BITS_PER_LONG;
  72. if (offset) {
  73. tmp = *(p++);
  74. tmp |= ~0UL >> (BITS_PER_LONG - offset);
  75. if (size < BITS_PER_LONG)
  76. goto found_first;
  77. if (~tmp)
  78. goto found_middle;
  79. size -= BITS_PER_LONG;
  80. result += BITS_PER_LONG;
  81. }
  82. while (size & ~(BITS_PER_LONG-1)) {
  83. if (~(tmp = *(p++)))
  84. goto found_middle;
  85. result += BITS_PER_LONG;
  86. size -= BITS_PER_LONG;
  87. }
  88. if (!size)
  89. return result;
  90. tmp = *p;
  91. found_first:
  92. tmp |= ~0UL << size;
  93. if (tmp == ~0UL) /* Are any bits zero? */
  94. return result + size; /* Nope. */
  95. found_middle:
  96. return result + ffz(tmp);
  97. }
  98. EXPORT_SYMBOL(find_next_zero_bit);