bitmap.h revision 1.6 1 /* $NetBSD: bitmap.h,v 1.6 2018/08/27 14:50:52 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _LINUX_BITMAP_H_
33 #define _LINUX_BITMAP_H_
34
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/systm.h>
38
39 /*
40 * bitmap_zero(bitmap, nbits)
41 *
42 * Zero a bitmap that was allocated to have nbits bits. Yes, this
43 * zeros bits past nbits.
44 */
45 static inline void
46 bitmap_zero(unsigned long *bitmap, size_t nbits)
47 {
48 const size_t bpl = NBBY * sizeof(*bitmap);
49
50 memset(bitmap, 0, howmany(nbits, bpl) * sizeof(*bitmap));
51 }
52
53 /*
54 * bitmap_empty(bitmap, nbits)
55 *
56 * Return true if all bits at 0, 1, 2, ..., nbits-2, nbits-1 are
57 * 0, or false if any of them is 1.
58 */
59 static inline bool
60 bitmap_empty(const unsigned long *bitmap, size_t nbits)
61 {
62 const size_t bpl = NBBY * sizeof(*bitmap);
63
64 for (; nbits >= bpl; nbits -= bpl) {
65 if (*bitmap++)
66 return false;
67 }
68
69 if (nbits) {
70 if (*bitmap & ~(~0UL << nbits))
71 return false;
72 }
73
74 return true;
75 }
76
77 /*
78 * bitmap_weight(bitmap, nbits)
79 *
80 * Compute the number of 1 bits at 0, 1, 2, ..., nbits-2, nbits-1.
81 */
82 static inline int
83 bitmap_weight(const unsigned long *bitmap, size_t nbits)
84 {
85 const size_t bpl = NBBY * sizeof(*bitmap);
86 int weight = 0;
87
88 for (; nbits >= bpl; nbits -= bpl)
89 weight += popcountl(*bitmap++);
90 if (nbits)
91 weight += popcountl(*bitmap & ~(~0UL << nbits));
92
93 return weight;
94 }
95
96 /*
97 * bitmap_set(bitmap, startbit, nbits)
98 *
99 * Set bits at startbit, startbit+1, ..., startbit+nbits-2,
100 * startbit+nbits-1 to 1.
101 */
102 static inline void
103 bitmap_set(unsigned long *bitmap, size_t startbit, size_t nbits)
104 {
105 const size_t bpl = NBBY * sizeof(*bitmap);
106 unsigned long *p = bitmap + startbit/bpl;
107 unsigned long mask;
108 unsigned sz;
109
110 for (sz = bpl - (startbit%bpl), mask = ~0UL << (startbit%bpl);
111 nbits >= sz;
112 nbits -= sz, sz = bpl, mask = ~0UL)
113 *p++ |= mask;
114
115 if (nbits)
116 *p |= mask & ~(~0UL << (nbits + bpl - sz));
117 }
118
119 /*
120 * bitmap_clear(bitmap, startbit, nbits)
121 *
122 * Clear bits at startbit, startbit+1, ..., startbit+nbits-2,
123 * startbit+nbits-1, replacing them by 0.
124 */
125 static inline void
126 bitmap_clear(unsigned long *bitmap, size_t startbit, size_t nbits)
127 {
128 const size_t bpl = NBBY * sizeof(*bitmap);
129 unsigned long *p = bitmap + startbit/bpl;
130 unsigned long mask;
131 unsigned sz;
132
133 for (sz = bpl - (startbit%bpl), mask = ~(~0UL << (startbit%bpl));
134 nbits >= sz;
135 nbits -= sz, sz = bpl, mask = 0UL)
136 *p++ &= mask;
137
138 if (nbits)
139 *p &= mask | (~0UL << (nbits + bpl - sz));
140 }
141
142 /*
143 * bitmap_and(dst, src1, src2, nbits)
144 *
145 * Set dst to be the bitwise AND of src1 and src2, all bitmaps
146 * allocated to have nbits bits. Yes, this modifies bits past
147 * nbits. Any pair of {dst, src1, src2} may be aliases.
148 */
149 static inline void
150 bitmap_and(unsigned long *dst, const unsigned long *src1,
151 const unsigned long *src2, size_t nbits)
152 {
153 const size_t bpl = NBBY * sizeof(unsigned long);
154 size_t n = howmany(nbits, bpl);
155
156 while (n --> 0)
157 *dst++ = *src1++ & *src2++;
158 }
159
160 /*
161 * bitmap_or(dst, src1, src2, nbits)
162 *
163 * Set dst to be the bitwise inclusive-OR of src1 and src2, all
164 * bitmaps allocated to have nbits bits. Yes, this modifies bits
165 * past nbits. Any pair of {dst, src1, src2} may be aliases.
166 */
167 static inline void
168 bitmap_or(unsigned long *dst, const unsigned long *src1,
169 const unsigned long *src2, size_t nbits)
170 {
171 const size_t bpl = NBBY * sizeof(unsigned long);
172 size_t n = howmany(nbits, bpl);
173
174 while (n --> 0)
175 *dst++ = *src1++ | *src2++;
176 }
177
178 #endif /* _LINUX_BITMAP_H_ */
179