xref: /kvmtool/util/find.c (revision 0febaae00bb6f8c5e694f87d6354fbcbe81e6653)
1*0febaae0SAlexandru Elisei /*
2*0febaae0SAlexandru Elisei  * Taken from Linux kernel version v5.16.
3*0febaae0SAlexandru Elisei  */
4*0febaae0SAlexandru Elisei #include "linux/bitmap.h"
5*0febaae0SAlexandru Elisei #include "linux/find.h"
6*0febaae0SAlexandru Elisei #include "linux/kernel.h"
7*0febaae0SAlexandru Elisei 
_find_next_bit(const unsigned long * addr1,const unsigned long * addr2,unsigned long nbits,unsigned long start,unsigned long invert)8*0febaae0SAlexandru Elisei unsigned long _find_next_bit(const unsigned long *addr1,
9*0febaae0SAlexandru Elisei 		const unsigned long *addr2, unsigned long nbits,
10*0febaae0SAlexandru Elisei 		unsigned long start, unsigned long invert)
11*0febaae0SAlexandru Elisei {
12*0febaae0SAlexandru Elisei 	unsigned long tmp, mask;
13*0febaae0SAlexandru Elisei 
14*0febaae0SAlexandru Elisei 	if (start >= nbits)
15*0febaae0SAlexandru Elisei 		return nbits;
16*0febaae0SAlexandru Elisei 
17*0febaae0SAlexandru Elisei 	tmp = addr1[start / BITS_PER_LONG];
18*0febaae0SAlexandru Elisei 	if (addr2)
19*0febaae0SAlexandru Elisei 		tmp &= addr2[start / BITS_PER_LONG];
20*0febaae0SAlexandru Elisei 	tmp ^= invert;
21*0febaae0SAlexandru Elisei 
22*0febaae0SAlexandru Elisei 	/* Handle 1st word. */
23*0febaae0SAlexandru Elisei 	mask = BITMAP_FIRST_WORD_MASK(start);
24*0febaae0SAlexandru Elisei 	tmp &= mask;
25*0febaae0SAlexandru Elisei 
26*0febaae0SAlexandru Elisei 	start = round_down(start, BITS_PER_LONG);
27*0febaae0SAlexandru Elisei 
28*0febaae0SAlexandru Elisei 	while (!tmp) {
29*0febaae0SAlexandru Elisei 		start += BITS_PER_LONG;
30*0febaae0SAlexandru Elisei 		if (start >= nbits)
31*0febaae0SAlexandru Elisei 			return nbits;
32*0febaae0SAlexandru Elisei 
33*0febaae0SAlexandru Elisei 		tmp = addr1[start / BITS_PER_LONG];
34*0febaae0SAlexandru Elisei 		if (addr2)
35*0febaae0SAlexandru Elisei 			tmp &= addr2[start / BITS_PER_LONG];
36*0febaae0SAlexandru Elisei 		tmp ^= invert;
37*0febaae0SAlexandru Elisei 	}
38*0febaae0SAlexandru Elisei 
39*0febaae0SAlexandru Elisei 	return min(start + __builtin_ctzl(tmp), nbits);
40*0febaae0SAlexandru Elisei }
41