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