| 
									
										
										
										
											2009-10-17 17:12:33 +02:00
										 |  |  | #ifndef _PERF_LINUX_BITOPS_H_
 | 
					
						
							|  |  |  | #define _PERF_LINUX_BITOPS_H_
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-30 19:31:12 -03:00
										 |  |  | #include <linux/kernel.h>
 | 
					
						
							| 
									
										
										
										
											2011-01-22 19:07:36 -02:00
										 |  |  | #include <linux/compiler.h>
 | 
					
						
							| 
									
										
										
										
											2010-04-30 19:31:12 -03:00
										 |  |  | #include <asm/hweight.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-17 17:12:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 01:15:00 +03:00
										 |  |  | #ifndef __WORDSIZE
 | 
					
						
							|  |  |  | #define __WORDSIZE (__SIZEOF_LONG__ * 8)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-30 19:31:12 -03:00
										 |  |  | #define BITS_PER_LONG __WORDSIZE
 | 
					
						
							|  |  |  | #define BITS_PER_BYTE           8
 | 
					
						
							|  |  |  | #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 | 
					
						
							| 
									
										
										
										
											2012-06-08 11:47:51 -03:00
										 |  |  | #define BITS_TO_U64(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
 | 
					
						
							|  |  |  | #define BITS_TO_U32(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
 | 
					
						
							| 
									
										
										
										
											2013-01-17 09:11:30 -08:00
										 |  |  | #define BITS_TO_BYTES(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE)
 | 
					
						
							| 
									
										
										
										
											2009-11-24 15:19:43 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-07 10:02:57 +01:00
										 |  |  | #define for_each_set_bit(bit, addr, size) \
 | 
					
						
							|  |  |  | 	for ((bit) = find_first_bit((addr), (size));		\ | 
					
						
							|  |  |  | 	     (bit) < (size);					\ | 
					
						
							|  |  |  | 	     (bit) = find_next_bit((addr), (size), (bit) + 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* same as for_each_set_bit() but use bit as value to start with */ | 
					
						
							| 
									
										
										
										
											2012-03-23 15:02:03 -07:00
										 |  |  | #define for_each_set_bit_from(bit, addr, size) \
 | 
					
						
							| 
									
										
										
										
											2011-12-07 10:02:57 +01:00
										 |  |  | 	for ((bit) = find_next_bit((addr), (size), (bit));	\ | 
					
						
							|  |  |  | 	     (bit) < (size);					\ | 
					
						
							|  |  |  | 	     (bit) = find_next_bit((addr), (size), (bit) + 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-17 17:12:33 +02:00
										 |  |  | static inline void set_bit(int nr, unsigned long *addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-26 19:39:15 -02:00
										 |  |  | static inline void clear_bit(int nr, unsigned long *addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-17 17:12:33 +02:00
										 |  |  | static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ((1UL << (nr % BITS_PER_LONG)) & | 
					
						
							|  |  |  | 		(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-30 19:31:12 -03:00
										 |  |  | static inline unsigned long hweight_long(unsigned long w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-17 17:12:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-07 10:02:57 +01:00
										 |  |  | #define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * __ffs - find first bit in word. | 
					
						
							|  |  |  |  * @word: The word to search | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Undefined if no bit exists, so code should check against 0 first. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static __always_inline unsigned long __ffs(unsigned long word) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int num = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if BITS_PER_LONG == 64
 | 
					
						
							|  |  |  | 	if ((word & 0xffffffff) == 0) { | 
					
						
							|  |  |  | 		num += 32; | 
					
						
							|  |  |  | 		word >>= 32; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if ((word & 0xffff) == 0) { | 
					
						
							|  |  |  | 		num += 16; | 
					
						
							|  |  |  | 		word >>= 16; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((word & 0xff) == 0) { | 
					
						
							|  |  |  | 		num += 8; | 
					
						
							|  |  |  | 		word >>= 8; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((word & 0xf) == 0) { | 
					
						
							|  |  |  | 		num += 4; | 
					
						
							|  |  |  | 		word >>= 4; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((word & 0x3) == 0) { | 
					
						
							|  |  |  | 		num += 2; | 
					
						
							|  |  |  | 		word >>= 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((word & 0x1) == 0) | 
					
						
							|  |  |  | 		num += 1; | 
					
						
							|  |  |  | 	return num; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Find the first set bit in a memory region. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline unsigned long | 
					
						
							|  |  |  | find_first_bit(const unsigned long *addr, unsigned long size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const unsigned long *p = addr; | 
					
						
							|  |  |  | 	unsigned long result = 0; | 
					
						
							|  |  |  | 	unsigned long tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (size & ~(BITS_PER_LONG-1)) { | 
					
						
							|  |  |  | 		if ((tmp = *(p++))) | 
					
						
							|  |  |  | 			goto found; | 
					
						
							|  |  |  | 		result += BITS_PER_LONG; | 
					
						
							|  |  |  | 		size -= BITS_PER_LONG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!size) | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | 
					
						
							|  |  |  | 	if (tmp == 0UL)		/* Are any bits set? */ | 
					
						
							|  |  |  | 		return result + size;	/* Nope. */ | 
					
						
							|  |  |  | found: | 
					
						
							|  |  |  | 	return result + __ffs(tmp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Find the next set bit in a memory region. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline unsigned long | 
					
						
							|  |  |  | find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const unsigned long *p = addr + BITOP_WORD(offset); | 
					
						
							|  |  |  | 	unsigned long result = offset & ~(BITS_PER_LONG-1); | 
					
						
							|  |  |  | 	unsigned long tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (offset >= size) | 
					
						
							|  |  |  | 		return size; | 
					
						
							|  |  |  | 	size -= result; | 
					
						
							|  |  |  | 	offset %= BITS_PER_LONG; | 
					
						
							|  |  |  | 	if (offset) { | 
					
						
							|  |  |  | 		tmp = *(p++); | 
					
						
							|  |  |  | 		tmp &= (~0UL << offset); | 
					
						
							|  |  |  | 		if (size < BITS_PER_LONG) | 
					
						
							|  |  |  | 			goto found_first; | 
					
						
							|  |  |  | 		if (tmp) | 
					
						
							|  |  |  | 			goto found_middle; | 
					
						
							|  |  |  | 		size -= BITS_PER_LONG; | 
					
						
							|  |  |  | 		result += BITS_PER_LONG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	while (size & ~(BITS_PER_LONG-1)) { | 
					
						
							|  |  |  | 		if ((tmp = *(p++))) | 
					
						
							|  |  |  | 			goto found_middle; | 
					
						
							|  |  |  | 		result += BITS_PER_LONG; | 
					
						
							|  |  |  | 		size -= BITS_PER_LONG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!size) | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	tmp = *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | found_first: | 
					
						
							|  |  |  | 	tmp &= (~0UL >> (BITS_PER_LONG - size)); | 
					
						
							|  |  |  | 	if (tmp == 0UL)		/* Are any bits set? */ | 
					
						
							|  |  |  | 		return result + size;	/* Nope. */ | 
					
						
							|  |  |  | found_middle: | 
					
						
							|  |  |  | 	return result + __ffs(tmp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-17 17:12:33 +02:00
										 |  |  | #endif
 |