find_next_bit.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. #include <asm/byteorder.h>
  15. #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
  16. #ifdef CONFIG_GENERIC_FIND_NEXT_BIT
  17. #ifndef find_next_bit
  18. /*
  19. * Find the next set bit in a memory region.
  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. #endif
  59. #ifndef find_next_zero_bit
  60. /*
  61. * This implementation of find_{first,next}_zero_bit was stolen from
  62. * Linus' asm-alpha/bitops.h.
  63. */
  64. unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
  65. unsigned long offset)
  66. {
  67. const unsigned long *p = addr + BITOP_WORD(offset);
  68. unsigned long result = offset & ~(BITS_PER_LONG-1);
  69. unsigned long tmp;
  70. if (offset >= size)
  71. return size;
  72. size -= result;
  73. offset %= BITS_PER_LONG;
  74. if (offset) {
  75. tmp = *(p++);
  76. tmp |= ~0UL >> (BITS_PER_LONG - offset);
  77. if (size < BITS_PER_LONG)
  78. goto found_first;
  79. if (~tmp)
  80. goto found_middle;
  81. size -= BITS_PER_LONG;
  82. result += BITS_PER_LONG;
  83. }
  84. while (size & ~(BITS_PER_LONG-1)) {
  85. if (~(tmp = *(p++)))
  86. goto found_middle;
  87. result += BITS_PER_LONG;
  88. size -= BITS_PER_LONG;
  89. }
  90. if (!size)
  91. return result;
  92. tmp = *p;
  93. found_first:
  94. tmp |= ~0UL << size;
  95. if (tmp == ~0UL) /* Are any bits zero? */
  96. return result + size; /* Nope. */
  97. found_middle:
  98. return result + ffz(tmp);
  99. }
  100. EXPORT_SYMBOL(find_next_zero_bit);
  101. #endif
  102. #endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
  103. #ifdef CONFIG_GENERIC_FIND_FIRST_BIT
  104. #ifndef find_first_bit
  105. /*
  106. * Find the first set bit in a memory region.
  107. */
  108. unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
  109. {
  110. const unsigned long *p = addr;
  111. unsigned long result = 0;
  112. unsigned long tmp;
  113. while (size & ~(BITS_PER_LONG-1)) {
  114. if ((tmp = *(p++)))
  115. goto found;
  116. result += BITS_PER_LONG;
  117. size -= BITS_PER_LONG;
  118. }
  119. if (!size)
  120. return result;
  121. tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
  122. if (tmp == 0UL) /* Are any bits set? */
  123. return result + size; /* Nope. */
  124. found:
  125. return result + __ffs(tmp);
  126. }
  127. EXPORT_SYMBOL(find_first_bit);
  128. #endif
  129. #ifndef find_first_zero_bit
  130. /*
  131. * Find the first cleared bit in a memory region.
  132. */
  133. unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
  134. {
  135. const unsigned long *p = addr;
  136. unsigned long result = 0;
  137. unsigned long tmp;
  138. while (size & ~(BITS_PER_LONG-1)) {
  139. if (~(tmp = *(p++)))
  140. goto found;
  141. result += BITS_PER_LONG;
  142. size -= BITS_PER_LONG;
  143. }
  144. if (!size)
  145. return result;
  146. tmp = (*p) | (~0UL << size);
  147. if (tmp == ~0UL) /* Are any bits zero? */
  148. return result + size; /* Nope. */
  149. found:
  150. return result + ffz(tmp);
  151. }
  152. EXPORT_SYMBOL(find_first_zero_bit);
  153. #endif
  154. #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
  155. #ifdef __BIG_ENDIAN
  156. #ifdef CONFIG_GENERIC_FIND_BIT_LE
  157. /* include/linux/byteorder does not support "unsigned long" type */
  158. static inline unsigned long ext2_swabp(const unsigned long * x)
  159. {
  160. #if BITS_PER_LONG == 64
  161. return (unsigned long) __swab64p((u64 *) x);
  162. #elif BITS_PER_LONG == 32
  163. return (unsigned long) __swab32p((u32 *) x);
  164. #else
  165. #error BITS_PER_LONG not defined
  166. #endif
  167. }
  168. /* include/linux/byteorder doesn't support "unsigned long" type */
  169. static inline unsigned long ext2_swab(const unsigned long y)
  170. {
  171. #if BITS_PER_LONG == 64
  172. return (unsigned long) __swab64((u64) y);
  173. #elif BITS_PER_LONG == 32
  174. return (unsigned long) __swab32((u32) y);
  175. #else
  176. #error BITS_PER_LONG not defined
  177. #endif
  178. }
  179. #ifndef find_next_zero_bit_le
  180. unsigned long find_next_zero_bit_le(const void *addr, unsigned
  181. long size, unsigned long offset)
  182. {
  183. const unsigned long *p = addr;
  184. unsigned long result = offset & ~(BITS_PER_LONG - 1);
  185. unsigned long tmp;
  186. if (offset >= size)
  187. return size;
  188. p += BITOP_WORD(offset);
  189. size -= result;
  190. offset &= (BITS_PER_LONG - 1UL);
  191. if (offset) {
  192. tmp = ext2_swabp(p++);
  193. tmp |= (~0UL >> (BITS_PER_LONG - offset));
  194. if (size < BITS_PER_LONG)
  195. goto found_first;
  196. if (~tmp)
  197. goto found_middle;
  198. size -= BITS_PER_LONG;
  199. result += BITS_PER_LONG;
  200. }
  201. while (size & ~(BITS_PER_LONG - 1)) {
  202. if (~(tmp = *(p++)))
  203. goto found_middle_swap;
  204. result += BITS_PER_LONG;
  205. size -= BITS_PER_LONG;
  206. }
  207. if (!size)
  208. return result;
  209. tmp = ext2_swabp(p);
  210. found_first:
  211. tmp |= ~0UL << size;
  212. if (tmp == ~0UL) /* Are any bits zero? */
  213. return result + size; /* Nope. Skip ffz */
  214. found_middle:
  215. return result + ffz(tmp);
  216. found_middle_swap:
  217. return result + ffz(ext2_swab(tmp));
  218. }
  219. EXPORT_SYMBOL(find_next_zero_bit_le);
  220. #endif
  221. #ifndef find_next_bit_le
  222. unsigned long find_next_bit_le(const void *addr, unsigned
  223. long size, unsigned long offset)
  224. {
  225. const unsigned long *p = addr;
  226. unsigned long result = offset & ~(BITS_PER_LONG - 1);
  227. unsigned long tmp;
  228. if (offset >= size)
  229. return size;
  230. p += BITOP_WORD(offset);
  231. size -= result;
  232. offset &= (BITS_PER_LONG - 1UL);
  233. if (offset) {
  234. tmp = ext2_swabp(p++);
  235. tmp &= (~0UL << offset);
  236. if (size < BITS_PER_LONG)
  237. goto found_first;
  238. if (tmp)
  239. goto found_middle;
  240. size -= BITS_PER_LONG;
  241. result += BITS_PER_LONG;
  242. }
  243. while (size & ~(BITS_PER_LONG - 1)) {
  244. tmp = *(p++);
  245. if (tmp)
  246. goto found_middle_swap;
  247. result += BITS_PER_LONG;
  248. size -= BITS_PER_LONG;
  249. }
  250. if (!size)
  251. return result;
  252. tmp = ext2_swabp(p);
  253. found_first:
  254. tmp &= (~0UL >> (BITS_PER_LONG - size));
  255. if (tmp == 0UL) /* Are any bits set? */
  256. return result + size; /* Nope. */
  257. found_middle:
  258. return result + __ffs(tmp);
  259. found_middle_swap:
  260. return result + __ffs(ext2_swab(tmp));
  261. }
  262. EXPORT_SYMBOL(find_next_bit_le);
  263. #endif
  264. #endif /* CONFIG_GENERIC_FIND_BIT_LE */
  265. #endif /* __BIG_ENDIAN */