1 1.13 riastrad /* $NetBSD: bitmap.h,v 1.13 2021/12/19 12:21:30 riastradh Exp $ */ 2 1.2 riastrad 3 1.2 riastrad /*- 4 1.3 riastrad * Copyright (c) 2018 The NetBSD Foundation, Inc. 5 1.2 riastrad * All rights reserved. 6 1.2 riastrad * 7 1.2 riastrad * This code is derived from software contributed to The NetBSD Foundation 8 1.2 riastrad * by Taylor R. Campbell. 9 1.2 riastrad * 10 1.2 riastrad * Redistribution and use in source and binary forms, with or without 11 1.2 riastrad * modification, are permitted provided that the following conditions 12 1.2 riastrad * are met: 13 1.2 riastrad * 1. Redistributions of source code must retain the above copyright 14 1.2 riastrad * notice, this list of conditions and the following disclaimer. 15 1.2 riastrad * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 riastrad * notice, this list of conditions and the following disclaimer in the 17 1.2 riastrad * documentation and/or other materials provided with the distribution. 18 1.2 riastrad * 19 1.2 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 riastrad * POSSIBILITY OF SUCH DAMAGE. 30 1.2 riastrad */ 31 1.2 riastrad 32 1.2 riastrad #ifndef _LINUX_BITMAP_H_ 33 1.2 riastrad #define _LINUX_BITMAP_H_ 34 1.2 riastrad 35 1.3 riastrad #include <sys/param.h> 36 1.3 riastrad #include <sys/types.h> 37 1.3 riastrad #include <sys/systm.h> 38 1.3 riastrad 39 1.10 riastrad #include <linux/slab.h> 40 1.10 riastrad 41 1.3 riastrad /* 42 1.3 riastrad * bitmap_zero(bitmap, nbits) 43 1.3 riastrad * 44 1.3 riastrad * Zero a bitmap that was allocated to have nbits bits. Yes, this 45 1.3 riastrad * zeros bits past nbits. 46 1.3 riastrad */ 47 1.3 riastrad static inline void 48 1.3 riastrad bitmap_zero(unsigned long *bitmap, size_t nbits) 49 1.3 riastrad { 50 1.3 riastrad const size_t bpl = NBBY * sizeof(*bitmap); 51 1.7 riastrad size_t n = howmany(nbits, bpl); 52 1.3 riastrad 53 1.7 riastrad memset(bitmap, 0, n * sizeof(*bitmap)); 54 1.3 riastrad } 55 1.3 riastrad 56 1.3 riastrad /* 57 1.3 riastrad * bitmap_empty(bitmap, nbits) 58 1.3 riastrad * 59 1.3 riastrad * Return true if all bits at 0, 1, 2, ..., nbits-2, nbits-1 are 60 1.3 riastrad * 0, or false if any of them is 1. 61 1.3 riastrad */ 62 1.3 riastrad static inline bool 63 1.3 riastrad bitmap_empty(const unsigned long *bitmap, size_t nbits) 64 1.3 riastrad { 65 1.3 riastrad const size_t bpl = NBBY * sizeof(*bitmap); 66 1.3 riastrad 67 1.6 riastrad for (; nbits >= bpl; nbits -= bpl) { 68 1.3 riastrad if (*bitmap++) 69 1.3 riastrad return false; 70 1.3 riastrad } 71 1.3 riastrad 72 1.3 riastrad if (nbits) { 73 1.3 riastrad if (*bitmap & ~(~0UL << nbits)) 74 1.3 riastrad return false; 75 1.3 riastrad } 76 1.3 riastrad 77 1.3 riastrad return true; 78 1.3 riastrad } 79 1.3 riastrad 80 1.3 riastrad /* 81 1.3 riastrad * bitmap_weight(bitmap, nbits) 82 1.3 riastrad * 83 1.3 riastrad * Compute the number of 1 bits at 0, 1, 2, ..., nbits-2, nbits-1. 84 1.3 riastrad */ 85 1.3 riastrad static inline int 86 1.3 riastrad bitmap_weight(const unsigned long *bitmap, size_t nbits) 87 1.3 riastrad { 88 1.3 riastrad const size_t bpl = NBBY * sizeof(*bitmap); 89 1.3 riastrad int weight = 0; 90 1.3 riastrad 91 1.6 riastrad for (; nbits >= bpl; nbits -= bpl) 92 1.3 riastrad weight += popcountl(*bitmap++); 93 1.3 riastrad if (nbits) 94 1.3 riastrad weight += popcountl(*bitmap & ~(~0UL << nbits)); 95 1.3 riastrad 96 1.3 riastrad return weight; 97 1.3 riastrad } 98 1.3 riastrad 99 1.3 riastrad /* 100 1.3 riastrad * bitmap_set(bitmap, startbit, nbits) 101 1.3 riastrad * 102 1.4 riastrad * Set bits at startbit, startbit+1, ..., startbit+nbits-2, 103 1.4 riastrad * startbit+nbits-1 to 1. 104 1.3 riastrad */ 105 1.3 riastrad static inline void 106 1.3 riastrad bitmap_set(unsigned long *bitmap, size_t startbit, size_t nbits) 107 1.3 riastrad { 108 1.3 riastrad const size_t bpl = NBBY * sizeof(*bitmap); 109 1.4 riastrad unsigned long *p = bitmap + startbit/bpl; 110 1.8 riastrad unsigned initial = startbit%bpl; 111 1.3 riastrad 112 1.8 riastrad /* Handle an initial odd word if any. */ 113 1.8 riastrad if (initial) { 114 1.8 riastrad /* Does the whole thing fit in a single word? */ 115 1.8 riastrad if (nbits <= bpl - initial) { 116 1.8 riastrad /* Yes: just set nbits starting at initial. */ 117 1.8 riastrad *p |= ~(~0ULL << nbits) << initial; 118 1.8 riastrad return; 119 1.8 riastrad } 120 1.8 riastrad /* Nope: set all bits above initial, and advance. */ 121 1.8 riastrad *p++ |= ~0ULL << initial; 122 1.8 riastrad nbits -= bpl - initial; 123 1.8 riastrad } 124 1.8 riastrad 125 1.8 riastrad /* Set the middle part to all bits 1. */ 126 1.8 riastrad for (; nbits >= bpl; nbits -= bpl) 127 1.8 riastrad *p++ = ~0UL; 128 1.3 riastrad 129 1.8 riastrad /* Handle a final odd word if any by setting its low nbits. */ 130 1.3 riastrad if (nbits) 131 1.8 riastrad *p |= ~(~0ULL << nbits); 132 1.3 riastrad } 133 1.3 riastrad 134 1.3 riastrad /* 135 1.4 riastrad * bitmap_clear(bitmap, startbit, nbits) 136 1.3 riastrad * 137 1.4 riastrad * Clear bits at startbit, startbit+1, ..., startbit+nbits-2, 138 1.4 riastrad * startbit+nbits-1, replacing them by 0. 139 1.3 riastrad */ 140 1.3 riastrad static inline void 141 1.3 riastrad bitmap_clear(unsigned long *bitmap, size_t startbit, size_t nbits) 142 1.3 riastrad { 143 1.3 riastrad const size_t bpl = NBBY * sizeof(*bitmap); 144 1.4 riastrad unsigned long *p = bitmap + startbit/bpl; 145 1.8 riastrad unsigned initial = startbit%bpl; 146 1.3 riastrad 147 1.8 riastrad /* Handle an initial odd word if any. */ 148 1.8 riastrad if (initial) { 149 1.8 riastrad /* Does the whole thing fit in a single word? */ 150 1.8 riastrad if (nbits <= bpl - initial) { 151 1.8 riastrad /* Yes: just clear nbits starting at initial. */ 152 1.8 riastrad *p &= ~(~(~0ULL << nbits) << initial); 153 1.8 riastrad return; 154 1.8 riastrad } 155 1.8 riastrad /* Nope: clear all bits above initial, and advance. */ 156 1.8 riastrad *p++ &= ~(~0ULL << initial); 157 1.8 riastrad nbits -= bpl - initial; 158 1.8 riastrad } 159 1.8 riastrad 160 1.8 riastrad /* Zero the middle part. */ 161 1.8 riastrad for (; nbits >= bpl; nbits -= bpl) 162 1.8 riastrad *p++ = 0UL; 163 1.3 riastrad 164 1.8 riastrad /* Handle a final odd word if any by clearing its low nbits. */ 165 1.3 riastrad if (nbits) 166 1.8 riastrad *p &= ~0ULL << nbits; 167 1.3 riastrad } 168 1.3 riastrad 169 1.3 riastrad /* 170 1.13 riastrad * bitmap_copy(dst, src, nbits) 171 1.13 riastrad * 172 1.13 riastrad * Copy the bitmap from src to dst. dst and src may alias (but 173 1.13 riastrad * why would you bother?). 174 1.13 riastrad */ 175 1.13 riastrad static inline void 176 1.13 riastrad bitmap_copy(unsigned long *dst, const unsigned long *src, size_t nbits) 177 1.13 riastrad { 178 1.13 riastrad const size_t bpl = NBBY * sizeof(unsigned long); 179 1.13 riastrad size_t n = howmany(nbits, bpl); 180 1.13 riastrad 181 1.13 riastrad while (n --> 0) 182 1.13 riastrad *dst++ = *src++; 183 1.13 riastrad } 184 1.13 riastrad 185 1.13 riastrad /* 186 1.9 riastrad * bitmap_complement(dst, src, nbits) 187 1.9 riastrad * 188 1.9 riastrad * Set dst to the the bitwise NOT of src. dst and src may alias. 189 1.9 riastrad */ 190 1.9 riastrad static inline void 191 1.9 riastrad bitmap_complement(unsigned long *dst, const unsigned long *src, size_t nbits) 192 1.9 riastrad { 193 1.9 riastrad const size_t bpl = NBBY * sizeof(unsigned long); 194 1.9 riastrad size_t n = howmany(nbits, bpl); 195 1.9 riastrad 196 1.9 riastrad while (n --> 0) 197 1.9 riastrad *dst++ = ~*src++; 198 1.9 riastrad } 199 1.9 riastrad 200 1.9 riastrad /* 201 1.3 riastrad * bitmap_and(dst, src1, src2, nbits) 202 1.3 riastrad * 203 1.3 riastrad * Set dst to be the bitwise AND of src1 and src2, all bitmaps 204 1.3 riastrad * allocated to have nbits bits. Yes, this modifies bits past 205 1.5 riastrad * nbits. Any pair of {dst, src1, src2} may be aliases. 206 1.3 riastrad */ 207 1.3 riastrad static inline void 208 1.3 riastrad bitmap_and(unsigned long *dst, const unsigned long *src1, 209 1.3 riastrad const unsigned long *src2, size_t nbits) 210 1.3 riastrad { 211 1.5 riastrad const size_t bpl = NBBY * sizeof(unsigned long); 212 1.5 riastrad size_t n = howmany(nbits, bpl); 213 1.3 riastrad 214 1.3 riastrad while (n --> 0) 215 1.3 riastrad *dst++ = *src1++ & *src2++; 216 1.3 riastrad } 217 1.3 riastrad 218 1.3 riastrad /* 219 1.13 riastrad * bitmap_andnot(dst, src1, src2, nbits) 220 1.13 riastrad * 221 1.13 riastrad * Set dst to be the bitwise AND of src1 and ~src2, all bitmaps 222 1.13 riastrad * allocated to have nbits bits. Yes, this modifies bits past 223 1.13 riastrad * nbits. Any pair of {dst, src1, src2} may be aliases. 224 1.13 riastrad */ 225 1.13 riastrad static inline void 226 1.13 riastrad bitmap_andnot(unsigned long *dst, const unsigned long *src1, 227 1.13 riastrad const unsigned long *src2, size_t nbits) 228 1.13 riastrad { 229 1.13 riastrad const size_t bpl = NBBY * sizeof(unsigned long); 230 1.13 riastrad size_t n = howmany(nbits, bpl); 231 1.13 riastrad 232 1.13 riastrad while (n --> 0) 233 1.13 riastrad *dst++ = *src1++ & ~*src2++; 234 1.13 riastrad } 235 1.13 riastrad 236 1.13 riastrad /* 237 1.5 riastrad * bitmap_or(dst, src1, src2, nbits) 238 1.3 riastrad * 239 1.3 riastrad * Set dst to be the bitwise inclusive-OR of src1 and src2, all 240 1.3 riastrad * bitmaps allocated to have nbits bits. Yes, this modifies bits 241 1.5 riastrad * past nbits. Any pair of {dst, src1, src2} may be aliases. 242 1.3 riastrad */ 243 1.3 riastrad static inline void 244 1.3 riastrad bitmap_or(unsigned long *dst, const unsigned long *src1, 245 1.3 riastrad const unsigned long *src2, size_t nbits) 246 1.3 riastrad { 247 1.5 riastrad const size_t bpl = NBBY * sizeof(unsigned long); 248 1.5 riastrad size_t n = howmany(nbits, bpl); 249 1.3 riastrad 250 1.3 riastrad while (n --> 0) 251 1.3 riastrad *dst++ = *src1++ | *src2++; 252 1.3 riastrad } 253 1.3 riastrad 254 1.10 riastrad static inline unsigned long * 255 1.11 riastrad bitmap_zalloc(size_t nbits, gfp_t gfp) 256 1.11 riastrad { 257 1.11 riastrad const size_t bpl = NBBY * sizeof(unsigned long); 258 1.11 riastrad size_t n = howmany(nbits, bpl); 259 1.11 riastrad 260 1.11 riastrad return kcalloc(n, sizeof(unsigned long), gfp); 261 1.10 riastrad } 262 1.10 riastrad 263 1.12 riastrad static inline void 264 1.12 riastrad bitmap_free(unsigned long *bitmap) 265 1.12 riastrad { 266 1.12 riastrad 267 1.12 riastrad kfree(bitmap); 268 1.12 riastrad } 269 1.12 riastrad 270 1.2 riastrad #endif /* _LINUX_BITMAP_H_ */ 271