diff options
author | Robert Richter <robert.richter@amd.com> | 2011-12-07 04:02:57 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-12-23 14:03:36 -0500 |
commit | b1e5a9bee3c342dd3281aef76d1be1044dd8addf (patch) | |
tree | 2e82e69f1f4d2ac04cb5d71f16bdbf254edd6b0c /tools/perf/util/include | |
parent | e20960c0271f91aead94746872fd976326a703b3 (diff) |
perf tools: Use for_each_set_bit() to iterate over feature flags
This patch introduces the for_each_set_bit() macro and modifies feature
implementation to use it.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-8-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/include')
-rw-r--r-- | tools/perf/util/include/linux/bitops.h | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 305c8484f200..62cdee78db7b 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h | |||
@@ -9,6 +9,17 @@ | |||
9 | #define BITS_PER_BYTE 8 | 9 | #define BITS_PER_BYTE 8 |
10 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) | 10 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) |
11 | 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 | |||
12 | static inline void set_bit(int nr, unsigned long *addr) | 23 | static inline void set_bit(int nr, unsigned long *addr) |
13 | { | 24 | { |
14 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); | 25 | addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); |
@@ -30,4 +41,111 @@ static inline unsigned long hweight_long(unsigned long w) | |||
30 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | 41 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); |
31 | } | 42 | } |
32 | 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 | */ | ||
52 | static __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 | */ | ||
86 | static inline unsigned long | ||
87 | find_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. */ | ||
105 | found: | ||
106 | return result + __ffs(tmp); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Find the next set bit in a memory region. | ||
111 | */ | ||
112 | static inline unsigned long | ||
113 | find_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 | |||
143 | found_first: | ||
144 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | ||
145 | if (tmp == 0UL) /* Are any bits set? */ | ||
146 | return result + size; /* Nope. */ | ||
147 | found_middle: | ||
148 | return result + __ffs(tmp); | ||
149 | } | ||
150 | |||
33 | #endif | 151 | #endif |