xref: /freebsd-src/sys/compat/linuxkpi/common/include/linux/bitmap.h (revision dbca442414191a43f334435b7910b63cb2777d53)
1c9dd0b48SHans Petter Selasky /*
2c9dd0b48SHans Petter Selasky  * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
3c9dd0b48SHans Petter Selasky  * All rights reserved.
4c9dd0b48SHans Petter Selasky  *
5c9dd0b48SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
6c9dd0b48SHans Petter Selasky  * modification, are permitted provided that the following conditions
7c9dd0b48SHans Petter Selasky  * are met:
8c9dd0b48SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
9c9dd0b48SHans Petter Selasky  *    notice unmodified, this list of conditions, and the following
10c9dd0b48SHans Petter Selasky  *    disclaimer.
11c9dd0b48SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
12c9dd0b48SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
13c9dd0b48SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
14c9dd0b48SHans Petter Selasky  *
15c9dd0b48SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16c9dd0b48SHans Petter Selasky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17c9dd0b48SHans Petter Selasky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18c9dd0b48SHans Petter Selasky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19c9dd0b48SHans Petter Selasky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20c9dd0b48SHans Petter Selasky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21c9dd0b48SHans Petter Selasky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22c9dd0b48SHans Petter Selasky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23c9dd0b48SHans Petter Selasky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24c9dd0b48SHans Petter Selasky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25c9dd0b48SHans Petter Selasky  */
26c9dd0b48SHans Petter Selasky 
27307f78f3SVladimir Kondratyev #ifndef _LINUXKPI_LINUX_BITMAP_H_
28307f78f3SVladimir Kondratyev #define	_LINUXKPI_LINUX_BITMAP_H_
29c9dd0b48SHans Petter Selasky 
30c9dd0b48SHans Petter Selasky #include <linux/bitops.h>
31ce03b301SEmmanuel Vadot #include <linux/slab.h>
32c9dd0b48SHans Petter Selasky 
33c9dd0b48SHans Petter Selasky static inline void
bitmap_zero(unsigned long * addr,const unsigned int size)34c9dd0b48SHans Petter Selasky bitmap_zero(unsigned long *addr, const unsigned int size)
35c9dd0b48SHans Petter Selasky {
36c9dd0b48SHans Petter Selasky 	memset(addr, 0, BITS_TO_LONGS(size) * sizeof(long));
37c9dd0b48SHans Petter Selasky }
38c9dd0b48SHans Petter Selasky 
39c9dd0b48SHans Petter Selasky static inline void
bitmap_fill(unsigned long * addr,const unsigned int size)40c9dd0b48SHans Petter Selasky bitmap_fill(unsigned long *addr, const unsigned int size)
41c9dd0b48SHans Petter Selasky {
42c9dd0b48SHans Petter Selasky 	const unsigned int tail = size & (BITS_PER_LONG - 1);
43c9dd0b48SHans Petter Selasky 
44c9dd0b48SHans Petter Selasky 	memset(addr, 0xff, BIT_WORD(size) * sizeof(long));
45c9dd0b48SHans Petter Selasky 
46c9dd0b48SHans Petter Selasky 	if (tail)
47c9dd0b48SHans Petter Selasky 		addr[BIT_WORD(size)] = BITMAP_LAST_WORD_MASK(tail);
48c9dd0b48SHans Petter Selasky }
49c9dd0b48SHans Petter Selasky 
50c9dd0b48SHans Petter Selasky static inline int
bitmap_full(unsigned long * addr,const unsigned int size)51c9dd0b48SHans Petter Selasky bitmap_full(unsigned long *addr, const unsigned int size)
52c9dd0b48SHans Petter Selasky {
53c9dd0b48SHans Petter Selasky 	const unsigned int end = BIT_WORD(size);
54c9dd0b48SHans Petter Selasky 	const unsigned int tail = size & (BITS_PER_LONG - 1);
55c9dd0b48SHans Petter Selasky 	unsigned int i;
56c9dd0b48SHans Petter Selasky 
57c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++) {
58c9dd0b48SHans Petter Selasky 		if (addr[i] != ~0UL)
59c9dd0b48SHans Petter Selasky 			return (0);
60c9dd0b48SHans Petter Selasky 	}
61c9dd0b48SHans Petter Selasky 
62c9dd0b48SHans Petter Selasky 	if (tail) {
63c9dd0b48SHans Petter Selasky 		const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
64c9dd0b48SHans Petter Selasky 
65c9dd0b48SHans Petter Selasky 		if ((addr[end] & mask) != mask)
66c9dd0b48SHans Petter Selasky 			return (0);
67c9dd0b48SHans Petter Selasky 	}
68c9dd0b48SHans Petter Selasky 	return (1);
69c9dd0b48SHans Petter Selasky }
70c9dd0b48SHans Petter Selasky 
71c9dd0b48SHans Petter Selasky static inline int
bitmap_empty(unsigned long * addr,const unsigned int size)72c9dd0b48SHans Petter Selasky bitmap_empty(unsigned long *addr, const unsigned int size)
73c9dd0b48SHans Petter Selasky {
74c9dd0b48SHans Petter Selasky 	const unsigned int end = BIT_WORD(size);
75c9dd0b48SHans Petter Selasky 	const unsigned int tail = size & (BITS_PER_LONG - 1);
76c9dd0b48SHans Petter Selasky 	unsigned int i;
77c9dd0b48SHans Petter Selasky 
78c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++) {
79c9dd0b48SHans Petter Selasky 		if (addr[i] != 0)
80c9dd0b48SHans Petter Selasky 			return (0);
81c9dd0b48SHans Petter Selasky 	}
82c9dd0b48SHans Petter Selasky 
83c9dd0b48SHans Petter Selasky 	if (tail) {
84c9dd0b48SHans Petter Selasky 		const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
85c9dd0b48SHans Petter Selasky 
86c9dd0b48SHans Petter Selasky 		if ((addr[end] & mask) != 0)
87c9dd0b48SHans Petter Selasky 			return (0);
88c9dd0b48SHans Petter Selasky 	}
89c9dd0b48SHans Petter Selasky 	return (1);
90c9dd0b48SHans Petter Selasky }
91c9dd0b48SHans Petter Selasky 
92c9dd0b48SHans Petter Selasky static inline void
bitmap_set(unsigned long * map,unsigned int start,int nr)93c9dd0b48SHans Petter Selasky bitmap_set(unsigned long *map, unsigned int start, int nr)
94c9dd0b48SHans Petter Selasky {
95c9dd0b48SHans Petter Selasky 	const unsigned int size = start + nr;
96c9dd0b48SHans Petter Selasky 	int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
97c9dd0b48SHans Petter Selasky 	unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
98c9dd0b48SHans Petter Selasky 
99c9dd0b48SHans Petter Selasky 	map += BIT_WORD(start);
100c9dd0b48SHans Petter Selasky 
101c9dd0b48SHans Petter Selasky 	while (nr - bits_to_set >= 0) {
102c9dd0b48SHans Petter Selasky 		*map |= mask_to_set;
103c9dd0b48SHans Petter Selasky 		nr -= bits_to_set;
104c9dd0b48SHans Petter Selasky 		bits_to_set = BITS_PER_LONG;
105c9dd0b48SHans Petter Selasky 		mask_to_set = ~0UL;
106c9dd0b48SHans Petter Selasky 		map++;
107c9dd0b48SHans Petter Selasky 	}
108c9dd0b48SHans Petter Selasky 
109c9dd0b48SHans Petter Selasky 	if (nr) {
110c9dd0b48SHans Petter Selasky 		mask_to_set &= BITMAP_LAST_WORD_MASK(size);
111c9dd0b48SHans Petter Selasky 		*map |= mask_to_set;
112c9dd0b48SHans Petter Selasky 	}
113c9dd0b48SHans Petter Selasky }
114c9dd0b48SHans Petter Selasky 
115c9dd0b48SHans Petter Selasky static inline void
bitmap_clear(unsigned long * map,unsigned int start,int nr)116c9dd0b48SHans Petter Selasky bitmap_clear(unsigned long *map, unsigned int start, int nr)
117c9dd0b48SHans Petter Selasky {
118c9dd0b48SHans Petter Selasky 	const unsigned int size = start + nr;
119c9dd0b48SHans Petter Selasky 	int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
120c9dd0b48SHans Petter Selasky 	unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
121c9dd0b48SHans Petter Selasky 
122c9dd0b48SHans Petter Selasky 	map += BIT_WORD(start);
123c9dd0b48SHans Petter Selasky 
124c9dd0b48SHans Petter Selasky 	while (nr - bits_to_clear >= 0) {
125c9dd0b48SHans Petter Selasky 		*map &= ~mask_to_clear;
126c9dd0b48SHans Petter Selasky 		nr -= bits_to_clear;
127c9dd0b48SHans Petter Selasky 		bits_to_clear = BITS_PER_LONG;
128c9dd0b48SHans Petter Selasky 		mask_to_clear = ~0UL;
129c9dd0b48SHans Petter Selasky 		map++;
130c9dd0b48SHans Petter Selasky 	}
131c9dd0b48SHans Petter Selasky 
132c9dd0b48SHans Petter Selasky 	if (nr) {
133c9dd0b48SHans Petter Selasky 		mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
134c9dd0b48SHans Petter Selasky 		*map &= ~mask_to_clear;
135c9dd0b48SHans Petter Selasky 	}
136c9dd0b48SHans Petter Selasky }
137c9dd0b48SHans Petter Selasky 
138c9dd0b48SHans Petter Selasky static inline unsigned int
bitmap_find_next_zero_area_off(const unsigned long * map,const unsigned int size,unsigned int start,unsigned int nr,unsigned int align_mask,unsigned int align_offset)139c9dd0b48SHans Petter Selasky bitmap_find_next_zero_area_off(const unsigned long *map,
140c9dd0b48SHans Petter Selasky     const unsigned int size, unsigned int start,
141c9dd0b48SHans Petter Selasky     unsigned int nr, unsigned int align_mask,
142c9dd0b48SHans Petter Selasky     unsigned int align_offset)
143c9dd0b48SHans Petter Selasky {
144c9dd0b48SHans Petter Selasky 	unsigned int index;
145c9dd0b48SHans Petter Selasky 	unsigned int end;
146c9dd0b48SHans Petter Selasky 	unsigned int i;
147c9dd0b48SHans Petter Selasky 
148c9dd0b48SHans Petter Selasky retry:
149c9dd0b48SHans Petter Selasky 	index = find_next_zero_bit(map, size, start);
150c9dd0b48SHans Petter Selasky 
151c9dd0b48SHans Petter Selasky 	index = (((index + align_offset) + align_mask) & ~align_mask) - align_offset;
152c9dd0b48SHans Petter Selasky 
153c9dd0b48SHans Petter Selasky 	end = index + nr;
154c9dd0b48SHans Petter Selasky 	if (end > size)
155c9dd0b48SHans Petter Selasky 		return (end);
156c9dd0b48SHans Petter Selasky 
157c9dd0b48SHans Petter Selasky 	i = find_next_bit(map, end, index);
158c9dd0b48SHans Petter Selasky 	if (i < end) {
159c9dd0b48SHans Petter Selasky 		start = i + 1;
160c9dd0b48SHans Petter Selasky 		goto retry;
161c9dd0b48SHans Petter Selasky 	}
162c9dd0b48SHans Petter Selasky 	return (index);
163c9dd0b48SHans Petter Selasky }
164c9dd0b48SHans Petter Selasky 
165c9dd0b48SHans Petter Selasky static inline unsigned int
bitmap_find_next_zero_area(const unsigned long * map,const unsigned int size,unsigned int start,unsigned int nr,unsigned int align_mask)166c9dd0b48SHans Petter Selasky bitmap_find_next_zero_area(const unsigned long *map,
167c9dd0b48SHans Petter Selasky     const unsigned int size, unsigned int start,
168c9dd0b48SHans Petter Selasky     unsigned int nr, unsigned int align_mask)
169c9dd0b48SHans Petter Selasky {
170c9dd0b48SHans Petter Selasky 	return (bitmap_find_next_zero_area_off(map, size,
171c9dd0b48SHans Petter Selasky 	    start, nr, align_mask, 0));
172c9dd0b48SHans Petter Selasky }
173c9dd0b48SHans Petter Selasky 
174c9dd0b48SHans Petter Selasky static inline int
bitmap_find_free_region(unsigned long * bitmap,int bits,int order)175c9dd0b48SHans Petter Selasky bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
176c9dd0b48SHans Petter Selasky {
177c9dd0b48SHans Petter Selasky 	int pos;
178c9dd0b48SHans Petter Selasky 	int end;
179c9dd0b48SHans Petter Selasky 
180c9dd0b48SHans Petter Selasky 	for (pos = 0; (end = pos + (1 << order)) <= bits; pos = end) {
181c9dd0b48SHans Petter Selasky 		if (!linux_reg_op(bitmap, pos, order, REG_OP_ISFREE))
182c9dd0b48SHans Petter Selasky 			continue;
183c9dd0b48SHans Petter Selasky 		linux_reg_op(bitmap, pos, order, REG_OP_ALLOC);
184c9dd0b48SHans Petter Selasky 		return (pos);
185c9dd0b48SHans Petter Selasky 	}
186c9dd0b48SHans Petter Selasky 	return (-ENOMEM);
187c9dd0b48SHans Petter Selasky }
188c9dd0b48SHans Petter Selasky 
189c9dd0b48SHans Petter Selasky static inline int
bitmap_allocate_region(unsigned long * bitmap,int pos,int order)190c9dd0b48SHans Petter Selasky bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
191c9dd0b48SHans Petter Selasky {
192c9dd0b48SHans Petter Selasky 	if (!linux_reg_op(bitmap, pos, order, REG_OP_ISFREE))
193c9dd0b48SHans Petter Selasky 		return (-EBUSY);
194c9dd0b48SHans Petter Selasky 	linux_reg_op(bitmap, pos, order, REG_OP_ALLOC);
195c9dd0b48SHans Petter Selasky 	return (0);
196c9dd0b48SHans Petter Selasky }
197c9dd0b48SHans Petter Selasky 
198c9dd0b48SHans Petter Selasky static inline void
bitmap_release_region(unsigned long * bitmap,int pos,int order)199c9dd0b48SHans Petter Selasky bitmap_release_region(unsigned long *bitmap, int pos, int order)
200c9dd0b48SHans Petter Selasky {
201c9dd0b48SHans Petter Selasky 	linux_reg_op(bitmap, pos, order, REG_OP_RELEASE);
202c9dd0b48SHans Petter Selasky }
203c9dd0b48SHans Petter Selasky 
204c9dd0b48SHans Petter Selasky static inline unsigned int
bitmap_weight(unsigned long * addr,const unsigned int size)205c9dd0b48SHans Petter Selasky bitmap_weight(unsigned long *addr, const unsigned int size)
206c9dd0b48SHans Petter Selasky {
207c9dd0b48SHans Petter Selasky 	const unsigned int end = BIT_WORD(size);
208c9dd0b48SHans Petter Selasky 	const unsigned int tail = size & (BITS_PER_LONG - 1);
209c9dd0b48SHans Petter Selasky 	unsigned int retval = 0;
210c9dd0b48SHans Petter Selasky 	unsigned int i;
211c9dd0b48SHans Petter Selasky 
212c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++)
213c9dd0b48SHans Petter Selasky 		retval += hweight_long(addr[i]);
214c9dd0b48SHans Petter Selasky 
215c9dd0b48SHans Petter Selasky 	if (tail) {
216c9dd0b48SHans Petter Selasky 		const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
217c9dd0b48SHans Petter Selasky 
218c9dd0b48SHans Petter Selasky 		retval += hweight_long(addr[end] & mask);
219c9dd0b48SHans Petter Selasky 	}
220c9dd0b48SHans Petter Selasky 	return (retval);
221c9dd0b48SHans Petter Selasky }
222c9dd0b48SHans Petter Selasky 
223c9dd0b48SHans Petter Selasky static inline int
bitmap_equal(const unsigned long * pa,const unsigned long * pb,unsigned size)224c9dd0b48SHans Petter Selasky bitmap_equal(const unsigned long *pa,
225c9dd0b48SHans Petter Selasky     const unsigned long *pb, unsigned size)
226c9dd0b48SHans Petter Selasky {
227c9dd0b48SHans Petter Selasky 	const unsigned int end = BIT_WORD(size);
228c9dd0b48SHans Petter Selasky 	const unsigned int tail = size & (BITS_PER_LONG - 1);
229c9dd0b48SHans Petter Selasky 	unsigned int i;
230c9dd0b48SHans Petter Selasky 
231c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++) {
232c9dd0b48SHans Petter Selasky 		if (pa[i] != pb[i])
233c9dd0b48SHans Petter Selasky 			return (0);
234c9dd0b48SHans Petter Selasky 	}
235c9dd0b48SHans Petter Selasky 
236c9dd0b48SHans Petter Selasky 	if (tail) {
237c9dd0b48SHans Petter Selasky 		const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
238c9dd0b48SHans Petter Selasky 
239c9dd0b48SHans Petter Selasky 		if ((pa[end] ^ pb[end]) & mask)
240c9dd0b48SHans Petter Selasky 			return (0);
241c9dd0b48SHans Petter Selasky 	}
242c9dd0b48SHans Petter Selasky 	return (1);
243c9dd0b48SHans Petter Selasky }
244c9dd0b48SHans Petter Selasky 
245127d8cfaSHans Petter Selasky static inline int
bitmap_subset(const unsigned long * pa,const unsigned long * pb,unsigned size)246127d8cfaSHans Petter Selasky bitmap_subset(const unsigned long *pa,
247127d8cfaSHans Petter Selasky     const unsigned long *pb, unsigned size)
248127d8cfaSHans Petter Selasky {
249127d8cfaSHans Petter Selasky 	const unsigned end = BIT_WORD(size);
250127d8cfaSHans Petter Selasky 	const unsigned tail = size & (BITS_PER_LONG - 1);
251127d8cfaSHans Petter Selasky 	unsigned i;
252127d8cfaSHans Petter Selasky 
253127d8cfaSHans Petter Selasky 	for (i = 0; i != end; i++) {
254127d8cfaSHans Petter Selasky 		if (pa[i] & ~pb[i])
255127d8cfaSHans Petter Selasky 			return (0);
256127d8cfaSHans Petter Selasky 	}
257127d8cfaSHans Petter Selasky 
258127d8cfaSHans Petter Selasky 	if (tail) {
259127d8cfaSHans Petter Selasky 		const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
260127d8cfaSHans Petter Selasky 
261127d8cfaSHans Petter Selasky 		if (pa[end] & ~pb[end] & mask)
262127d8cfaSHans Petter Selasky 			return (0);
263127d8cfaSHans Petter Selasky 	}
264127d8cfaSHans Petter Selasky 	return (1);
265127d8cfaSHans Petter Selasky }
266127d8cfaSHans Petter Selasky 
2675ae2e6f9SVladimir Kondratyev static inline bool
bitmap_intersects(const unsigned long * pa,const unsigned long * pb,unsigned size)2685ae2e6f9SVladimir Kondratyev bitmap_intersects(const unsigned long *pa, const unsigned long *pb,
2695ae2e6f9SVladimir Kondratyev     unsigned size)
2705ae2e6f9SVladimir Kondratyev {
2715ae2e6f9SVladimir Kondratyev 	const unsigned end = BIT_WORD(size);
2725ae2e6f9SVladimir Kondratyev 	const unsigned tail = size & (BITS_PER_LONG - 1);
2735ae2e6f9SVladimir Kondratyev 	unsigned i;
2745ae2e6f9SVladimir Kondratyev 
2755ae2e6f9SVladimir Kondratyev 	for (i = 0; i != end; i++)
2765ae2e6f9SVladimir Kondratyev 		if (pa[i] & pb[i])
2775ae2e6f9SVladimir Kondratyev 			return (true);
2785ae2e6f9SVladimir Kondratyev 
2795ae2e6f9SVladimir Kondratyev 	if (tail) {
2805ae2e6f9SVladimir Kondratyev 		 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
2815ae2e6f9SVladimir Kondratyev 
2825ae2e6f9SVladimir Kondratyev 		if (pa[end] & pb[end] & mask)
2835ae2e6f9SVladimir Kondratyev 			return (true);
2845ae2e6f9SVladimir Kondratyev 	}
2855ae2e6f9SVladimir Kondratyev 	return (false);
2865ae2e6f9SVladimir Kondratyev }
2875ae2e6f9SVladimir Kondratyev 
288c9dd0b48SHans Petter Selasky static inline void
bitmap_complement(unsigned long * dst,const unsigned long * src,const unsigned int size)2897ce7605eSHans Petter Selasky bitmap_complement(unsigned long *dst, const unsigned long *src,
2907ce7605eSHans Petter Selasky     const unsigned int size)
2917ce7605eSHans Petter Selasky {
2927ce7605eSHans Petter Selasky 	const unsigned int end = BITS_TO_LONGS(size);
2937ce7605eSHans Petter Selasky 	unsigned int i;
2947ce7605eSHans Petter Selasky 
2957ce7605eSHans Petter Selasky 	for (i = 0; i != end; i++)
2967ce7605eSHans Petter Selasky 		dst[i] = ~src[i];
2977ce7605eSHans Petter Selasky }
2987ce7605eSHans Petter Selasky 
2997ce7605eSHans Petter Selasky static inline void
bitmap_copy(unsigned long * dst,const unsigned long * src,const unsigned int size)30026a57869SEmmanuel Vadot bitmap_copy(unsigned long *dst, const unsigned long *src,
30126a57869SEmmanuel Vadot     const unsigned int size)
30226a57869SEmmanuel Vadot {
30326a57869SEmmanuel Vadot 	const unsigned int end = BITS_TO_LONGS(size);
30426a57869SEmmanuel Vadot 	unsigned int i;
30526a57869SEmmanuel Vadot 
30626a57869SEmmanuel Vadot 	for (i = 0; i != end; i++)
30726a57869SEmmanuel Vadot 		dst[i] = src[i];
30826a57869SEmmanuel Vadot }
30926a57869SEmmanuel Vadot 
31026a57869SEmmanuel Vadot static inline void
bitmap_to_arr32(uint32_t * dst,const unsigned long * src,unsigned int size)311e5cf9debSVladimir Kondratyev bitmap_to_arr32(uint32_t *dst, const unsigned long *src, unsigned int size)
312e5cf9debSVladimir Kondratyev {
313e5cf9debSVladimir Kondratyev 	const unsigned int end = howmany(size, 32);
314e5cf9debSVladimir Kondratyev 
315e5cf9debSVladimir Kondratyev #ifdef __LP64__
316e5cf9debSVladimir Kondratyev 	unsigned int i = 0;
317e5cf9debSVladimir Kondratyev 	while (i < end) {
318e5cf9debSVladimir Kondratyev 		dst[i++] = (uint32_t)(*src & UINT_MAX);
319e5cf9debSVladimir Kondratyev 		if (i < end)
320e5cf9debSVladimir Kondratyev 			dst[i++] = (uint32_t)(*src >> 32);
321e5cf9debSVladimir Kondratyev 		src++;
322e5cf9debSVladimir Kondratyev 	}
323e5cf9debSVladimir Kondratyev #else
32406c844e1SVladimir Kondratyev 	bitmap_copy((unsigned long *)dst, src, size);
325e5cf9debSVladimir Kondratyev #endif
326e5cf9debSVladimir Kondratyev 	if ((size % 32) != 0) /* Linux uses BITS_PER_LONG. Seems to be a bug */
327e5cf9debSVladimir Kondratyev 		dst[end - 1] &= (uint32_t)(UINT_MAX >> (32 - (size % 32)));
328e5cf9debSVladimir Kondratyev }
329e5cf9debSVladimir Kondratyev 
330e5cf9debSVladimir Kondratyev static inline void
bitmap_from_arr32(unsigned long * dst,const uint32_t * src,unsigned int size)3315ae2e6f9SVladimir Kondratyev bitmap_from_arr32(unsigned long *dst, const uint32_t *src,
3325ae2e6f9SVladimir Kondratyev     unsigned int size)
3335ae2e6f9SVladimir Kondratyev {
3345ae2e6f9SVladimir Kondratyev 	const unsigned int end = BIT_WORD(size);
3355ae2e6f9SVladimir Kondratyev 	const unsigned int tail = size & (BITS_PER_LONG - 1);
3365ae2e6f9SVladimir Kondratyev 
3375ae2e6f9SVladimir Kondratyev #ifdef __LP64__
3385ae2e6f9SVladimir Kondratyev 	const unsigned int end32 = howmany(size, 32);
3395ae2e6f9SVladimir Kondratyev 	unsigned int i = 0;
3405ae2e6f9SVladimir Kondratyev 
3415ae2e6f9SVladimir Kondratyev 	while (i < end32) {
3425ae2e6f9SVladimir Kondratyev 		dst[i++/2] = (unsigned long) *(src++);
3435ae2e6f9SVladimir Kondratyev 		if (i < end32)
3445ae2e6f9SVladimir Kondratyev 			dst[i++/2] |= ((unsigned long) *(src++)) << 32;
3455ae2e6f9SVladimir Kondratyev 	}
3465ae2e6f9SVladimir Kondratyev #else
347*dbca4424SVladimir Kondratyev 	bitmap_copy(dst, (const unsigned long *)src, size);
3485ae2e6f9SVladimir Kondratyev #endif
3495ae2e6f9SVladimir Kondratyev 	if ((size % BITS_PER_LONG) != 0)
3505ae2e6f9SVladimir Kondratyev 		dst[end] &= BITMAP_LAST_WORD_MASK(tail);
3515ae2e6f9SVladimir Kondratyev }
3525ae2e6f9SVladimir Kondratyev 
3535ae2e6f9SVladimir Kondratyev static inline void
bitmap_or(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)354c9dd0b48SHans Petter Selasky bitmap_or(unsigned long *dst, const unsigned long *src1,
355c9dd0b48SHans Petter Selasky     const unsigned long *src2, const unsigned int size)
356c9dd0b48SHans Petter Selasky {
357c9dd0b48SHans Petter Selasky 	const unsigned int end = BITS_TO_LONGS(size);
358c9dd0b48SHans Petter Selasky 	unsigned int i;
359c9dd0b48SHans Petter Selasky 
360c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++)
361c9dd0b48SHans Petter Selasky 		dst[i] = src1[i] | src2[i];
362c9dd0b48SHans Petter Selasky }
363c9dd0b48SHans Petter Selasky 
364c9dd0b48SHans Petter Selasky static inline void
bitmap_and(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)365c9dd0b48SHans Petter Selasky bitmap_and(unsigned long *dst, const unsigned long *src1,
366c9dd0b48SHans Petter Selasky     const unsigned long *src2, const unsigned int size)
367c9dd0b48SHans Petter Selasky {
368c9dd0b48SHans Petter Selasky 	const unsigned int end = BITS_TO_LONGS(size);
369c9dd0b48SHans Petter Selasky 	unsigned int i;
370c9dd0b48SHans Petter Selasky 
371c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++)
372c9dd0b48SHans Petter Selasky 		dst[i] = src1[i] & src2[i];
373c9dd0b48SHans Petter Selasky }
374c9dd0b48SHans Petter Selasky 
375c9dd0b48SHans Petter Selasky static inline void
bitmap_andnot(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)37626a57869SEmmanuel Vadot bitmap_andnot(unsigned long *dst, const unsigned long *src1,
37726a57869SEmmanuel Vadot     const unsigned long *src2, const unsigned int size)
37826a57869SEmmanuel Vadot {
37926a57869SEmmanuel Vadot 	const unsigned int end = BITS_TO_LONGS(size);
38026a57869SEmmanuel Vadot 	unsigned int i;
38126a57869SEmmanuel Vadot 
38226a57869SEmmanuel Vadot 	for (i = 0; i != end; i++)
38326a57869SEmmanuel Vadot 		dst[i] = src1[i] & ~src2[i];
38426a57869SEmmanuel Vadot }
38526a57869SEmmanuel Vadot 
38626a57869SEmmanuel Vadot static inline void
bitmap_xor(unsigned long * dst,const unsigned long * src1,const unsigned long * src2,const unsigned int size)387c9dd0b48SHans Petter Selasky bitmap_xor(unsigned long *dst, const unsigned long *src1,
388c9dd0b48SHans Petter Selasky     const unsigned long *src2, const unsigned int size)
389c9dd0b48SHans Petter Selasky {
390c9dd0b48SHans Petter Selasky 	const unsigned int end = BITS_TO_LONGS(size);
391c9dd0b48SHans Petter Selasky 	unsigned int i;
392c9dd0b48SHans Petter Selasky 
393c9dd0b48SHans Petter Selasky 	for (i = 0; i != end; i++)
394c9dd0b48SHans Petter Selasky 		dst[i] = src1[i] ^ src2[i];
395c9dd0b48SHans Petter Selasky }
396c9dd0b48SHans Petter Selasky 
3975ae2e6f9SVladimir Kondratyev static inline void
bitmap_shift_right(unsigned long * dst,const unsigned long * src,unsigned int shift,unsigned int size)3985ae2e6f9SVladimir Kondratyev bitmap_shift_right(unsigned long *dst, const unsigned long *src,
3995ae2e6f9SVladimir Kondratyev     unsigned int shift, unsigned int size)
4005ae2e6f9SVladimir Kondratyev {
4015ae2e6f9SVladimir Kondratyev 	const unsigned int end = BITS_TO_LONGS(size);
4025ae2e6f9SVladimir Kondratyev 	const unsigned int tail = size & (BITS_PER_LONG - 1);
4035ae2e6f9SVladimir Kondratyev 	const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
4045ae2e6f9SVladimir Kondratyev 	const unsigned int off = BIT_WORD(shift);
4055ae2e6f9SVladimir Kondratyev 	const unsigned int rem = shift & (BITS_PER_LONG - 1);
4065ae2e6f9SVladimir Kondratyev 	unsigned long left, right;
4075ae2e6f9SVladimir Kondratyev 	unsigned int i, srcpos;
4085ae2e6f9SVladimir Kondratyev 
4095ae2e6f9SVladimir Kondratyev 	for (i = 0, srcpos = off; srcpos < end; i++, srcpos++) {
4105ae2e6f9SVladimir Kondratyev 		right = src[srcpos];
4115ae2e6f9SVladimir Kondratyev 		left = 0;
4125ae2e6f9SVladimir Kondratyev 
4135ae2e6f9SVladimir Kondratyev 		if (srcpos == end - 1)
4145ae2e6f9SVladimir Kondratyev 			right &= mask;
4155ae2e6f9SVladimir Kondratyev 
4165ae2e6f9SVladimir Kondratyev 		if (rem != 0) {
4175ae2e6f9SVladimir Kondratyev 			right >>= rem;
4185ae2e6f9SVladimir Kondratyev 			if (srcpos + 1 < end) {
4195ae2e6f9SVladimir Kondratyev 				left = src[srcpos + 1];
4205ae2e6f9SVladimir Kondratyev 				if (srcpos + 1 == end - 1)
4215ae2e6f9SVladimir Kondratyev 					left &= mask;
4225ae2e6f9SVladimir Kondratyev 				left <<= (BITS_PER_LONG - rem);
4235ae2e6f9SVladimir Kondratyev 			}
4245ae2e6f9SVladimir Kondratyev 		}
4255ae2e6f9SVladimir Kondratyev 		dst[i] = left | right;
4265ae2e6f9SVladimir Kondratyev 	}
4275ae2e6f9SVladimir Kondratyev 	if (off != 0)
4285ae2e6f9SVladimir Kondratyev 		memset(dst + end - off, 0, off * sizeof(unsigned long));
4295ae2e6f9SVladimir Kondratyev }
4305ae2e6f9SVladimir Kondratyev 
4313d84874dSEmmanuel Vadot static inline unsigned long *
bitmap_alloc(unsigned int size,gfp_t flags)4323d84874dSEmmanuel Vadot bitmap_alloc(unsigned int size, gfp_t flags)
4333d84874dSEmmanuel Vadot {
4343d84874dSEmmanuel Vadot 	return (kmalloc_array(BITS_TO_LONGS(size),
4353d84874dSEmmanuel Vadot 	    sizeof(unsigned long), flags));
4363d84874dSEmmanuel Vadot }
4373d84874dSEmmanuel Vadot 
4383d84874dSEmmanuel Vadot static inline unsigned long *
bitmap_zalloc(unsigned int size,gfp_t flags)4393d84874dSEmmanuel Vadot bitmap_zalloc(unsigned int size, gfp_t flags)
4403d84874dSEmmanuel Vadot {
4413d84874dSEmmanuel Vadot 	return (bitmap_alloc(size, flags | __GFP_ZERO));
4423d84874dSEmmanuel Vadot }
4433d84874dSEmmanuel Vadot 
444ce03b301SEmmanuel Vadot static inline void
bitmap_free(const unsigned long * bitmap)445ce03b301SEmmanuel Vadot bitmap_free(const unsigned long *bitmap)
446ce03b301SEmmanuel Vadot {
447ce03b301SEmmanuel Vadot 	kfree(bitmap);
448ce03b301SEmmanuel Vadot }
449ce03b301SEmmanuel Vadot 
450307f78f3SVladimir Kondratyev #endif					/* _LINUXKPI_LINUX_BITMAP_H_ */
451