xref: /linux-6.15/tools/include/linux/find.h (revision 6333cb31)
14ade0818SYury Norov /* SPDX-License-Identifier: GPL-2.0 */
24ade0818SYury Norov #ifndef _TOOLS_LINUX_FIND_H_
34ade0818SYury Norov #define _TOOLS_LINUX_FIND_H_
44ade0818SYury Norov 
54ade0818SYury Norov #ifndef _TOOLS_LINUX_BITMAP_H
64ade0818SYury Norov #error tools: only <linux/bitmap.h> can be included directly
74ade0818SYury Norov #endif
84ade0818SYury Norov 
94ade0818SYury Norov #include <linux/bitops.h>
104ade0818SYury Norov 
11*6333cb31SYury Norov unsigned long _find_next_bit(const unsigned long *addr1, unsigned long nbits,
12*6333cb31SYury Norov 				unsigned long start);
13*6333cb31SYury Norov unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigned long *addr2,
14*6333cb31SYury Norov 					unsigned long nbits, unsigned long start);
15*6333cb31SYury Norov unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits,
16*6333cb31SYury Norov 					 unsigned long start);
174ade0818SYury Norov extern unsigned long _find_first_bit(const unsigned long *addr, unsigned long size);
184ade0818SYury Norov extern unsigned long _find_first_and_bit(const unsigned long *addr1,
194ade0818SYury Norov 					 const unsigned long *addr2, unsigned long size);
204ade0818SYury Norov extern unsigned long _find_first_zero_bit(const unsigned long *addr, unsigned long size);
214ade0818SYury Norov 
224ade0818SYury Norov #ifndef find_next_bit
234ade0818SYury Norov /**
244ade0818SYury Norov  * find_next_bit - find the next set bit in a memory region
254ade0818SYury Norov  * @addr: The address to base the search on
264ade0818SYury Norov  * @size: The bitmap size in bits
27*6333cb31SYury Norov  * @offset: The bitnumber to start searching at
284ade0818SYury Norov  *
294ade0818SYury Norov  * Returns the bit number for the next set bit
304ade0818SYury Norov  * If no bits are set, returns @size.
314ade0818SYury Norov  */
324ade0818SYury Norov static inline
find_next_bit(const unsigned long * addr,unsigned long size,unsigned long offset)334ade0818SYury Norov unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
344ade0818SYury Norov 			    unsigned long offset)
354ade0818SYury Norov {
364ade0818SYury Norov 	if (small_const_nbits(size)) {
374ade0818SYury Norov 		unsigned long val;
384ade0818SYury Norov 
394ade0818SYury Norov 		if (unlikely(offset >= size))
404ade0818SYury Norov 			return size;
414ade0818SYury Norov 
424ade0818SYury Norov 		val = *addr & GENMASK(size - 1, offset);
434ade0818SYury Norov 		return val ? __ffs(val) : size;
444ade0818SYury Norov 	}
454ade0818SYury Norov 
46*6333cb31SYury Norov 	return _find_next_bit(addr, size, offset);
474ade0818SYury Norov }
484ade0818SYury Norov #endif
494ade0818SYury Norov 
504ade0818SYury Norov #ifndef find_next_and_bit
514ade0818SYury Norov /**
524ade0818SYury Norov  * find_next_and_bit - find the next set bit in both memory regions
534ade0818SYury Norov  * @addr1: The first address to base the search on
544ade0818SYury Norov  * @addr2: The second address to base the search on
554ade0818SYury Norov  * @size: The bitmap size in bits
56*6333cb31SYury Norov  * @offset: The bitnumber to start searching at
574ade0818SYury Norov  *
584ade0818SYury Norov  * Returns the bit number for the next set bit
594ade0818SYury Norov  * If no bits are set, returns @size.
604ade0818SYury Norov  */
614ade0818SYury Norov static inline
find_next_and_bit(const unsigned long * addr1,const unsigned long * addr2,unsigned long size,unsigned long offset)624ade0818SYury Norov unsigned long find_next_and_bit(const unsigned long *addr1,
634ade0818SYury Norov 		const unsigned long *addr2, unsigned long size,
644ade0818SYury Norov 		unsigned long offset)
654ade0818SYury Norov {
664ade0818SYury Norov 	if (small_const_nbits(size)) {
674ade0818SYury Norov 		unsigned long val;
684ade0818SYury Norov 
694ade0818SYury Norov 		if (unlikely(offset >= size))
704ade0818SYury Norov 			return size;
714ade0818SYury Norov 
724ade0818SYury Norov 		val = *addr1 & *addr2 & GENMASK(size - 1, offset);
734ade0818SYury Norov 		return val ? __ffs(val) : size;
744ade0818SYury Norov 	}
754ade0818SYury Norov 
76*6333cb31SYury Norov 	return _find_next_and_bit(addr1, addr2, size, offset);
774ade0818SYury Norov }
784ade0818SYury Norov #endif
794ade0818SYury Norov 
804ade0818SYury Norov #ifndef find_next_zero_bit
814ade0818SYury Norov /**
824ade0818SYury Norov  * find_next_zero_bit - find the next cleared bit in a memory region
834ade0818SYury Norov  * @addr: The address to base the search on
844ade0818SYury Norov  * @size: The bitmap size in bits
85*6333cb31SYury Norov  * @offset: The bitnumber to start searching at
864ade0818SYury Norov  *
874ade0818SYury Norov  * Returns the bit number of the next zero bit
884ade0818SYury Norov  * If no bits are zero, returns @size.
894ade0818SYury Norov  */
904ade0818SYury Norov static inline
find_next_zero_bit(const unsigned long * addr,unsigned long size,unsigned long offset)914ade0818SYury Norov unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
924ade0818SYury Norov 				 unsigned long offset)
934ade0818SYury Norov {
944ade0818SYury Norov 	if (small_const_nbits(size)) {
954ade0818SYury Norov 		unsigned long val;
964ade0818SYury Norov 
974ade0818SYury Norov 		if (unlikely(offset >= size))
984ade0818SYury Norov 			return size;
994ade0818SYury Norov 
1004ade0818SYury Norov 		val = *addr | ~GENMASK(size - 1, offset);
1014ade0818SYury Norov 		return val == ~0UL ? size : ffz(val);
1024ade0818SYury Norov 	}
1034ade0818SYury Norov 
104*6333cb31SYury Norov 	return _find_next_zero_bit(addr, size, offset);
1054ade0818SYury Norov }
1064ade0818SYury Norov #endif
1074ade0818SYury Norov 
1084ade0818SYury Norov #ifndef find_first_bit
1094ade0818SYury Norov /**
1104ade0818SYury Norov  * find_first_bit - find the first set bit in a memory region
1114ade0818SYury Norov  * @addr: The address to start the search at
1124ade0818SYury Norov  * @size: The maximum number of bits to search
1134ade0818SYury Norov  *
1144ade0818SYury Norov  * Returns the bit number of the first set bit.
1154ade0818SYury Norov  * If no bits are set, returns @size.
1164ade0818SYury Norov  */
1174ade0818SYury Norov static inline
find_first_bit(const unsigned long * addr,unsigned long size)1184ade0818SYury Norov unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
1194ade0818SYury Norov {
1204ade0818SYury Norov 	if (small_const_nbits(size)) {
1214ade0818SYury Norov 		unsigned long val = *addr & GENMASK(size - 1, 0);
1224ade0818SYury Norov 
1234ade0818SYury Norov 		return val ? __ffs(val) : size;
1244ade0818SYury Norov 	}
1254ade0818SYury Norov 
1264ade0818SYury Norov 	return _find_first_bit(addr, size);
1274ade0818SYury Norov }
1284ade0818SYury Norov #endif
1294ade0818SYury Norov 
1304ade0818SYury Norov #ifndef find_first_and_bit
1314ade0818SYury Norov /**
1324ade0818SYury Norov  * find_first_and_bit - find the first set bit in both memory regions
1334ade0818SYury Norov  * @addr1: The first address to base the search on
1344ade0818SYury Norov  * @addr2: The second address to base the search on
1354ade0818SYury Norov  * @size: The bitmap size in bits
1364ade0818SYury Norov  *
1374ade0818SYury Norov  * Returns the bit number for the next set bit
1384ade0818SYury Norov  * If no bits are set, returns @size.
1394ade0818SYury Norov  */
1404ade0818SYury Norov static inline
find_first_and_bit(const unsigned long * addr1,const unsigned long * addr2,unsigned long size)1414ade0818SYury Norov unsigned long find_first_and_bit(const unsigned long *addr1,
1424ade0818SYury Norov 				 const unsigned long *addr2,
1434ade0818SYury Norov 				 unsigned long size)
1444ade0818SYury Norov {
1454ade0818SYury Norov 	if (small_const_nbits(size)) {
1464ade0818SYury Norov 		unsigned long val = *addr1 & *addr2 & GENMASK(size - 1, 0);
1474ade0818SYury Norov 
1484ade0818SYury Norov 		return val ? __ffs(val) : size;
1494ade0818SYury Norov 	}
1504ade0818SYury Norov 
1514ade0818SYury Norov 	return _find_first_and_bit(addr1, addr2, size);
1524ade0818SYury Norov }
1534ade0818SYury Norov #endif
1544ade0818SYury Norov 
1554ade0818SYury Norov #ifndef find_first_zero_bit
1564ade0818SYury Norov /**
1574ade0818SYury Norov  * find_first_zero_bit - find the first cleared bit in a memory region
1584ade0818SYury Norov  * @addr: The address to start the search at
1594ade0818SYury Norov  * @size: The maximum number of bits to search
1604ade0818SYury Norov  *
1614ade0818SYury Norov  * Returns the bit number of the first cleared bit.
1624ade0818SYury Norov  * If no bits are zero, returns @size.
1634ade0818SYury Norov  */
1644ade0818SYury Norov static inline
find_first_zero_bit(const unsigned long * addr,unsigned long size)1654ade0818SYury Norov unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
1664ade0818SYury Norov {
1674ade0818SYury Norov 	if (small_const_nbits(size)) {
1684ade0818SYury Norov 		unsigned long val = *addr | ~GENMASK(size - 1, 0);
1694ade0818SYury Norov 
1704ade0818SYury Norov 		return val == ~0UL ? size : ffz(val);
1714ade0818SYury Norov 	}
1724ade0818SYury Norov 
1734ade0818SYury Norov 	return _find_first_zero_bit(addr, size);
1744ade0818SYury Norov }
1754ade0818SYury Norov #endif
1764ade0818SYury Norov 
1774ade0818SYury Norov #endif /*__LINUX_FIND_H_ */
178