xref: /OK3568_Linux_fs/kernel/lib/find_bit.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* bit search implementation
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun  * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2008 IBM Corporation
8*4882a593Smuzhiyun  * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
9*4882a593Smuzhiyun  * (Inspired by David Howell's find_next_bit implementation)
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
12*4882a593Smuzhiyun  * size and improve performance, 2015.
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/bitops.h>
16*4882a593Smuzhiyun #include <linux/bitmap.h>
17*4882a593Smuzhiyun #include <linux/export.h>
18*4882a593Smuzhiyun #include <linux/kernel.h>
19*4882a593Smuzhiyun #include <linux/minmax.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #if !defined(find_next_bit) || !defined(find_next_zero_bit) ||			\
22*4882a593Smuzhiyun 	!defined(find_next_bit_le) || !defined(find_next_zero_bit_le) ||	\
23*4882a593Smuzhiyun 	!defined(find_next_and_bit)
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun  * This is a common helper function for find_next_bit, find_next_zero_bit, and
26*4882a593Smuzhiyun  * find_next_and_bit. The differences are:
27*4882a593Smuzhiyun  *  - The "invert" argument, which is XORed with each fetched word before
28*4882a593Smuzhiyun  *    searching it for one bits.
29*4882a593Smuzhiyun  *  - The optional "addr2", which is anded with "addr1" if present.
30*4882a593Smuzhiyun  */
_find_next_bit(const unsigned long * addr1,const unsigned long * addr2,unsigned long nbits,unsigned long start,unsigned long invert,unsigned long le)31*4882a593Smuzhiyun static unsigned long _find_next_bit(const unsigned long *addr1,
32*4882a593Smuzhiyun 		const unsigned long *addr2, unsigned long nbits,
33*4882a593Smuzhiyun 		unsigned long start, unsigned long invert, unsigned long le)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	unsigned long tmp, mask;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	if (unlikely(start >= nbits))
38*4882a593Smuzhiyun 		return nbits;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	tmp = addr1[start / BITS_PER_LONG];
41*4882a593Smuzhiyun 	if (addr2)
42*4882a593Smuzhiyun 		tmp &= addr2[start / BITS_PER_LONG];
43*4882a593Smuzhiyun 	tmp ^= invert;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	/* Handle 1st word. */
46*4882a593Smuzhiyun 	mask = BITMAP_FIRST_WORD_MASK(start);
47*4882a593Smuzhiyun 	if (le)
48*4882a593Smuzhiyun 		mask = swab(mask);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	tmp &= mask;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	start = round_down(start, BITS_PER_LONG);
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	while (!tmp) {
55*4882a593Smuzhiyun 		start += BITS_PER_LONG;
56*4882a593Smuzhiyun 		if (start >= nbits)
57*4882a593Smuzhiyun 			return nbits;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 		tmp = addr1[start / BITS_PER_LONG];
60*4882a593Smuzhiyun 		if (addr2)
61*4882a593Smuzhiyun 			tmp &= addr2[start / BITS_PER_LONG];
62*4882a593Smuzhiyun 		tmp ^= invert;
63*4882a593Smuzhiyun 	}
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	if (le)
66*4882a593Smuzhiyun 		tmp = swab(tmp);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return min(start + __ffs(tmp), nbits);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun #endif
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #ifndef find_next_bit
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun  * Find the next set bit in a memory region.
75*4882a593Smuzhiyun  */
find_next_bit(const unsigned long * addr,unsigned long size,unsigned long offset)76*4882a593Smuzhiyun unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
77*4882a593Smuzhiyun 			    unsigned long offset)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	return _find_next_bit(addr, NULL, size, offset, 0UL, 0);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun EXPORT_SYMBOL(find_next_bit);
82*4882a593Smuzhiyun #endif
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #ifndef find_next_zero_bit
find_next_zero_bit(const unsigned long * addr,unsigned long size,unsigned long offset)85*4882a593Smuzhiyun unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
86*4882a593Smuzhiyun 				 unsigned long offset)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	return _find_next_bit(addr, NULL, size, offset, ~0UL, 0);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun EXPORT_SYMBOL(find_next_zero_bit);
91*4882a593Smuzhiyun #endif
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun #if !defined(find_next_and_bit)
find_next_and_bit(const unsigned long * addr1,const unsigned long * addr2,unsigned long size,unsigned long offset)94*4882a593Smuzhiyun unsigned long find_next_and_bit(const unsigned long *addr1,
95*4882a593Smuzhiyun 		const unsigned long *addr2, unsigned long size,
96*4882a593Smuzhiyun 		unsigned long offset)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	return _find_next_bit(addr1, addr2, size, offset, 0UL, 0);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun EXPORT_SYMBOL(find_next_and_bit);
101*4882a593Smuzhiyun #endif
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun #ifndef find_first_bit
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun  * Find the first set bit in a memory region.
106*4882a593Smuzhiyun  */
find_first_bit(const unsigned long * addr,unsigned long size)107*4882a593Smuzhiyun unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	unsigned long idx;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
112*4882a593Smuzhiyun 		if (addr[idx])
113*4882a593Smuzhiyun 			return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return size;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun EXPORT_SYMBOL(find_first_bit);
119*4882a593Smuzhiyun #endif
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun #ifndef find_first_zero_bit
122*4882a593Smuzhiyun /*
123*4882a593Smuzhiyun  * Find the first cleared bit in a memory region.
124*4882a593Smuzhiyun  */
find_first_zero_bit(const unsigned long * addr,unsigned long size)125*4882a593Smuzhiyun unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	unsigned long idx;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
130*4882a593Smuzhiyun 		if (addr[idx] != ~0UL)
131*4882a593Smuzhiyun 			return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	return size;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun EXPORT_SYMBOL(find_first_zero_bit);
137*4882a593Smuzhiyun #endif
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #ifndef find_last_bit
find_last_bit(const unsigned long * addr,unsigned long size)140*4882a593Smuzhiyun unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	if (size) {
143*4882a593Smuzhiyun 		unsigned long val = BITMAP_LAST_WORD_MASK(size);
144*4882a593Smuzhiyun 		unsigned long idx = (size-1) / BITS_PER_LONG;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 		do {
147*4882a593Smuzhiyun 			val &= addr[idx];
148*4882a593Smuzhiyun 			if (val)
149*4882a593Smuzhiyun 				return idx * BITS_PER_LONG + __fls(val);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 			val = ~0ul;
152*4882a593Smuzhiyun 		} while (idx--);
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 	return size;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun EXPORT_SYMBOL(find_last_bit);
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun #ifndef find_next_zero_bit_le
find_next_zero_bit_le(const void * addr,unsigned long size,unsigned long offset)162*4882a593Smuzhiyun unsigned long find_next_zero_bit_le(const void *addr, unsigned
163*4882a593Smuzhiyun 		long size, unsigned long offset)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun 	return _find_next_bit(addr, NULL, size, offset, ~0UL, 1);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun EXPORT_SYMBOL(find_next_zero_bit_le);
168*4882a593Smuzhiyun #endif
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun #ifndef find_next_bit_le
find_next_bit_le(const void * addr,unsigned long size,unsigned long offset)171*4882a593Smuzhiyun unsigned long find_next_bit_le(const void *addr, unsigned
172*4882a593Smuzhiyun 		long size, unsigned long offset)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	return _find_next_bit(addr, NULL, size, offset, 0UL, 1);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun EXPORT_SYMBOL(find_next_bit_le);
177*4882a593Smuzhiyun #endif
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun #endif /* __BIG_ENDIAN */
180*4882a593Smuzhiyun 
find_next_clump8(unsigned long * clump,const unsigned long * addr,unsigned long size,unsigned long offset)181*4882a593Smuzhiyun unsigned long find_next_clump8(unsigned long *clump, const unsigned long *addr,
182*4882a593Smuzhiyun 			       unsigned long size, unsigned long offset)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	offset = find_next_bit(addr, size, offset);
185*4882a593Smuzhiyun 	if (offset == size)
186*4882a593Smuzhiyun 		return size;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	offset = round_down(offset, 8);
189*4882a593Smuzhiyun 	*clump = bitmap_get_value8(addr, offset);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	return offset;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun EXPORT_SYMBOL(find_next_clump8);
194