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