1a9643ea8Slogwang /*- 2*22ce4affSfengbojiang * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*22ce4affSfengbojiang * 4a9643ea8Slogwang * Copyright (c) 2008, Jeffrey Roberson <[email protected]> 5a9643ea8Slogwang * All rights reserved. 6a9643ea8Slogwang * 7a9643ea8Slogwang * Copyright (c) 2008 Nokia Corporation 8a9643ea8Slogwang * All rights reserved. 9a9643ea8Slogwang * 10a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 11a9643ea8Slogwang * modification, are permitted provided that the following conditions 12a9643ea8Slogwang * are met: 13a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright 14a9643ea8Slogwang * notice unmodified, this list of conditions, and the following 15a9643ea8Slogwang * disclaimer. 16a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright 17a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the 18a9643ea8Slogwang * documentation and/or other materials provided with the distribution. 19a9643ea8Slogwang * 20a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21a9643ea8Slogwang * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22a9643ea8Slogwang * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23a9643ea8Slogwang * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24a9643ea8Slogwang * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25a9643ea8Slogwang * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26a9643ea8Slogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27a9643ea8Slogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28a9643ea8Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29a9643ea8Slogwang * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30a9643ea8Slogwang * 31a9643ea8Slogwang * $FreeBSD$ 32a9643ea8Slogwang */ 33a9643ea8Slogwang 34a9643ea8Slogwang #ifndef _SYS_BITSET_H_ 35a9643ea8Slogwang #define _SYS_BITSET_H_ 36a9643ea8Slogwang 37*22ce4affSfengbojiang /* 38*22ce4affSfengbojiang * Whether expr is both constant and true. Result is itself constant. 39*22ce4affSfengbojiang * Used to enable optimizations for sets with a known small size. 40*22ce4affSfengbojiang */ 41*22ce4affSfengbojiang #define __constexpr_cond(expr) (__builtin_constant_p((expr)) && (expr)) 42*22ce4affSfengbojiang 43a9643ea8Slogwang #define __bitset_mask(_s, n) \ 44*22ce4affSfengbojiang (1UL << (__constexpr_cond(__bitset_words((_s)) == 1) ? \ 45a9643ea8Slogwang (__size_t)(n) : ((n) % _BITSET_BITS))) 46a9643ea8Slogwang 47a9643ea8Slogwang #define __bitset_word(_s, n) \ 48*22ce4affSfengbojiang (__constexpr_cond(__bitset_words((_s)) == 1) ? \ 49*22ce4affSfengbojiang 0 : ((n) / _BITSET_BITS)) 50a9643ea8Slogwang 51a9643ea8Slogwang #define BIT_CLR(_s, n, p) \ 52a9643ea8Slogwang ((p)->__bits[__bitset_word(_s, n)] &= ~__bitset_mask((_s), (n))) 53a9643ea8Slogwang 54a9643ea8Slogwang #define BIT_COPY(_s, f, t) (void)(*(t) = *(f)) 55a9643ea8Slogwang 56a9643ea8Slogwang #define BIT_ISSET(_s, n, p) \ 57a9643ea8Slogwang ((((p)->__bits[__bitset_word(_s, n)] & __bitset_mask((_s), (n))) != 0)) 58a9643ea8Slogwang 59a9643ea8Slogwang #define BIT_SET(_s, n, p) \ 60a9643ea8Slogwang ((p)->__bits[__bitset_word(_s, n)] |= __bitset_mask((_s), (n))) 61a9643ea8Slogwang 62a9643ea8Slogwang #define BIT_ZERO(_s, p) do { \ 63a9643ea8Slogwang __size_t __i; \ 64a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 65a9643ea8Slogwang (p)->__bits[__i] = 0L; \ 66a9643ea8Slogwang } while (0) 67a9643ea8Slogwang 68a9643ea8Slogwang #define BIT_FILL(_s, p) do { \ 69a9643ea8Slogwang __size_t __i; \ 70a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 71a9643ea8Slogwang (p)->__bits[__i] = -1L; \ 72a9643ea8Slogwang } while (0) 73a9643ea8Slogwang 74a9643ea8Slogwang #define BIT_SETOF(_s, n, p) do { \ 75a9643ea8Slogwang BIT_ZERO(_s, p); \ 76a9643ea8Slogwang (p)->__bits[__bitset_word(_s, n)] = __bitset_mask((_s), (n)); \ 77a9643ea8Slogwang } while (0) 78a9643ea8Slogwang 79a9643ea8Slogwang /* Is p empty. */ 80a9643ea8Slogwang #define BIT_EMPTY(_s, p) __extension__ ({ \ 81a9643ea8Slogwang __size_t __i; \ 82a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 83a9643ea8Slogwang if ((p)->__bits[__i]) \ 84a9643ea8Slogwang break; \ 85a9643ea8Slogwang __i == __bitset_words((_s)); \ 86a9643ea8Slogwang }) 87a9643ea8Slogwang 88a9643ea8Slogwang /* Is p full set. */ 89a9643ea8Slogwang #define BIT_ISFULLSET(_s, p) __extension__ ({ \ 90a9643ea8Slogwang __size_t __i; \ 91a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 92a9643ea8Slogwang if ((p)->__bits[__i] != (long)-1) \ 93a9643ea8Slogwang break; \ 94a9643ea8Slogwang __i == __bitset_words((_s)); \ 95a9643ea8Slogwang }) 96a9643ea8Slogwang 97a9643ea8Slogwang /* Is c a subset of p. */ 98a9643ea8Slogwang #define BIT_SUBSET(_s, p, c) __extension__ ({ \ 99a9643ea8Slogwang __size_t __i; \ 100a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 101a9643ea8Slogwang if (((c)->__bits[__i] & \ 102a9643ea8Slogwang (p)->__bits[__i]) != \ 103a9643ea8Slogwang (c)->__bits[__i]) \ 104a9643ea8Slogwang break; \ 105a9643ea8Slogwang __i == __bitset_words((_s)); \ 106a9643ea8Slogwang }) 107a9643ea8Slogwang 108a9643ea8Slogwang /* Are there any common bits between b & c? */ 109a9643ea8Slogwang #define BIT_OVERLAP(_s, p, c) __extension__ ({ \ 110a9643ea8Slogwang __size_t __i; \ 111a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 112a9643ea8Slogwang if (((c)->__bits[__i] & \ 113a9643ea8Slogwang (p)->__bits[__i]) != 0) \ 114a9643ea8Slogwang break; \ 115a9643ea8Slogwang __i != __bitset_words((_s)); \ 116a9643ea8Slogwang }) 117a9643ea8Slogwang 118a9643ea8Slogwang /* Compare two sets, returns 0 if equal 1 otherwise. */ 119a9643ea8Slogwang #define BIT_CMP(_s, p, c) __extension__ ({ \ 120a9643ea8Slogwang __size_t __i; \ 121a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 122a9643ea8Slogwang if (((c)->__bits[__i] != \ 123a9643ea8Slogwang (p)->__bits[__i])) \ 124a9643ea8Slogwang break; \ 125a9643ea8Slogwang __i != __bitset_words((_s)); \ 126a9643ea8Slogwang }) 127a9643ea8Slogwang 128a9643ea8Slogwang #define BIT_OR(_s, d, s) do { \ 129a9643ea8Slogwang __size_t __i; \ 130a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 131a9643ea8Slogwang (d)->__bits[__i] |= (s)->__bits[__i]; \ 132a9643ea8Slogwang } while (0) 133a9643ea8Slogwang 134*22ce4affSfengbojiang #define BIT_OR2(_s, d, s1, s2) do { \ 135*22ce4affSfengbojiang __size_t __i; \ 136*22ce4affSfengbojiang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 137*22ce4affSfengbojiang (d)->__bits[__i] = (s1)->__bits[__i] | (s2)->__bits[__i];\ 138*22ce4affSfengbojiang } while (0) 139*22ce4affSfengbojiang 140a9643ea8Slogwang #define BIT_AND(_s, d, s) do { \ 141a9643ea8Slogwang __size_t __i; \ 142a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 143a9643ea8Slogwang (d)->__bits[__i] &= (s)->__bits[__i]; \ 144a9643ea8Slogwang } while (0) 145a9643ea8Slogwang 146*22ce4affSfengbojiang #define BIT_AND2(_s, d, s1, s2) do { \ 147*22ce4affSfengbojiang __size_t __i; \ 148*22ce4affSfengbojiang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 149*22ce4affSfengbojiang (d)->__bits[__i] = (s1)->__bits[__i] & (s2)->__bits[__i];\ 150*22ce4affSfengbojiang } while (0) 151*22ce4affSfengbojiang 152*22ce4affSfengbojiang #define BIT_ANDNOT(_s, d, s) do { \ 153a9643ea8Slogwang __size_t __i; \ 154a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 155a9643ea8Slogwang (d)->__bits[__i] &= ~(s)->__bits[__i]; \ 156a9643ea8Slogwang } while (0) 157a9643ea8Slogwang 158*22ce4affSfengbojiang #define BIT_ANDNOT2(_s, d, s1, s2) do { \ 159*22ce4affSfengbojiang __size_t __i; \ 160*22ce4affSfengbojiang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 161*22ce4affSfengbojiang (d)->__bits[__i] = (s1)->__bits[__i] & ~(s2)->__bits[__i];\ 162*22ce4affSfengbojiang } while (0) 163*22ce4affSfengbojiang 164*22ce4affSfengbojiang #define BIT_XOR(_s, d, s) do { \ 165*22ce4affSfengbojiang __size_t __i; \ 166*22ce4affSfengbojiang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 167*22ce4affSfengbojiang (d)->__bits[__i] ^= (s)->__bits[__i]; \ 168*22ce4affSfengbojiang } while (0) 169*22ce4affSfengbojiang 170*22ce4affSfengbojiang #define BIT_XOR2(_s, d, s1, s2) do { \ 171*22ce4affSfengbojiang __size_t __i; \ 172*22ce4affSfengbojiang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 173*22ce4affSfengbojiang (d)->__bits[__i] = (s1)->__bits[__i] ^ (s2)->__bits[__i];\ 174*22ce4affSfengbojiang } while (0) 175*22ce4affSfengbojiang 176*22ce4affSfengbojiang /* 177*22ce4affSfengbojiang * Note, the atomic(9) API is not consistent between clear/set and 178*22ce4affSfengbojiang * testandclear/testandset in whether the value argument is a mask 179*22ce4affSfengbojiang * or a bit index. 180*22ce4affSfengbojiang */ 181*22ce4affSfengbojiang 182a9643ea8Slogwang #define BIT_CLR_ATOMIC(_s, n, p) \ 183a9643ea8Slogwang atomic_clear_long(&(p)->__bits[__bitset_word(_s, n)], \ 184a9643ea8Slogwang __bitset_mask((_s), n)) 185a9643ea8Slogwang 186a9643ea8Slogwang #define BIT_SET_ATOMIC(_s, n, p) \ 187a9643ea8Slogwang atomic_set_long(&(p)->__bits[__bitset_word(_s, n)], \ 188a9643ea8Slogwang __bitset_mask((_s), n)) 189a9643ea8Slogwang 190a9643ea8Slogwang #define BIT_SET_ATOMIC_ACQ(_s, n, p) \ 191a9643ea8Slogwang atomic_set_acq_long(&(p)->__bits[__bitset_word(_s, n)], \ 192a9643ea8Slogwang __bitset_mask((_s), n)) 193a9643ea8Slogwang 194*22ce4affSfengbojiang #define BIT_TEST_CLR_ATOMIC(_s, n, p) \ 195*22ce4affSfengbojiang (atomic_testandclear_long( \ 196*22ce4affSfengbojiang &(p)->__bits[__bitset_word((_s), (n))], (n)) != 0) 197*22ce4affSfengbojiang 198*22ce4affSfengbojiang #define BIT_TEST_SET_ATOMIC(_s, n, p) \ 199*22ce4affSfengbojiang (atomic_testandset_long( \ 200*22ce4affSfengbojiang &(p)->__bits[__bitset_word((_s), (n))], (n)) != 0) 201*22ce4affSfengbojiang 202a9643ea8Slogwang /* Convenience functions catering special cases. */ 203a9643ea8Slogwang #define BIT_AND_ATOMIC(_s, d, s) do { \ 204a9643ea8Slogwang __size_t __i; \ 205a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 206a9643ea8Slogwang atomic_clear_long(&(d)->__bits[__i], \ 207a9643ea8Slogwang ~(s)->__bits[__i]); \ 208a9643ea8Slogwang } while (0) 209a9643ea8Slogwang 210a9643ea8Slogwang #define BIT_OR_ATOMIC(_s, d, s) do { \ 211a9643ea8Slogwang __size_t __i; \ 212a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 213a9643ea8Slogwang atomic_set_long(&(d)->__bits[__i], \ 214a9643ea8Slogwang (s)->__bits[__i]); \ 215a9643ea8Slogwang } while (0) 216a9643ea8Slogwang 217a9643ea8Slogwang #define BIT_COPY_STORE_REL(_s, f, t) do { \ 218a9643ea8Slogwang __size_t __i; \ 219a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 220a9643ea8Slogwang atomic_store_rel_long(&(t)->__bits[__i], \ 221a9643ea8Slogwang (f)->__bits[__i]); \ 222a9643ea8Slogwang } while (0) 223a9643ea8Slogwang 224*22ce4affSfengbojiang /* 225*22ce4affSfengbojiang * Note that `start` and the returned value from BIT_FFS_AT are 226*22ce4affSfengbojiang * 1-based bit indices. 227*22ce4affSfengbojiang */ 228*22ce4affSfengbojiang #define BIT_FFS_AT(_s, p, start) __extension__ ({ \ 229a9643ea8Slogwang __size_t __i; \ 230*22ce4affSfengbojiang long __bit, __mask; \ 231*22ce4affSfengbojiang \ 232*22ce4affSfengbojiang __mask = ~0UL << ((start) % _BITSET_BITS); \ 233*22ce4affSfengbojiang __bit = 0; \ 234*22ce4affSfengbojiang for (__i = __bitset_word((_s), (start)); \ 235*22ce4affSfengbojiang __i < __bitset_words((_s)); \ 236*22ce4affSfengbojiang __i++) { \ 237*22ce4affSfengbojiang if (((p)->__bits[__i] & __mask) != 0) { \ 238*22ce4affSfengbojiang __bit = ffsl((p)->__bits[__i] & __mask); \ 239*22ce4affSfengbojiang __bit += __i * _BITSET_BITS; \ 240*22ce4affSfengbojiang break; \ 241*22ce4affSfengbojiang } \ 242*22ce4affSfengbojiang __mask = ~0UL; \ 243*22ce4affSfengbojiang } \ 244*22ce4affSfengbojiang __bit; \ 245*22ce4affSfengbojiang }) 246*22ce4affSfengbojiang 247*22ce4affSfengbojiang #define BIT_FFS(_s, p) BIT_FFS_AT((_s), (p), 0) 248*22ce4affSfengbojiang 249*22ce4affSfengbojiang #define BIT_FLS(_s, p) __extension__ ({ \ 250*22ce4affSfengbojiang __size_t __i; \ 251*22ce4affSfengbojiang long __bit; \ 252a9643ea8Slogwang \ 253a9643ea8Slogwang __bit = 0; \ 254*22ce4affSfengbojiang for (__i = __bitset_words((_s)); __i > 0; __i--) { \ 255*22ce4affSfengbojiang if ((p)->__bits[__i - 1] != 0) { \ 256*22ce4affSfengbojiang __bit = flsl((p)->__bits[__i - 1]); \ 257*22ce4affSfengbojiang __bit += (__i - 1) * _BITSET_BITS; \ 258a9643ea8Slogwang break; \ 259a9643ea8Slogwang } \ 260a9643ea8Slogwang } \ 261a9643ea8Slogwang __bit; \ 262a9643ea8Slogwang }) 263a9643ea8Slogwang 264a9643ea8Slogwang #define BIT_COUNT(_s, p) __extension__ ({ \ 265a9643ea8Slogwang __size_t __i; \ 266*22ce4affSfengbojiang long __count; \ 267a9643ea8Slogwang \ 268a9643ea8Slogwang __count = 0; \ 269a9643ea8Slogwang for (__i = 0; __i < __bitset_words((_s)); __i++) \ 270a9643ea8Slogwang __count += __bitcountl((p)->__bits[__i]); \ 271a9643ea8Slogwang __count; \ 272a9643ea8Slogwang }) 273a9643ea8Slogwang 274a9643ea8Slogwang #define BITSET_T_INITIALIZER(x) \ 275a9643ea8Slogwang { .__bits = { x } } 276a9643ea8Slogwang 277a9643ea8Slogwang #define BITSET_FSET(n) \ 278a9643ea8Slogwang [ 0 ... ((n) - 1) ] = (-1L) 279a9643ea8Slogwang 280*22ce4affSfengbojiang #define BITSET_SIZE(_s) (__bitset_words((_s)) * sizeof(long)) 281*22ce4affSfengbojiang 282a9643ea8Slogwang /* 283a9643ea8Slogwang * Dynamically allocate a bitset. 284a9643ea8Slogwang */ 285*22ce4affSfengbojiang #define BITSET_ALLOC(_s, mt, mf) malloc(BITSET_SIZE((_s)), mt, (mf)) 286a9643ea8Slogwang 287a9643ea8Slogwang #endif /* !_SYS_BITSET_H_ */ 288