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