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