2 * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #ifndef _LINUXKPI_LINUX_BITMAP_H_
30 #define _LINUXKPI_LINUX_BITMAP_H_
32 #include <linux/bitops.h>
33 #include <linux/slab.h>
36 bitmap_zero(unsigned long *addr, const unsigned int size)
38 memset(addr, 0, BITS_TO_LONGS(size) * sizeof(long));
42 bitmap_fill(unsigned long *addr, const unsigned int size)
44 const unsigned int tail = size & (BITS_PER_LONG - 1);
46 memset(addr, 0xff, BIT_WORD(size) * sizeof(long));
49 addr[BIT_WORD(size)] = BITMAP_LAST_WORD_MASK(tail);
53 bitmap_full(unsigned long *addr, const unsigned int size)
55 const unsigned int end = BIT_WORD(size);
56 const unsigned int tail = size & (BITS_PER_LONG - 1);
59 for (i = 0; i != end; i++) {
65 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
67 if ((addr[end] & mask) != mask)
74 bitmap_empty(unsigned long *addr, const unsigned int size)
76 const unsigned int end = BIT_WORD(size);
77 const unsigned int tail = size & (BITS_PER_LONG - 1);
80 for (i = 0; i != end; i++) {
86 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
88 if ((addr[end] & mask) != 0)
95 bitmap_set(unsigned long *map, unsigned int start, int nr)
97 const unsigned int size = start + nr;
98 int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
99 unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
101 map += BIT_WORD(start);
103 while (nr - bits_to_set >= 0) {
106 bits_to_set = BITS_PER_LONG;
112 mask_to_set &= BITMAP_LAST_WORD_MASK(size);
118 bitmap_clear(unsigned long *map, unsigned int start, int nr)
120 const unsigned int size = start + nr;
121 int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
122 unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
124 map += BIT_WORD(start);
126 while (nr - bits_to_clear >= 0) {
127 *map &= ~mask_to_clear;
129 bits_to_clear = BITS_PER_LONG;
130 mask_to_clear = ~0UL;
135 mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
136 *map &= ~mask_to_clear;
140 static inline unsigned int
141 bitmap_find_next_zero_area_off(const unsigned long *map,
142 const unsigned int size, unsigned int start,
143 unsigned int nr, unsigned int align_mask,
144 unsigned int align_offset)
151 index = find_next_zero_bit(map, size, start);
153 index = (((index + align_offset) + align_mask) & ~align_mask) - align_offset;
159 i = find_next_bit(map, end, index);
167 static inline unsigned int
168 bitmap_find_next_zero_area(const unsigned long *map,
169 const unsigned int size, unsigned int start,
170 unsigned int nr, unsigned int align_mask)
172 return (bitmap_find_next_zero_area_off(map, size,
173 start, nr, align_mask, 0));
177 bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
182 for (pos = 0; (end = pos + (1 << order)) <= bits; pos = end) {
183 if (!linux_reg_op(bitmap, pos, order, REG_OP_ISFREE))
185 linux_reg_op(bitmap, pos, order, REG_OP_ALLOC);
192 bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
194 if (!linux_reg_op(bitmap, pos, order, REG_OP_ISFREE))
196 linux_reg_op(bitmap, pos, order, REG_OP_ALLOC);
201 bitmap_release_region(unsigned long *bitmap, int pos, int order)
203 linux_reg_op(bitmap, pos, order, REG_OP_RELEASE);
206 static inline unsigned int
207 bitmap_weight(unsigned long *addr, const unsigned int size)
209 const unsigned int end = BIT_WORD(size);
210 const unsigned int tail = size & (BITS_PER_LONG - 1);
211 unsigned int retval = 0;
214 for (i = 0; i != end; i++)
215 retval += hweight_long(addr[i]);
218 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
220 retval += hweight_long(addr[end] & mask);
226 bitmap_equal(const unsigned long *pa,
227 const unsigned long *pb, unsigned size)
229 const unsigned int end = BIT_WORD(size);
230 const unsigned int tail = size & (BITS_PER_LONG - 1);
233 for (i = 0; i != end; i++) {
239 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
241 if ((pa[end] ^ pb[end]) & mask)
248 bitmap_subset(const unsigned long *pa,
249 const unsigned long *pb, unsigned size)
251 const unsigned end = BIT_WORD(size);
252 const unsigned tail = size & (BITS_PER_LONG - 1);
255 for (i = 0; i != end; i++) {
261 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
263 if (pa[end] & ~pb[end] & mask)
270 bitmap_complement(unsigned long *dst, const unsigned long *src,
271 const unsigned int size)
273 const unsigned int end = BITS_TO_LONGS(size);
276 for (i = 0; i != end; i++)
281 bitmap_copy(unsigned long *dst, const unsigned long *src,
282 const unsigned int size)
284 const unsigned int end = BITS_TO_LONGS(size);
287 for (i = 0; i != end; i++)
292 bitmap_or(unsigned long *dst, const unsigned long *src1,
293 const unsigned long *src2, const unsigned int size)
295 const unsigned int end = BITS_TO_LONGS(size);
298 for (i = 0; i != end; i++)
299 dst[i] = src1[i] | src2[i];
303 bitmap_and(unsigned long *dst, const unsigned long *src1,
304 const unsigned long *src2, const unsigned int size)
306 const unsigned int end = BITS_TO_LONGS(size);
309 for (i = 0; i != end; i++)
310 dst[i] = src1[i] & src2[i];
314 bitmap_andnot(unsigned long *dst, const unsigned long *src1,
315 const unsigned long *src2, const unsigned int size)
317 const unsigned int end = BITS_TO_LONGS(size);
320 for (i = 0; i != end; i++)
321 dst[i] = src1[i] & ~src2[i];
325 bitmap_xor(unsigned long *dst, const unsigned long *src1,
326 const unsigned long *src2, const unsigned int size)
328 const unsigned int end = BITS_TO_LONGS(size);
331 for (i = 0; i != end; i++)
332 dst[i] = src1[i] ^ src2[i];
335 static inline unsigned long *
336 bitmap_alloc(unsigned int size, gfp_t flags)
338 return (kmalloc_array(BITS_TO_LONGS(size),
339 sizeof(unsigned long), flags));
342 static inline unsigned long *
343 bitmap_zalloc(unsigned int size, gfp_t flags)
345 return (bitmap_alloc(size, flags | __GFP_ZERO));
349 bitmap_free(const unsigned long *bitmap)
354 #endif /* _LINUXKPI_LINUX_BITMAP_H_ */