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