at v3.3 3.4 kB view raw
1#ifndef _PERF_LINUX_BITOPS_H_ 2#define _PERF_LINUX_BITOPS_H_ 3 4#include <linux/kernel.h> 5#include <linux/compiler.h> 6#include <asm/hweight.h> 7 8#define BITS_PER_LONG __WORDSIZE 9#define BITS_PER_BYTE 8 10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 11 12#define for_each_set_bit(bit, addr, size) \ 13 for ((bit) = find_first_bit((addr), (size)); \ 14 (bit) < (size); \ 15 (bit) = find_next_bit((addr), (size), (bit) + 1)) 16 17/* same as for_each_set_bit() but use bit as value to start with */ 18#define for_each_set_bit_cont(bit, addr, size) \ 19 for ((bit) = find_next_bit((addr), (size), (bit)); \ 20 (bit) < (size); \ 21 (bit) = find_next_bit((addr), (size), (bit) + 1)) 22 23static inline void set_bit(int nr, unsigned long *addr) 24{ 25 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 26} 27 28static inline void clear_bit(int nr, unsigned long *addr) 29{ 30 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG)); 31} 32 33static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) 34{ 35 return ((1UL << (nr % BITS_PER_LONG)) & 36 (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; 37} 38 39static inline unsigned long hweight_long(unsigned long w) 40{ 41 return sizeof(w) == 4 ? hweight32(w) : hweight64(w); 42} 43 44#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 45 46/** 47 * __ffs - find first bit in word. 48 * @word: The word to search 49 * 50 * Undefined if no bit exists, so code should check against 0 first. 51 */ 52static __always_inline unsigned long __ffs(unsigned long word) 53{ 54 int num = 0; 55 56#if BITS_PER_LONG == 64 57 if ((word & 0xffffffff) == 0) { 58 num += 32; 59 word >>= 32; 60 } 61#endif 62 if ((word & 0xffff) == 0) { 63 num += 16; 64 word >>= 16; 65 } 66 if ((word & 0xff) == 0) { 67 num += 8; 68 word >>= 8; 69 } 70 if ((word & 0xf) == 0) { 71 num += 4; 72 word >>= 4; 73 } 74 if ((word & 0x3) == 0) { 75 num += 2; 76 word >>= 2; 77 } 78 if ((word & 0x1) == 0) 79 num += 1; 80 return num; 81} 82 83/* 84 * Find the first set bit in a memory region. 85 */ 86static inline unsigned long 87find_first_bit(const unsigned long *addr, unsigned long size) 88{ 89 const unsigned long *p = addr; 90 unsigned long result = 0; 91 unsigned long tmp; 92 93 while (size & ~(BITS_PER_LONG-1)) { 94 if ((tmp = *(p++))) 95 goto found; 96 result += BITS_PER_LONG; 97 size -= BITS_PER_LONG; 98 } 99 if (!size) 100 return result; 101 102 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); 103 if (tmp == 0UL) /* Are any bits set? */ 104 return result + size; /* Nope. */ 105found: 106 return result + __ffs(tmp); 107} 108 109/* 110 * Find the next set bit in a memory region. 111 */ 112static inline unsigned long 113find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) 114{ 115 const unsigned long *p = addr + BITOP_WORD(offset); 116 unsigned long result = offset & ~(BITS_PER_LONG-1); 117 unsigned long tmp; 118 119 if (offset >= size) 120 return size; 121 size -= result; 122 offset %= BITS_PER_LONG; 123 if (offset) { 124 tmp = *(p++); 125 tmp &= (~0UL << offset); 126 if (size < BITS_PER_LONG) 127 goto found_first; 128 if (tmp) 129 goto found_middle; 130 size -= BITS_PER_LONG; 131 result += BITS_PER_LONG; 132 } 133 while (size & ~(BITS_PER_LONG-1)) { 134 if ((tmp = *(p++))) 135 goto found_middle; 136 result += BITS_PER_LONG; 137 size -= BITS_PER_LONG; 138 } 139 if (!size) 140 return result; 141 tmp = *p; 142 143found_first: 144 tmp &= (~0UL >> (BITS_PER_LONG - size)); 145 if (tmp == 0UL) /* Are any bits set? */ 146 return result + size; /* Nope. */ 147found_middle: 148 return result + __ffs(tmp); 149} 150 151#endif