1
2
3
4
5
6
7
8#include <linux/module.h>
9#include <linux/ctype.h>
10#include <linux/errno.h>
11#include <linux/bitmap.h>
12#include <asm/bitops.h>
13#include <asm/uaccess.h>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41int __bitmap_empty(const unsigned long *bitmap, int bits)
42{
43 int k, lim = bits/BITS_PER_LONG;
44 for (k = 0; k < lim; ++k)
45 if (bitmap[k])
46 return 0;
47
48 if (bits % BITS_PER_LONG)
49 if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
50 return 0;
51
52 return 1;
53}
54EXPORT_SYMBOL(__bitmap_empty);
55
56int __bitmap_full(const unsigned long *bitmap, int bits)
57{
58 int k, lim = bits/BITS_PER_LONG;
59 for (k = 0; k < lim; ++k)
60 if (~bitmap[k])
61 return 0;
62
63 if (bits % BITS_PER_LONG)
64 if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
65 return 0;
66
67 return 1;
68}
69EXPORT_SYMBOL(__bitmap_full);
70
71int __bitmap_equal(const unsigned long *bitmap1,
72 const unsigned long *bitmap2, int bits)
73{
74 int k, lim = bits/BITS_PER_LONG;
75 for (k = 0; k < lim; ++k)
76 if (bitmap1[k] != bitmap2[k])
77 return 0;
78
79 if (bits % BITS_PER_LONG)
80 if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
81 return 0;
82
83 return 1;
84}
85EXPORT_SYMBOL(__bitmap_equal);
86
87void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
88{
89 int k, lim = bits/BITS_PER_LONG;
90 for (k = 0; k < lim; ++k)
91 dst[k] = ~src[k];
92
93 if (bits % BITS_PER_LONG)
94 dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
95}
96EXPORT_SYMBOL(__bitmap_complement);
97
98
99
100
101
102
103
104
105
106
107
108
109void __bitmap_shift_right(unsigned long *dst,
110 const unsigned long *src, int shift, int bits)
111{
112 int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
113 int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
114 unsigned long mask = (1UL << left) - 1;
115 for (k = 0; off + k < lim; ++k) {
116 unsigned long upper, lower;
117
118
119
120
121
122 if (!rem || off + k + 1 >= lim)
123 upper = 0;
124 else {
125 upper = src[off + k + 1];
126 if (off + k + 1 == lim - 1 && left)
127 upper &= mask;
128 }
129 lower = src[off + k];
130 if (left && off + k == lim - 1)
131 lower &= mask;
132 dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
133 if (left && k == lim - 1)
134 dst[k] &= mask;
135 }
136 if (off)
137 memset(&dst[lim - off], 0, off*sizeof(unsigned long));
138}
139EXPORT_SYMBOL(__bitmap_shift_right);
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154void __bitmap_shift_left(unsigned long *dst,
155 const unsigned long *src, int shift, int bits)
156{
157 int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
158 int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
159 for (k = lim - off - 1; k >= 0; --k) {
160 unsigned long upper, lower;
161
162
163
164
165
166 if (rem && k > 0)
167 lower = src[k - 1];
168 else
169 lower = 0;
170 upper = src[k];
171 if (left && k == lim - 1)
172 upper &= (1UL << left) - 1;
173 dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
174 if (left && k + off == lim - 1)
175 dst[k + off] &= (1UL << left) - 1;
176 }
177 if (off)
178 memset(dst, 0, off*sizeof(unsigned long));
179}
180EXPORT_SYMBOL(__bitmap_shift_left);
181
182void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
183 const unsigned long *bitmap2, int bits)
184{
185 int k;
186 int nr = BITS_TO_LONGS(bits);
187
188 for (k = 0; k < nr; k++)
189 dst[k] = bitmap1[k] & bitmap2[k];
190}
191EXPORT_SYMBOL(__bitmap_and);
192
193void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
194 const unsigned long *bitmap2, int bits)
195{
196 int k;
197 int nr = BITS_TO_LONGS(bits);
198
199 for (k = 0; k < nr; k++)
200 dst[k] = bitmap1[k] | bitmap2[k];
201}
202EXPORT_SYMBOL(__bitmap_or);
203
204void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
205 const unsigned long *bitmap2, int bits)
206{
207 int k;
208 int nr = BITS_TO_LONGS(bits);
209
210 for (k = 0; k < nr; k++)
211 dst[k] = bitmap1[k] ^ bitmap2[k];
212}
213EXPORT_SYMBOL(__bitmap_xor);
214
215void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
216 const unsigned long *bitmap2, int bits)
217{
218 int k;
219 int nr = BITS_TO_LONGS(bits);
220
221 for (k = 0; k < nr; k++)
222 dst[k] = bitmap1[k] & ~bitmap2[k];
223}
224EXPORT_SYMBOL(__bitmap_andnot);
225
226int __bitmap_intersects(const unsigned long *bitmap1,
227 const unsigned long *bitmap2, int bits)
228{
229 int k, lim = bits/BITS_PER_LONG;
230 for (k = 0; k < lim; ++k)
231 if (bitmap1[k] & bitmap2[k])
232 return 1;
233
234 if (bits % BITS_PER_LONG)
235 if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
236 return 1;
237 return 0;
238}
239EXPORT_SYMBOL(__bitmap_intersects);
240
241int __bitmap_subset(const unsigned long *bitmap1,
242 const unsigned long *bitmap2, int bits)
243{
244 int k, lim = bits/BITS_PER_LONG;
245 for (k = 0; k < lim; ++k)
246 if (bitmap1[k] & ~bitmap2[k])
247 return 0;
248
249 if (bits % BITS_PER_LONG)
250 if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
251 return 0;
252 return 1;
253}
254EXPORT_SYMBOL(__bitmap_subset);
255
256#if BITS_PER_LONG == 32
257int __bitmap_weight(const unsigned long *bitmap, int bits)
258{
259 int k, w = 0, lim = bits/BITS_PER_LONG;
260
261 for (k = 0; k < lim; k++)
262 w += hweight32(bitmap[k]);
263
264 if (bits % BITS_PER_LONG)
265 w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
266
267 return w;
268}
269#else
270int __bitmap_weight(const unsigned long *bitmap, int bits)
271{
272 int k, w = 0, lim = bits/BITS_PER_LONG;
273
274 for (k = 0; k < lim; k++)
275 w += hweight64(bitmap[k]);
276
277 if (bits % BITS_PER_LONG)
278 w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
279
280 return w;
281}
282#endif
283EXPORT_SYMBOL(__bitmap_weight);
284
285
286
287
288
289
290#define CHUNKSZ 32
291#define nbits_to_hold_value(val) fls(val)
292#define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1))
293#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
294
295
296
297
298
299
300
301
302
303
304
305int bitmap_scnprintf(char *buf, unsigned int buflen,
306 const unsigned long *maskp, int nmaskbits)
307{
308 int i, word, bit, len = 0;
309 unsigned long val;
310 const char *sep = "";
311 int chunksz;
312 u32 chunkmask;
313
314 chunksz = nmaskbits & (CHUNKSZ - 1);
315 if (chunksz == 0)
316 chunksz = CHUNKSZ;
317
318 i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ;
319 for (; i >= 0; i -= CHUNKSZ) {
320 chunkmask = ((1ULL << chunksz) - 1);
321 word = i / BITS_PER_LONG;
322 bit = i % BITS_PER_LONG;
323 val = (maskp[word] >> bit) & chunkmask;
324 len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
325 (chunksz+3)/4, val);
326 chunksz = CHUNKSZ;
327 sep = ",";
328 }
329 return len;
330}
331EXPORT_SYMBOL(bitmap_scnprintf);
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
349 unsigned long *maskp, int nmaskbits)
350{
351 int c, old_c, totaldigits, ndigits, nchunks, nbits;
352 u32 chunk;
353
354 bitmap_zero(maskp, nmaskbits);
355
356 nchunks = nbits = totaldigits = c = 0;
357 do {
358 chunk = ndigits = 0;
359
360
361 while (ubuflen) {
362 old_c = c;
363 if (get_user(c, ubuf++))
364 return -EFAULT;
365 ubuflen--;
366 if (isspace(c))
367 continue;
368
369
370
371
372
373
374 if (totaldigits && c && isspace(old_c))
375 return -EINVAL;
376
377
378 if (c == '\0' || c == ',')
379 break;
380
381 if (!isxdigit(c))
382 return -EINVAL;
383
384
385
386
387
388
389 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
390 return -EOVERFLOW;
391
392 chunk = (chunk << 4) | unhex(c);
393 ndigits++; totaldigits++;
394 }
395 if (ndigits == 0)
396 return -EINVAL;
397 if (nchunks == 0 && chunk == 0)
398 continue;
399
400 __bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
401 *maskp |= chunk;
402 nchunks++;
403 nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
404 if (nbits > nmaskbits)
405 return -EOVERFLOW;
406 } while (ubuflen && c == ',');
407
408 return 0;
409}
410EXPORT_SYMBOL(bitmap_parse);
411