1 /* find_next_bit.c: fallback find next bit implementation
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
7 * size and improve performance, 2015.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
15 #include <linux/bitops.h>
16 #include <linux/export.h>
17 #include <linux/kernel.h>
19 #if !defined(find_next_bit) || !defined(find_next_zero_bit)
22 * This is a common helper function for find_next_bit and
23 * find_next_zero_bit. The difference is the "invert" argument, which
24 * is XORed with each fetched word before searching it for one bits.
26 static unsigned long _find_next_bit(const unsigned long *addr,
27 unsigned long nbits, unsigned long start, unsigned long invert)
31 if (!nbits || start >= nbits)
34 tmp = addr[start / BITS_PER_LONG] ^ invert;
36 /* Handle 1st word. */
37 tmp &= BITMAP_FIRST_WORD_MASK(start);
38 start = round_down(start, BITS_PER_LONG);
41 start += BITS_PER_LONG;
45 tmp = addr[start / BITS_PER_LONG] ^ invert;
48 return min(start + __ffs(tmp), nbits);
54 * Find the next set bit in a memory region.
56 unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
59 return _find_next_bit(addr, size, offset, 0UL);
61 EXPORT_SYMBOL(find_next_bit);
64 #ifndef find_next_zero_bit
65 unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
68 return _find_next_bit(addr, size, offset, ~0UL);
70 EXPORT_SYMBOL(find_next_zero_bit);
73 #ifndef find_first_bit
75 * Find the first set bit in a memory region.
77 unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
81 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
83 return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
88 EXPORT_SYMBOL(find_first_bit);
91 #ifndef find_first_zero_bit
93 * Find the first cleared bit in a memory region.
95 unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
99 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
100 if (addr[idx] != ~0UL)
101 return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
106 EXPORT_SYMBOL(find_first_zero_bit);
111 /* include/linux/byteorder does not support "unsigned long" type */
112 static inline unsigned long ext2_swab(const unsigned long y)
114 #if BITS_PER_LONG == 64
115 return (unsigned long) __swab64((u64) y);
116 #elif BITS_PER_LONG == 32
117 return (unsigned long) __swab32((u32) y);
119 #error BITS_PER_LONG not defined
123 #if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
124 static unsigned long _find_next_bit_le(const unsigned long *addr,
125 unsigned long nbits, unsigned long start, unsigned long invert)
129 if (!nbits || start >= nbits)
132 tmp = addr[start / BITS_PER_LONG] ^ invert;
134 /* Handle 1st word. */
135 tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
136 start = round_down(start, BITS_PER_LONG);
139 start += BITS_PER_LONG;
143 tmp = addr[start / BITS_PER_LONG] ^ invert;
146 return min(start + __ffs(ext2_swab(tmp)), nbits);
150 #ifndef find_next_zero_bit_le
151 unsigned long find_next_zero_bit_le(const void *addr, unsigned
152 long size, unsigned long offset)
154 return _find_next_bit_le(addr, size, offset, ~0UL);
156 EXPORT_SYMBOL(find_next_zero_bit_le);
159 #ifndef find_next_bit_le
160 unsigned long find_next_bit_le(const void *addr, unsigned
161 long size, unsigned long offset)
163 return _find_next_bit_le(addr, size, offset, 0UL);
165 EXPORT_SYMBOL(find_next_bit_le);
168 #endif /* __BIG_ENDIAN */