OSDN Git Service

tools: Move code originally from asm-generic/atomic.h into tools/include/asm-generic/
[android-x86/kernel.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 #ifndef __WORDSIZE
9 #define __WORDSIZE (__SIZEOF_LONG__ * 8)
10 #endif
11
12 #define BITS_PER_LONG __WORDSIZE
13 #define BITS_PER_BYTE           8
14 #define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
15 #define BITS_TO_U64(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
16 #define BITS_TO_U32(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
17 #define BITS_TO_BYTES(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE)
18 #define BIT_WORD(nr)            ((nr) / BITS_PER_LONG)
19 #define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
20
21 #define for_each_set_bit(bit, addr, size) \
22         for ((bit) = find_first_bit((addr), (size));            \
23              (bit) < (size);                                    \
24              (bit) = find_next_bit((addr), (size), (bit) + 1))
25
26 /* same as for_each_set_bit() but use bit as value to start with */
27 #define for_each_set_bit_from(bit, addr, size) \
28         for ((bit) = find_next_bit((addr), (size), (bit));      \
29              (bit) < (size);                                    \
30              (bit) = find_next_bit((addr), (size), (bit) + 1))
31
32 #include <asm-generic/bitops/atomic.h>
33
34 static inline unsigned long hweight_long(unsigned long w)
35 {
36         return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
37 }
38
39 #define BITOP_WORD(nr)          ((nr) / BITS_PER_LONG)
40
41 #include <asm-generic/bitops/__ffs.h>
42
43 typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
44
45 /*
46  * Find the first set bit in a memory region.
47  */
48 static inline unsigned long
49 find_first_bit(const unsigned long *addr, unsigned long size)
50 {
51         long_alias_t *p = (long_alias_t *) addr;
52         unsigned long result = 0;
53         unsigned long tmp;
54
55         while (size & ~(BITS_PER_LONG-1)) {
56                 if ((tmp = *(p++)))
57                         goto found;
58                 result += BITS_PER_LONG;
59                 size -= BITS_PER_LONG;
60         }
61         if (!size)
62                 return result;
63
64         tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
65         if (tmp == 0UL)         /* Are any bits set? */
66                 return result + size;   /* Nope. */
67 found:
68         return result + __ffs(tmp);
69 }
70
71 /*
72  * Find the next set bit in a memory region.
73  */
74 static inline unsigned long
75 find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
76 {
77         const unsigned long *p = addr + BITOP_WORD(offset);
78         unsigned long result = offset & ~(BITS_PER_LONG-1);
79         unsigned long tmp;
80
81         if (offset >= size)
82                 return size;
83         size -= result;
84         offset %= BITS_PER_LONG;
85         if (offset) {
86                 tmp = *(p++);
87                 tmp &= (~0UL << offset);
88                 if (size < BITS_PER_LONG)
89                         goto found_first;
90                 if (tmp)
91                         goto found_middle;
92                 size -= BITS_PER_LONG;
93                 result += BITS_PER_LONG;
94         }
95         while (size & ~(BITS_PER_LONG-1)) {
96                 if ((tmp = *(p++)))
97                         goto found_middle;
98                 result += BITS_PER_LONG;
99                 size -= BITS_PER_LONG;
100         }
101         if (!size)
102                 return result;
103         tmp = *p;
104
105 found_first:
106         tmp &= (~0UL >> (BITS_PER_LONG - size));
107         if (tmp == 0UL)         /* Are any bits set? */
108                 return result + size;   /* Nope. */
109 found_middle:
110         return result + __ffs(tmp);
111 }
112
113 #endif