]>
Commit | Line | Data |
---|---|---|
e0e53b2f CC |
1 | /* |
2 | * Bitmap Module | |
3 | * | |
4 | * Stolen from linux/src/lib/bitmap.c | |
5 | * | |
6 | * Copyright (C) 2010 Corentin Chary | |
7 | * | |
8 | * This source code is licensed under the GNU General Public License, | |
9 | * Version 2. | |
10 | */ | |
11 | ||
12 | #include "bitops.h" | |
13 | #include "bitmap.h" | |
14 | ||
15 | /* | |
16 | * bitmaps provide an array of bits, implemented using an an | |
17 | * array of unsigned longs. The number of valid bits in a | |
18 | * given bitmap does _not_ need to be an exact multiple of | |
19 | * BITS_PER_LONG. | |
20 | * | |
21 | * The possible unused bits in the last, partially used word | |
22 | * of a bitmap are 'don't care'. The implementation makes | |
23 | * no particular effort to keep them zero. It ensures that | |
24 | * their value will not affect the results of any operation. | |
25 | * The bitmap operations that return Boolean (bitmap_empty, | |
26 | * for example) or scalar (bitmap_weight, for example) results | |
27 | * carefully filter out these unused bits from impacting their | |
28 | * results. | |
29 | * | |
30 | * These operations actually hold to a slightly stronger rule: | |
31 | * if you don't input any bitmaps to these ops that have some | |
32 | * unused bits set, then they won't output any set unused bits | |
33 | * in output bitmaps. | |
34 | * | |
35 | * The byte ordering of bitmaps is more natural on little | |
36 | * endian architectures. | |
37 | */ | |
38 | ||
39 | int slow_bitmap_empty(const unsigned long *bitmap, int bits) | |
40 | { | |
41 | int k, lim = bits/BITS_PER_LONG; | |
42 | ||
43 | for (k = 0; k < lim; ++k) { | |
44 | if (bitmap[k]) { | |
45 | return 0; | |
46 | } | |
47 | } | |
48 | if (bits % BITS_PER_LONG) { | |
49 | if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) { | |
50 | return 0; | |
51 | } | |
52 | } | |
53 | ||
54 | return 1; | |
55 | } | |
56 | ||
57 | int slow_bitmap_full(const unsigned long *bitmap, int bits) | |
58 | { | |
59 | int k, lim = bits/BITS_PER_LONG; | |
60 | ||
61 | for (k = 0; k < lim; ++k) { | |
62 | if (~bitmap[k]) { | |
63 | return 0; | |
64 | } | |
65 | } | |
66 | ||
67 | if (bits % BITS_PER_LONG) { | |
68 | if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) { | |
69 | return 0; | |
70 | } | |
71 | } | |
72 | ||
73 | return 1; | |
74 | } | |
75 | ||
76 | int slow_bitmap_equal(const unsigned long *bitmap1, | |
77 | const unsigned long *bitmap2, int bits) | |
78 | { | |
79 | int k, lim = bits/BITS_PER_LONG; | |
80 | ||
81 | for (k = 0; k < lim; ++k) { | |
82 | if (bitmap1[k] != bitmap2[k]) { | |
83 | return 0; | |
84 | } | |
85 | } | |
86 | ||
87 | if (bits % BITS_PER_LONG) { | |
88 | if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) { | |
89 | return 0; | |
90 | } | |
91 | } | |
92 | ||
93 | return 1; | |
94 | } | |
95 | ||
96 | void slow_bitmap_complement(unsigned long *dst, const unsigned long *src, | |
97 | int bits) | |
98 | { | |
99 | int k, lim = bits/BITS_PER_LONG; | |
100 | ||
101 | for (k = 0; k < lim; ++k) { | |
102 | dst[k] = ~src[k]; | |
103 | } | |
104 | ||
105 | if (bits % BITS_PER_LONG) { | |
106 | dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits); | |
107 | } | |
108 | } | |
109 | ||
110 | int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1, | |
111 | const unsigned long *bitmap2, int bits) | |
112 | { | |
113 | int k; | |
114 | int nr = BITS_TO_LONGS(bits); | |
115 | unsigned long result = 0; | |
116 | ||
117 | for (k = 0; k < nr; k++) { | |
118 | result |= (dst[k] = bitmap1[k] & bitmap2[k]); | |
119 | } | |
120 | return result != 0; | |
121 | } | |
122 | ||
123 | void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1, | |
124 | const unsigned long *bitmap2, int bits) | |
125 | { | |
126 | int k; | |
127 | int nr = BITS_TO_LONGS(bits); | |
128 | ||
129 | for (k = 0; k < nr; k++) { | |
130 | dst[k] = bitmap1[k] | bitmap2[k]; | |
131 | } | |
132 | } | |
133 | ||
134 | void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1, | |
135 | const unsigned long *bitmap2, int bits) | |
136 | { | |
137 | int k; | |
138 | int nr = BITS_TO_LONGS(bits); | |
139 | ||
140 | for (k = 0; k < nr; k++) { | |
141 | dst[k] = bitmap1[k] ^ bitmap2[k]; | |
142 | } | |
143 | } | |
144 | ||
145 | int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1, | |
146 | const unsigned long *bitmap2, int bits) | |
147 | { | |
148 | int k; | |
149 | int nr = BITS_TO_LONGS(bits); | |
150 | unsigned long result = 0; | |
151 | ||
152 | for (k = 0; k < nr; k++) { | |
153 | result |= (dst[k] = bitmap1[k] & ~bitmap2[k]); | |
154 | } | |
155 | return result != 0; | |
156 | } | |
157 | ||
158 | #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) | |
159 | ||
160 | void bitmap_set(unsigned long *map, int start, int nr) | |
161 | { | |
162 | unsigned long *p = map + BIT_WORD(start); | |
163 | const int size = start + nr; | |
164 | int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); | |
165 | unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); | |
166 | ||
167 | while (nr - bits_to_set >= 0) { | |
168 | *p |= mask_to_set; | |
169 | nr -= bits_to_set; | |
170 | bits_to_set = BITS_PER_LONG; | |
171 | mask_to_set = ~0UL; | |
172 | p++; | |
173 | } | |
174 | if (nr) { | |
175 | mask_to_set &= BITMAP_LAST_WORD_MASK(size); | |
176 | *p |= mask_to_set; | |
177 | } | |
178 | } | |
179 | ||
180 | void bitmap_clear(unsigned long *map, int start, int nr) | |
181 | { | |
182 | unsigned long *p = map + BIT_WORD(start); | |
183 | const int size = start + nr; | |
184 | int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); | |
185 | unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); | |
186 | ||
187 | while (nr - bits_to_clear >= 0) { | |
188 | *p &= ~mask_to_clear; | |
189 | nr -= bits_to_clear; | |
190 | bits_to_clear = BITS_PER_LONG; | |
191 | mask_to_clear = ~0UL; | |
192 | p++; | |
193 | } | |
194 | if (nr) { | |
195 | mask_to_clear &= BITMAP_LAST_WORD_MASK(size); | |
196 | *p &= ~mask_to_clear; | |
197 | } | |
198 | } | |
199 | ||
200 | #define ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) | |
201 | ||
202 | /** | |
203 | * bitmap_find_next_zero_area - find a contiguous aligned zero area | |
204 | * @map: The address to base the search on | |
205 | * @size: The bitmap size in bits | |
206 | * @start: The bitnumber to start searching at | |
207 | * @nr: The number of zeroed bits we're looking for | |
208 | * @align_mask: Alignment mask for zero area | |
209 | * | |
210 | * The @align_mask should be one less than a power of 2; the effect is that | |
211 | * the bit offset of all zero areas this function finds is multiples of that | |
212 | * power of 2. A @align_mask of 0 means no alignment is required. | |
213 | */ | |
214 | unsigned long bitmap_find_next_zero_area(unsigned long *map, | |
215 | unsigned long size, | |
216 | unsigned long start, | |
217 | unsigned int nr, | |
218 | unsigned long align_mask) | |
219 | { | |
220 | unsigned long index, end, i; | |
221 | again: | |
222 | index = find_next_zero_bit(map, size, start); | |
223 | ||
224 | /* Align allocation */ | |
225 | index = ALIGN_MASK(index, align_mask); | |
226 | ||
227 | end = index + nr; | |
228 | if (end > size) { | |
229 | return end; | |
230 | } | |
231 | i = find_next_bit(map, end, index); | |
232 | if (i < end) { | |
233 | start = i + 1; | |
234 | goto again; | |
235 | } | |
236 | return index; | |
237 | } | |
238 | ||
239 | int slow_bitmap_intersects(const unsigned long *bitmap1, | |
240 | const unsigned long *bitmap2, int bits) | |
241 | { | |
242 | int k, lim = bits/BITS_PER_LONG; | |
243 | ||
244 | for (k = 0; k < lim; ++k) { | |
245 | if (bitmap1[k] & bitmap2[k]) { | |
246 | return 1; | |
247 | } | |
248 | } | |
249 | ||
250 | if (bits % BITS_PER_LONG) { | |
251 | if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) { | |
252 | return 1; | |
253 | } | |
254 | } | |
255 | return 0; | |
256 | } |