xref: /xnu-11215.1.10/osfmk/kern/bits.h (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1*8d741a5dSApple OSS Distributions /*
2*8d741a5dSApple OSS Distributions  * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
3*8d741a5dSApple OSS Distributions  *
4*8d741a5dSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*8d741a5dSApple OSS Distributions  *
6*8d741a5dSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*8d741a5dSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*8d741a5dSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*8d741a5dSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*8d741a5dSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*8d741a5dSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*8d741a5dSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*8d741a5dSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*8d741a5dSApple OSS Distributions  *
15*8d741a5dSApple OSS Distributions  * Please obtain a copy of the License at
16*8d741a5dSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*8d741a5dSApple OSS Distributions  *
18*8d741a5dSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*8d741a5dSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*8d741a5dSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*8d741a5dSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*8d741a5dSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*8d741a5dSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*8d741a5dSApple OSS Distributions  * limitations under the License.
25*8d741a5dSApple OSS Distributions  *
26*8d741a5dSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*8d741a5dSApple OSS Distributions  *
28*8d741a5dSApple OSS Distributions  * Bit manipulation functions
29*8d741a5dSApple OSS Distributions  */
30*8d741a5dSApple OSS Distributions 
31*8d741a5dSApple OSS Distributions #ifndef __BITS_H__
32*8d741a5dSApple OSS Distributions #define __BITS_H__
33*8d741a5dSApple OSS Distributions 
34*8d741a5dSApple OSS Distributions #ifdef KERNEL
35*8d741a5dSApple OSS Distributions #include <kern/assert.h>
36*8d741a5dSApple OSS Distributions #include <kern/kalloc.h>
37*8d741a5dSApple OSS Distributions #else
38*8d741a5dSApple OSS Distributions #include <assert.h>
39*8d741a5dSApple OSS Distributions #include <stdlib.h>
40*8d741a5dSApple OSS Distributions #define kalloc_data(x, y) malloc(x)
41*8d741a5dSApple OSS Distributions #define kfree_data(x, y) free(x)
42*8d741a5dSApple OSS Distributions #endif
43*8d741a5dSApple OSS Distributions #include <stdbool.h>
44*8d741a5dSApple OSS Distributions #include <stdint.h>
45*8d741a5dSApple OSS Distributions #include <stdatomic.h>
46*8d741a5dSApple OSS Distributions #include <string.h>
47*8d741a5dSApple OSS Distributions 
48*8d741a5dSApple OSS Distributions #ifndef __DARWIN_UINT
49*8d741a5dSApple OSS Distributions typedef unsigned int                    uint;
50*8d741a5dSApple OSS Distributions #define __DARWIN_UINT
51*8d741a5dSApple OSS Distributions #endif
52*8d741a5dSApple OSS Distributions 
53*8d741a5dSApple OSS Distributions #define BIT(b)                          (1ULL << (b))
54*8d741a5dSApple OSS Distributions 
55*8d741a5dSApple OSS Distributions #define mask(width)                     (width >= 64 ? -1ULL : (BIT(width) - 1))
56*8d741a5dSApple OSS Distributions #define extract(x, shift, width)        ((((uint64_t)(x)) >> (shift)) & mask(width))
57*8d741a5dSApple OSS Distributions #define bits(x, hi, lo)                 extract((x), (lo), (hi) - (lo) + 1)
58*8d741a5dSApple OSS Distributions 
59*8d741a5dSApple OSS Distributions #define bit_set(x, b)                   ((x) |= BIT(b))
60*8d741a5dSApple OSS Distributions #define bit_clear(x, b)                 ((x) &= ~BIT(b))
61*8d741a5dSApple OSS Distributions #define bit_test(x, b)                  ((bool)((x) & BIT(b)))
62*8d741a5dSApple OSS Distributions 
63*8d741a5dSApple OSS Distributions inline static uint64_t
bit_ror64(uint64_t bitmap,uint n)64*8d741a5dSApple OSS Distributions bit_ror64(uint64_t bitmap, uint n)
65*8d741a5dSApple OSS Distributions {
66*8d741a5dSApple OSS Distributions #if defined(__arm64__)
67*8d741a5dSApple OSS Distributions 	uint64_t result;
68*8d741a5dSApple OSS Distributions 	uint64_t _n = (uint64_t)n;
69*8d741a5dSApple OSS Distributions 	asm volatile ("ror %0, %1, %2" : "=r" (result) : "r" (bitmap), "r" (_n));
70*8d741a5dSApple OSS Distributions 	return result;
71*8d741a5dSApple OSS Distributions #else
72*8d741a5dSApple OSS Distributions 	n = n & 63;
73*8d741a5dSApple OSS Distributions 	return (bitmap >> n) | (bitmap << (64 - n));
74*8d741a5dSApple OSS Distributions #endif
75*8d741a5dSApple OSS Distributions }
76*8d741a5dSApple OSS Distributions 
77*8d741a5dSApple OSS Distributions inline static uint64_t
bit_rol64(uint64_t bitmap,uint n)78*8d741a5dSApple OSS Distributions bit_rol64(uint64_t bitmap, uint n)
79*8d741a5dSApple OSS Distributions {
80*8d741a5dSApple OSS Distributions #if defined(__arm64__)
81*8d741a5dSApple OSS Distributions 	return bit_ror64(bitmap, 64U - n);
82*8d741a5dSApple OSS Distributions #else
83*8d741a5dSApple OSS Distributions 	n = n & 63;
84*8d741a5dSApple OSS Distributions 	return (bitmap << n) | (bitmap >> (64 - n));
85*8d741a5dSApple OSS Distributions #endif
86*8d741a5dSApple OSS Distributions }
87*8d741a5dSApple OSS Distributions 
88*8d741a5dSApple OSS Distributions /* Non-atomically clear the bit and returns whether the bit value was changed */
89*8d741a5dSApple OSS Distributions #define bit_clear_if_set(bitmap, bit) \
90*8d741a5dSApple OSS Distributions ({ \
91*8d741a5dSApple OSS Distributions 	int _n = (bit); \
92*8d741a5dSApple OSS Distributions 	__auto_type _map = &(bitmap); \
93*8d741a5dSApple OSS Distributions 	bool _bit_is_set = bit_test(*_map, _n); \
94*8d741a5dSApple OSS Distributions 	bit_clear(*_map, _n); \
95*8d741a5dSApple OSS Distributions 	_bit_is_set; \
96*8d741a5dSApple OSS Distributions })
97*8d741a5dSApple OSS Distributions 
98*8d741a5dSApple OSS Distributions /* Non-atomically set the bit and returns whether the bit value was changed */
99*8d741a5dSApple OSS Distributions #define bit_set_if_clear(bitmap, bit) \
100*8d741a5dSApple OSS Distributions ({ \
101*8d741a5dSApple OSS Distributions 	int _n = (bit); \
102*8d741a5dSApple OSS Distributions 	__auto_type _map = &(bitmap); \
103*8d741a5dSApple OSS Distributions 	bool _bit_is_set = bit_test(*_map, _n); \
104*8d741a5dSApple OSS Distributions 	bit_set(*_map, _n); \
105*8d741a5dSApple OSS Distributions 	!_bit_is_set; \
106*8d741a5dSApple OSS Distributions })
107*8d741a5dSApple OSS Distributions 
108*8d741a5dSApple OSS Distributions /* Returns the most significant '1' bit, or -1 if all zeros */
109*8d741a5dSApple OSS Distributions inline static int
bit_first(uint64_t bitmap)110*8d741a5dSApple OSS Distributions bit_first(uint64_t bitmap)
111*8d741a5dSApple OSS Distributions {
112*8d741a5dSApple OSS Distributions #if defined(__arm64__)
113*8d741a5dSApple OSS Distributions 	int64_t result;
114*8d741a5dSApple OSS Distributions 	asm volatile ("clz %0, %1" : "=r" (result) : "r" (bitmap));
115*8d741a5dSApple OSS Distributions 	return 63 - (int)result;
116*8d741a5dSApple OSS Distributions #else
117*8d741a5dSApple OSS Distributions 	return (bitmap == 0) ? -1 : 63 - __builtin_clzll(bitmap);
118*8d741a5dSApple OSS Distributions #endif
119*8d741a5dSApple OSS Distributions }
120*8d741a5dSApple OSS Distributions 
121*8d741a5dSApple OSS Distributions 
122*8d741a5dSApple OSS Distributions inline static int
__bit_next(uint64_t bitmap,int previous_bit)123*8d741a5dSApple OSS Distributions __bit_next(uint64_t bitmap, int previous_bit)
124*8d741a5dSApple OSS Distributions {
125*8d741a5dSApple OSS Distributions 	uint64_t mask = previous_bit ? mask(previous_bit) : ~0ULL;
126*8d741a5dSApple OSS Distributions 
127*8d741a5dSApple OSS Distributions 	return bit_first(bitmap & mask);
128*8d741a5dSApple OSS Distributions }
129*8d741a5dSApple OSS Distributions 
130*8d741a5dSApple OSS Distributions /* Returns the most significant '1' bit that is less significant than previous_bit,
131*8d741a5dSApple OSS Distributions  * or -1 if no such bit exists.
132*8d741a5dSApple OSS Distributions  */
133*8d741a5dSApple OSS Distributions inline static int
bit_next(uint64_t bitmap,int previous_bit)134*8d741a5dSApple OSS Distributions bit_next(uint64_t bitmap, int previous_bit)
135*8d741a5dSApple OSS Distributions {
136*8d741a5dSApple OSS Distributions 	if (previous_bit == 0) {
137*8d741a5dSApple OSS Distributions 		return -1;
138*8d741a5dSApple OSS Distributions 	} else {
139*8d741a5dSApple OSS Distributions 		return __bit_next(bitmap, previous_bit);
140*8d741a5dSApple OSS Distributions 	}
141*8d741a5dSApple OSS Distributions }
142*8d741a5dSApple OSS Distributions 
143*8d741a5dSApple OSS Distributions /* Returns the least significant '1' bit, or -1 if all zeros */
144*8d741a5dSApple OSS Distributions inline static int
lsb_first(uint64_t bitmap)145*8d741a5dSApple OSS Distributions lsb_first(uint64_t bitmap)
146*8d741a5dSApple OSS Distributions {
147*8d741a5dSApple OSS Distributions 	return __builtin_ffsll((long long)bitmap) - 1;
148*8d741a5dSApple OSS Distributions }
149*8d741a5dSApple OSS Distributions 
150*8d741a5dSApple OSS Distributions /* Returns the least significant '1' bit that is more significant than previous_bit,
151*8d741a5dSApple OSS Distributions  * or -1 if no such bit exists.
152*8d741a5dSApple OSS Distributions  * previous_bit may be -1, in which case this is equivalent to lsb_first()
153*8d741a5dSApple OSS Distributions  */
154*8d741a5dSApple OSS Distributions inline static int
lsb_next(uint64_t bitmap,int previous_bit)155*8d741a5dSApple OSS Distributions lsb_next(uint64_t bitmap, int previous_bit)
156*8d741a5dSApple OSS Distributions {
157*8d741a5dSApple OSS Distributions 	uint64_t mask = mask(previous_bit + 1);
158*8d741a5dSApple OSS Distributions 
159*8d741a5dSApple OSS Distributions 	return lsb_first(bitmap & ~mask);
160*8d741a5dSApple OSS Distributions }
161*8d741a5dSApple OSS Distributions 
162*8d741a5dSApple OSS Distributions inline static int
bit_count(uint64_t x)163*8d741a5dSApple OSS Distributions bit_count(uint64_t x)
164*8d741a5dSApple OSS Distributions {
165*8d741a5dSApple OSS Distributions 	return __builtin_popcountll(x);
166*8d741a5dSApple OSS Distributions }
167*8d741a5dSApple OSS Distributions 
168*8d741a5dSApple OSS Distributions /* Return the highest power of 2 that is <= n, or -1 if n == 0 */
169*8d741a5dSApple OSS Distributions inline static int
bit_floor(uint64_t n)170*8d741a5dSApple OSS Distributions bit_floor(uint64_t n)
171*8d741a5dSApple OSS Distributions {
172*8d741a5dSApple OSS Distributions 	return bit_first(n);
173*8d741a5dSApple OSS Distributions }
174*8d741a5dSApple OSS Distributions 
175*8d741a5dSApple OSS Distributions /* Return the lowest power of 2 that is >= n, or -1 if n == 0 */
176*8d741a5dSApple OSS Distributions inline static int
bit_ceiling(uint64_t n)177*8d741a5dSApple OSS Distributions bit_ceiling(uint64_t n)
178*8d741a5dSApple OSS Distributions {
179*8d741a5dSApple OSS Distributions 	if (n == 0) {
180*8d741a5dSApple OSS Distributions 		return -1;
181*8d741a5dSApple OSS Distributions 	}
182*8d741a5dSApple OSS Distributions 	return bit_first(n - 1) + 1;
183*8d741a5dSApple OSS Distributions }
184*8d741a5dSApple OSS Distributions 
185*8d741a5dSApple OSS Distributions /* If n is a power of 2, bit_log2(n) == bit_floor(n) == bit_ceiling(n) */
186*8d741a5dSApple OSS Distributions #define bit_log2(n)             bit_floor((uint64_t)(n))
187*8d741a5dSApple OSS Distributions 
188*8d741a5dSApple OSS Distributions typedef uint64_t                bitmap_t;
189*8d741a5dSApple OSS Distributions 
190*8d741a5dSApple OSS Distributions 
191*8d741a5dSApple OSS Distributions inline static bool
atomic_bit_set(_Atomic bitmap_t * __single map,int n,int mem_order)192*8d741a5dSApple OSS Distributions atomic_bit_set(_Atomic bitmap_t *__single map, int n, int mem_order)
193*8d741a5dSApple OSS Distributions {
194*8d741a5dSApple OSS Distributions 	bitmap_t prev;
195*8d741a5dSApple OSS Distributions 	prev = __c11_atomic_fetch_or(map, BIT(n), mem_order);
196*8d741a5dSApple OSS Distributions 	return bit_test(prev, n);
197*8d741a5dSApple OSS Distributions }
198*8d741a5dSApple OSS Distributions 
199*8d741a5dSApple OSS Distributions inline static bool
atomic_bit_clear(_Atomic bitmap_t * __single map,int n,int mem_order)200*8d741a5dSApple OSS Distributions atomic_bit_clear(_Atomic bitmap_t *__single map, int n, int mem_order)
201*8d741a5dSApple OSS Distributions {
202*8d741a5dSApple OSS Distributions 	bitmap_t prev;
203*8d741a5dSApple OSS Distributions 	prev = __c11_atomic_fetch_and(map, ~BIT(n), mem_order);
204*8d741a5dSApple OSS Distributions 	return bit_test(prev, n);
205*8d741a5dSApple OSS Distributions }
206*8d741a5dSApple OSS Distributions 
207*8d741a5dSApple OSS Distributions 
208*8d741a5dSApple OSS Distributions #define BITMAP_LEN(n)   (((uint)(n) + 63) >> 6)         /* Round to 64bit bitmap_t */
209*8d741a5dSApple OSS Distributions #define BITMAP_SIZE(n)  (size_t)(BITMAP_LEN(n) << 3)            /* Round to 64bit bitmap_t, then convert to bytes */
210*8d741a5dSApple OSS Distributions #define bitmap_bit(n)   bits(n, 5, 0)
211*8d741a5dSApple OSS Distributions #define bitmap_index(n) bits(n, 63, 6)
212*8d741a5dSApple OSS Distributions 
213*8d741a5dSApple OSS Distributions inline static bitmap_t * __header_indexable
bitmap_zero(bitmap_t * __header_indexable map,uint nbits)214*8d741a5dSApple OSS Distributions bitmap_zero(bitmap_t *__header_indexable map, uint nbits)
215*8d741a5dSApple OSS Distributions {
216*8d741a5dSApple OSS Distributions 	memset((void *)map, 0, BITMAP_SIZE(nbits));
217*8d741a5dSApple OSS Distributions 	return map;
218*8d741a5dSApple OSS Distributions }
219*8d741a5dSApple OSS Distributions 
220*8d741a5dSApple OSS Distributions inline static bitmap_t *__header_indexable
bitmap_full(bitmap_t * __header_indexable map,uint nbits)221*8d741a5dSApple OSS Distributions bitmap_full(bitmap_t *__header_indexable map, uint nbits)
222*8d741a5dSApple OSS Distributions {
223*8d741a5dSApple OSS Distributions 	uint i;
224*8d741a5dSApple OSS Distributions 
225*8d741a5dSApple OSS Distributions 	for (i = 0; i < bitmap_index(nbits - 1); i++) {
226*8d741a5dSApple OSS Distributions 		map[i] = ~((uint64_t)0);
227*8d741a5dSApple OSS Distributions 	}
228*8d741a5dSApple OSS Distributions 
229*8d741a5dSApple OSS Distributions 	uint nbits_filled = i * 64;
230*8d741a5dSApple OSS Distributions 
231*8d741a5dSApple OSS Distributions 	if (nbits > nbits_filled) {
232*8d741a5dSApple OSS Distributions 		map[i] = mask(nbits - nbits_filled);
233*8d741a5dSApple OSS Distributions 	}
234*8d741a5dSApple OSS Distributions 
235*8d741a5dSApple OSS Distributions 	return map;
236*8d741a5dSApple OSS Distributions }
237*8d741a5dSApple OSS Distributions 
238*8d741a5dSApple OSS Distributions inline static bool
bitmap_is_empty(bitmap_t * __header_indexable map,uint nbits)239*8d741a5dSApple OSS Distributions bitmap_is_empty(bitmap_t *__header_indexable map, uint nbits)
240*8d741a5dSApple OSS Distributions {
241*8d741a5dSApple OSS Distributions 	for (uint i = 0; i < BITMAP_LEN(nbits); i++) {
242*8d741a5dSApple OSS Distributions 		if (map[i]) {
243*8d741a5dSApple OSS Distributions 			return false;
244*8d741a5dSApple OSS Distributions 		}
245*8d741a5dSApple OSS Distributions 	}
246*8d741a5dSApple OSS Distributions 
247*8d741a5dSApple OSS Distributions 	return true;
248*8d741a5dSApple OSS Distributions }
249*8d741a5dSApple OSS Distributions 
250*8d741a5dSApple OSS Distributions inline static bool
bitmap_is_full(bitmap_t * __header_indexable map,uint nbits)251*8d741a5dSApple OSS Distributions bitmap_is_full(bitmap_t *__header_indexable map, uint nbits)
252*8d741a5dSApple OSS Distributions {
253*8d741a5dSApple OSS Distributions 	uint i;
254*8d741a5dSApple OSS Distributions 
255*8d741a5dSApple OSS Distributions 	for (i = 0; i < bitmap_index(nbits - 1); i++) {
256*8d741a5dSApple OSS Distributions 		if (map[i] != ~((uint64_t)0)) {
257*8d741a5dSApple OSS Distributions 			return false;
258*8d741a5dSApple OSS Distributions 		}
259*8d741a5dSApple OSS Distributions 	}
260*8d741a5dSApple OSS Distributions 
261*8d741a5dSApple OSS Distributions 	uint nbits_filled = i * 64;
262*8d741a5dSApple OSS Distributions 
263*8d741a5dSApple OSS Distributions 	if (nbits > nbits_filled) {
264*8d741a5dSApple OSS Distributions 		return map[i] == mask(nbits - nbits_filled);
265*8d741a5dSApple OSS Distributions 	}
266*8d741a5dSApple OSS Distributions 
267*8d741a5dSApple OSS Distributions 	return true;
268*8d741a5dSApple OSS Distributions }
269*8d741a5dSApple OSS Distributions 
270*8d741a5dSApple OSS Distributions inline static bitmap_t *__header_indexable
bitmap_alloc(uint nbits)271*8d741a5dSApple OSS Distributions bitmap_alloc(uint nbits)
272*8d741a5dSApple OSS Distributions {
273*8d741a5dSApple OSS Distributions 	assert(nbits > 0);
274*8d741a5dSApple OSS Distributions 	return (bitmap_t *)kalloc_data(BITMAP_SIZE(nbits), Z_WAITOK_ZERO);
275*8d741a5dSApple OSS Distributions }
276*8d741a5dSApple OSS Distributions 
277*8d741a5dSApple OSS Distributions inline static void
bitmap_free(bitmap_t * map,uint nbits)278*8d741a5dSApple OSS Distributions bitmap_free(bitmap_t *map, uint nbits)
279*8d741a5dSApple OSS Distributions {
280*8d741a5dSApple OSS Distributions 	assert(nbits > 0);
281*8d741a5dSApple OSS Distributions 	kfree_data(map, BITMAP_SIZE(nbits));
282*8d741a5dSApple OSS Distributions }
283*8d741a5dSApple OSS Distributions 
284*8d741a5dSApple OSS Distributions inline static void
bitmap_set(bitmap_t * __header_indexable map,uint n)285*8d741a5dSApple OSS Distributions bitmap_set(bitmap_t *__header_indexable map, uint n)
286*8d741a5dSApple OSS Distributions {
287*8d741a5dSApple OSS Distributions 	bit_set(map[bitmap_index(n)], bitmap_bit(n));
288*8d741a5dSApple OSS Distributions }
289*8d741a5dSApple OSS Distributions 
290*8d741a5dSApple OSS Distributions inline static void
bitmap_clear(bitmap_t * __header_indexable map,uint n)291*8d741a5dSApple OSS Distributions bitmap_clear(bitmap_t *__header_indexable map, uint n)
292*8d741a5dSApple OSS Distributions {
293*8d741a5dSApple OSS Distributions 	bit_clear(map[bitmap_index(n)], bitmap_bit(n));
294*8d741a5dSApple OSS Distributions }
295*8d741a5dSApple OSS Distributions 
296*8d741a5dSApple OSS Distributions inline static bool
atomic_bitmap_set(_Atomic bitmap_t * __header_indexable map,uint n,int mem_order)297*8d741a5dSApple OSS Distributions atomic_bitmap_set(_Atomic bitmap_t *__header_indexable map, uint n, int mem_order)
298*8d741a5dSApple OSS Distributions {
299*8d741a5dSApple OSS Distributions 	return atomic_bit_set(&map[bitmap_index(n)], bitmap_bit(n), mem_order);
300*8d741a5dSApple OSS Distributions }
301*8d741a5dSApple OSS Distributions 
302*8d741a5dSApple OSS Distributions inline static bool
atomic_bitmap_clear(_Atomic bitmap_t * __header_indexable map,uint n,int mem_order)303*8d741a5dSApple OSS Distributions atomic_bitmap_clear(_Atomic bitmap_t *__header_indexable map, uint n, int mem_order)
304*8d741a5dSApple OSS Distributions {
305*8d741a5dSApple OSS Distributions 	return atomic_bit_clear(&map[bitmap_index(n)], bitmap_bit(n), mem_order);
306*8d741a5dSApple OSS Distributions }
307*8d741a5dSApple OSS Distributions 
308*8d741a5dSApple OSS Distributions inline static bool
bitmap_test(const bitmap_t * __header_indexable map,uint n)309*8d741a5dSApple OSS Distributions bitmap_test(const bitmap_t *__header_indexable map, uint n)
310*8d741a5dSApple OSS Distributions {
311*8d741a5dSApple OSS Distributions 	return bit_test(map[bitmap_index(n)], bitmap_bit(n));
312*8d741a5dSApple OSS Distributions }
313*8d741a5dSApple OSS Distributions 
314*8d741a5dSApple OSS Distributions inline static int
bitmap_first(bitmap_t * __header_indexable map,uint nbits)315*8d741a5dSApple OSS Distributions bitmap_first(bitmap_t *__header_indexable map, uint nbits)
316*8d741a5dSApple OSS Distributions {
317*8d741a5dSApple OSS Distributions 	for (int i = (int)bitmap_index(nbits - 1); i >= 0; i--) {
318*8d741a5dSApple OSS Distributions 		if (map[i] == 0) {
319*8d741a5dSApple OSS Distributions 			continue;
320*8d741a5dSApple OSS Distributions 		}
321*8d741a5dSApple OSS Distributions 		return (i << 6) + bit_first(map[i]);
322*8d741a5dSApple OSS Distributions 	}
323*8d741a5dSApple OSS Distributions 
324*8d741a5dSApple OSS Distributions 	return -1;
325*8d741a5dSApple OSS Distributions }
326*8d741a5dSApple OSS Distributions 
327*8d741a5dSApple OSS Distributions inline static void
bitmap_not(bitmap_t * __header_indexable out,const bitmap_t * __header_indexable in,uint nbits)328*8d741a5dSApple OSS Distributions bitmap_not(
329*8d741a5dSApple OSS Distributions 	bitmap_t       *__header_indexable out,
330*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in,
331*8d741a5dSApple OSS Distributions 	uint                               nbits)
332*8d741a5dSApple OSS Distributions {
333*8d741a5dSApple OSS Distributions 	uint i;
334*8d741a5dSApple OSS Distributions 
335*8d741a5dSApple OSS Distributions 	for (i = 0; i < bitmap_index(nbits - 1); i++) {
336*8d741a5dSApple OSS Distributions 		out[i] = ~in[i];
337*8d741a5dSApple OSS Distributions 	}
338*8d741a5dSApple OSS Distributions 
339*8d741a5dSApple OSS Distributions 	uint nbits_complete = i * 64;
340*8d741a5dSApple OSS Distributions 
341*8d741a5dSApple OSS Distributions 	if (nbits > nbits_complete) {
342*8d741a5dSApple OSS Distributions 		out[i] = ~in[i] & mask(nbits - nbits_complete);
343*8d741a5dSApple OSS Distributions 	}
344*8d741a5dSApple OSS Distributions }
345*8d741a5dSApple OSS Distributions 
346*8d741a5dSApple OSS Distributions inline static void
bitmap_and(bitmap_t * __header_indexable out,const bitmap_t * __header_indexable in1,const bitmap_t * __header_indexable in2,uint nbits)347*8d741a5dSApple OSS Distributions bitmap_and(
348*8d741a5dSApple OSS Distributions 	bitmap_t       *__header_indexable out,
349*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in1,
350*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in2,
351*8d741a5dSApple OSS Distributions 	uint                               nbits)
352*8d741a5dSApple OSS Distributions {
353*8d741a5dSApple OSS Distributions 	for (uint i = 0; i <= bitmap_index(nbits - 1); i++) {
354*8d741a5dSApple OSS Distributions 		out[i] = in1[i] & in2[i];
355*8d741a5dSApple OSS Distributions 	}
356*8d741a5dSApple OSS Distributions }
357*8d741a5dSApple OSS Distributions 
358*8d741a5dSApple OSS Distributions inline static void
bitmap_and_not(bitmap_t * __header_indexable out,const bitmap_t * __header_indexable in1,const bitmap_t * __header_indexable in2,uint nbits)359*8d741a5dSApple OSS Distributions bitmap_and_not(
360*8d741a5dSApple OSS Distributions 	bitmap_t       *__header_indexable out,
361*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in1,
362*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in2,
363*8d741a5dSApple OSS Distributions 	uint                               nbits)
364*8d741a5dSApple OSS Distributions {
365*8d741a5dSApple OSS Distributions 	uint i;
366*8d741a5dSApple OSS Distributions 
367*8d741a5dSApple OSS Distributions 	for (i = 0; i <= bitmap_index(nbits - 1); i++) {
368*8d741a5dSApple OSS Distributions 		out[i] = in1[i] & ~in2[i];
369*8d741a5dSApple OSS Distributions 	}
370*8d741a5dSApple OSS Distributions }
371*8d741a5dSApple OSS Distributions 
372*8d741a5dSApple OSS Distributions inline static void
bitmap_or(bitmap_t * __header_indexable out,const bitmap_t * __header_indexable in1,const bitmap_t * __header_indexable in2,uint nbits)373*8d741a5dSApple OSS Distributions bitmap_or(
374*8d741a5dSApple OSS Distributions 	bitmap_t       *__header_indexable out,
375*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in1,
376*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in2,
377*8d741a5dSApple OSS Distributions 	uint                        nbits)
378*8d741a5dSApple OSS Distributions {
379*8d741a5dSApple OSS Distributions 	for (uint i = 0; i <= bitmap_index(nbits - 1); i++) {
380*8d741a5dSApple OSS Distributions 		out[i] = in1[i] | in2[i];
381*8d741a5dSApple OSS Distributions 	}
382*8d741a5dSApple OSS Distributions }
383*8d741a5dSApple OSS Distributions 
384*8d741a5dSApple OSS Distributions inline static bool
bitmap_equal(const bitmap_t * __header_indexable in1,const bitmap_t * __header_indexable in2,uint nbits)385*8d741a5dSApple OSS Distributions bitmap_equal(
386*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in1,
387*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable in2,
388*8d741a5dSApple OSS Distributions 	uint                               nbits)
389*8d741a5dSApple OSS Distributions {
390*8d741a5dSApple OSS Distributions 	for (uint i = 0; i <= bitmap_index(nbits - 1); i++) {
391*8d741a5dSApple OSS Distributions 		if (in1[i] != in2[i]) {
392*8d741a5dSApple OSS Distributions 			return false;
393*8d741a5dSApple OSS Distributions 		}
394*8d741a5dSApple OSS Distributions 	}
395*8d741a5dSApple OSS Distributions 
396*8d741a5dSApple OSS Distributions 	return true;
397*8d741a5dSApple OSS Distributions }
398*8d741a5dSApple OSS Distributions 
399*8d741a5dSApple OSS Distributions inline static int
bitmap_and_not_mask_first(bitmap_t * __header_indexable map,const bitmap_t * __header_indexable mask,uint nbits)400*8d741a5dSApple OSS Distributions bitmap_and_not_mask_first(
401*8d741a5dSApple OSS Distributions 	bitmap_t       *__header_indexable map,
402*8d741a5dSApple OSS Distributions 	const bitmap_t *__header_indexable mask,
403*8d741a5dSApple OSS Distributions 	uint                               nbits)
404*8d741a5dSApple OSS Distributions {
405*8d741a5dSApple OSS Distributions 	for (int i = (int)bitmap_index(nbits - 1); i >= 0; i--) {
406*8d741a5dSApple OSS Distributions 		if ((map[i] & ~mask[i]) == 0) {
407*8d741a5dSApple OSS Distributions 			continue;
408*8d741a5dSApple OSS Distributions 		}
409*8d741a5dSApple OSS Distributions 		return (i << 6) + bit_first(map[i] & ~mask[i]);
410*8d741a5dSApple OSS Distributions 	}
411*8d741a5dSApple OSS Distributions 
412*8d741a5dSApple OSS Distributions 	return -1;
413*8d741a5dSApple OSS Distributions }
414*8d741a5dSApple OSS Distributions 
415*8d741a5dSApple OSS Distributions inline static int
bitmap_lsb_first(const bitmap_t * __header_indexable map,uint nbits)416*8d741a5dSApple OSS Distributions bitmap_lsb_first(const bitmap_t *__header_indexable map, uint nbits)
417*8d741a5dSApple OSS Distributions {
418*8d741a5dSApple OSS Distributions 	for (uint i = 0; i <= bitmap_index(nbits - 1); i++) {
419*8d741a5dSApple OSS Distributions 		if (map[i] == 0) {
420*8d741a5dSApple OSS Distributions 			continue;
421*8d741a5dSApple OSS Distributions 		}
422*8d741a5dSApple OSS Distributions 		return (int)((i << 6) + (uint32_t)lsb_first(map[i]));
423*8d741a5dSApple OSS Distributions 	}
424*8d741a5dSApple OSS Distributions 
425*8d741a5dSApple OSS Distributions 	return -1;
426*8d741a5dSApple OSS Distributions }
427*8d741a5dSApple OSS Distributions 
428*8d741a5dSApple OSS Distributions inline static int
bitmap_next(const bitmap_t * __header_indexable map,uint prev)429*8d741a5dSApple OSS Distributions bitmap_next(const bitmap_t *__header_indexable map, uint prev)
430*8d741a5dSApple OSS Distributions {
431*8d741a5dSApple OSS Distributions 	if (prev == 0) {
432*8d741a5dSApple OSS Distributions 		return -1;
433*8d741a5dSApple OSS Distributions 	}
434*8d741a5dSApple OSS Distributions 
435*8d741a5dSApple OSS Distributions 	int64_t i = bitmap_index(prev - 1);
436*8d741a5dSApple OSS Distributions 	int res = __bit_next(map[i], bits(prev, 5, 0));
437*8d741a5dSApple OSS Distributions 	if (res >= 0) {
438*8d741a5dSApple OSS Distributions 		return (int)(res + (i << 6));
439*8d741a5dSApple OSS Distributions 	}
440*8d741a5dSApple OSS Distributions 
441*8d741a5dSApple OSS Distributions 	for (i = i - 1; i >= 0; i--) {
442*8d741a5dSApple OSS Distributions 		if (map[i] == 0) {
443*8d741a5dSApple OSS Distributions 			continue;
444*8d741a5dSApple OSS Distributions 		}
445*8d741a5dSApple OSS Distributions 		return (int)((i << 6) + bit_first(map[i]));
446*8d741a5dSApple OSS Distributions 	}
447*8d741a5dSApple OSS Distributions 
448*8d741a5dSApple OSS Distributions 	return -1;
449*8d741a5dSApple OSS Distributions }
450*8d741a5dSApple OSS Distributions 
451*8d741a5dSApple OSS Distributions inline static int
bitmap_lsb_next(const bitmap_t * __header_indexable map,uint nbits,uint prev)452*8d741a5dSApple OSS Distributions bitmap_lsb_next(const bitmap_t *__header_indexable map, uint nbits, uint prev)
453*8d741a5dSApple OSS Distributions {
454*8d741a5dSApple OSS Distributions 	if ((prev + 1) >= nbits) {
455*8d741a5dSApple OSS Distributions 		return -1;
456*8d741a5dSApple OSS Distributions 	}
457*8d741a5dSApple OSS Distributions 
458*8d741a5dSApple OSS Distributions 	uint64_t i = bitmap_index(prev + 1);
459*8d741a5dSApple OSS Distributions 	uint b = bits((prev + 1), 5, 0) - 1;
460*8d741a5dSApple OSS Distributions 	int32_t res = lsb_next((uint64_t)map[i], (int)b);
461*8d741a5dSApple OSS Distributions 	if (res >= 0) {
462*8d741a5dSApple OSS Distributions 		return (int)((uint64_t)res + (i << 6));
463*8d741a5dSApple OSS Distributions 	}
464*8d741a5dSApple OSS Distributions 
465*8d741a5dSApple OSS Distributions 	for (i = i + 1; i <= bitmap_index(nbits - 1); i++) {
466*8d741a5dSApple OSS Distributions 		if (map[i] == 0) {
467*8d741a5dSApple OSS Distributions 			continue;
468*8d741a5dSApple OSS Distributions 		}
469*8d741a5dSApple OSS Distributions 		return (int)((i << 6) + (uint64_t)lsb_first(map[i]));
470*8d741a5dSApple OSS Distributions 	}
471*8d741a5dSApple OSS Distributions 
472*8d741a5dSApple OSS Distributions 	return -1;
473*8d741a5dSApple OSS Distributions }
474*8d741a5dSApple OSS Distributions 
475*8d741a5dSApple OSS Distributions #endif
476