]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/bits.h
2 * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 * Bit manipulation functions
35 #include <kern/assert.h>
36 #include <kern/kalloc.h>
40 #define kalloc(x) malloc(x)
41 #define kfree(x, y) free(x)
45 #include <stdatomic.h>
47 typedef unsigned int uint
;
49 #define BIT(b) (1ULL << (b))
51 #define mask(width) (width >= 64 ? -1ULL : (BIT(width) - 1))
52 #define extract(x, shift, width) ((((uint64_t)(x)) >> (shift)) & mask(width))
53 #define bits(x, hi, lo) extract((x), (lo), (hi) - (lo) + 1)
55 #define bit_set(x, b) ((x) |= BIT(b))
56 #define bit_clear(x, b) ((x) &= ~BIT(b))
57 #define bit_test(x, b) ((bool)((x) & BIT(b)))
59 inline static uint64_t
60 bit_ror64(uint64_t bitmap
, uint n
)
62 #if defined(__arm64__)
64 uint64_t _n
= (uint64_t)n
;
65 asm volatile ("ror %0, %1, %2" : "=r" (result
) : "r" (bitmap
), "r" (_n
));
69 return (bitmap
>> n
) | (bitmap
<< (64 - n
));
73 inline static uint64_t
74 bit_rol64(uint64_t bitmap
, uint n
)
76 #if defined(__arm64__)
77 return bit_ror64(bitmap
, 64U - n
);
80 return (bitmap
<< n
) | (bitmap
>> (64 - n
));
84 /* Non-atomically clear the bit and returns whether the bit value was changed */
86 bit_clear_if_set(uint64_t bitmap
, int bit
)
88 bool bit_is_set
= bit_test(bitmap
, bit
);
89 bit_clear(bitmap
, bit
);
93 /* Non-atomically set the bit and returns whether the bit value was changed */
95 bit_set_if_clear(uint64_t bitmap
, int bit
)
97 bool bit_is_set
= bit_test(bitmap
, bit
);
102 /* Returns the most significant '1' bit, or -1 if all zeros */
104 bit_first(uint64_t bitmap
)
106 #if defined(__arm64__)
108 asm volatile ("clz %0, %1" : "=r" (result
) : "r" (bitmap
));
109 return 63 - (int)result
;
111 return (bitmap
== 0) ? -1 : 63 - __builtin_clzll(bitmap
);
117 __bit_next(uint64_t bitmap
, int previous_bit
)
119 uint64_t mask
= previous_bit
? mask(previous_bit
) : ~0ULL;
121 return bit_first(bitmap
& mask
);
124 /* Returns the most significant '1' bit that is less significant than previous_bit,
125 * or -1 if no such bit exists.
128 bit_next(uint64_t bitmap
, int previous_bit
)
130 if (previous_bit
== 0) {
133 return __bit_next(bitmap
, previous_bit
);
137 /* Returns the least significant '1' bit, or -1 if all zeros */
139 lsb_first(uint64_t bitmap
)
141 return __builtin_ffsll((long long)bitmap
) - 1;
144 /* Returns the least significant '1' bit that is more significant than previous_bit,
145 * or -1 if no such bit exists.
146 * previous_bit may be -1, in which case this is equivalent to lsb_first()
149 lsb_next(uint64_t bitmap
, int previous_bit
)
151 uint64_t mask
= mask(previous_bit
+ 1);
153 return lsb_first(bitmap
& ~mask
);
157 bit_count(uint64_t x
)
159 return __builtin_popcountll(x
);
162 /* Return the highest power of 2 that is <= n, or -1 if n == 0 */
164 bit_floor(uint64_t n
)
169 /* Return the lowest power of 2 that is >= n, or -1 if n == 0 */
171 bit_ceiling(uint64_t n
)
176 return bit_first(n
- 1) + 1;
179 /* If n is a power of 2, bit_log2(n) == bit_floor(n) == bit_ceiling(n) */
180 #define bit_log2(n) bit_floor((uint64_t)(n))
182 typedef uint64_t bitmap_t
;
186 atomic_bit_set(_Atomic bitmap_t
*map
, int n
, int mem_order
)
189 prev
= __c11_atomic_fetch_or(map
, BIT(n
), mem_order
);
190 return bit_test(prev
, n
);
194 atomic_bit_clear(_Atomic bitmap_t
*map
, int n
, int mem_order
)
197 prev
= __c11_atomic_fetch_and(map
, ~BIT(n
), mem_order
);
198 return bit_test(prev
, n
);
202 #define BITMAP_LEN(n) (((uint)(n) + 63) >> 6) /* Round to 64bit bitmap_t */
203 #define BITMAP_SIZE(n) (size_t)(BITMAP_LEN(n) << 3) /* Round to 64bit bitmap_t, then convert to bytes */
204 #define bitmap_bit(n) bits(n, 5, 0)
205 #define bitmap_index(n) bits(n, 63, 6)
207 inline static bitmap_t
*
208 bitmap_zero(bitmap_t
*map
, uint nbits
)
210 return (bitmap_t
*)memset((void *)map
, 0, BITMAP_SIZE(nbits
));
213 inline static bitmap_t
*
214 bitmap_full(bitmap_t
*map
, uint nbits
)
218 for (i
= 0; i
< bitmap_index(nbits
- 1); i
++) {
219 map
[i
] = ~((uint64_t)0);
222 uint nbits_filled
= i
* 64;
224 if (nbits
> nbits_filled
) {
225 map
[i
] = mask(nbits
- nbits_filled
);
232 bitmap_is_full(bitmap_t
*map
, uint nbits
)
236 for (i
= 0; i
< bitmap_index(nbits
- 1); i
++) {
237 if (map
[i
] != ~((uint64_t)0)) {
242 uint nbits_filled
= i
* 64;
244 if (nbits
> nbits_filled
) {
245 return map
[i
] == mask(nbits
- nbits_filled
);
251 inline static bitmap_t
*
252 bitmap_alloc(uint nbits
)
255 bitmap_t
*map
= (bitmap_t
*)kalloc(BITMAP_SIZE(nbits
));
257 bitmap_zero(map
, nbits
);
263 bitmap_free(bitmap_t
*map
, uint nbits
)
266 kfree(map
, BITMAP_SIZE(nbits
));
270 bitmap_set(bitmap_t
*map
, uint n
)
272 bit_set(map
[bitmap_index(n
)], bitmap_bit(n
));
276 bitmap_clear(bitmap_t
*map
, uint n
)
278 bit_clear(map
[bitmap_index(n
)], bitmap_bit(n
));
282 atomic_bitmap_set(_Atomic bitmap_t
*map
, uint n
, int mem_order
)
284 return atomic_bit_set(&map
[bitmap_index(n
)], bitmap_bit(n
), mem_order
);
288 atomic_bitmap_clear(_Atomic bitmap_t
*map
, uint n
, int mem_order
)
290 return atomic_bit_clear(&map
[bitmap_index(n
)], bitmap_bit(n
), mem_order
);
294 bitmap_test(const bitmap_t
*map
, uint n
)
296 return bit_test(map
[bitmap_index(n
)], bitmap_bit(n
));
300 bitmap_first(bitmap_t
*map
, uint nbits
)
302 for (int i
= (int)bitmap_index(nbits
- 1); i
>= 0; i
--) {
306 return (i
<< 6) + bit_first(map
[i
]);
313 bitmap_not(bitmap_t
*out
, const bitmap_t
*in
, uint nbits
)
317 for (i
= 0; i
< bitmap_index(nbits
- 1); i
++) {
321 uint nbits_complete
= i
* 64;
323 if (nbits
> nbits_complete
) {
324 out
[i
] = ~in
[i
] & mask(nbits
- nbits_complete
);
329 bitmap_and(bitmap_t
*out
, const bitmap_t
*in1
, const bitmap_t
*in2
, uint nbits
)
331 for (uint i
= 0; i
<= bitmap_index(nbits
- 1); i
++) {
332 out
[i
] = in1
[i
] & in2
[i
];
337 bitmap_and_not(bitmap_t
*out
, const bitmap_t
*in1
, const bitmap_t
*in2
, uint nbits
)
341 for (i
= 0; i
< bitmap_index(nbits
- 1); i
++) {
342 out
[i
] = in1
[i
] & ~in2
[i
];
345 uint nbits_complete
= i
* 64;
347 if (nbits
> nbits_complete
) {
348 out
[i
] = (in1
[i
] & ~in2
[i
]) & mask(nbits
- nbits_complete
);
353 bitmap_equal(const bitmap_t
*in1
, const bitmap_t
*in2
, uint nbits
)
355 for (uint i
= 0; i
<= bitmap_index(nbits
- 1); i
++) {
356 if (in1
[i
] != in2
[i
]) {
365 bitmap_and_not_mask_first(bitmap_t
*map
, bitmap_t
*mask
, uint nbits
)
367 for (int i
= (int)bitmap_index(nbits
- 1); i
>= 0; i
--) {
368 if ((map
[i
] & ~mask
[i
]) == 0) {
371 return (i
<< 6) + bit_first(map
[i
] & ~mask
[i
]);
378 bitmap_lsb_first(const bitmap_t
*map
, uint nbits
)
380 for (uint i
= 0; i
<= bitmap_index(nbits
- 1); i
++) {
384 return (int)((i
<< 6) + (uint32_t)lsb_first(map
[i
]));
391 bitmap_next(const bitmap_t
*map
, uint prev
)
397 int64_t i
= bitmap_index(prev
- 1);
398 int res
= __bit_next(map
[i
], bits(prev
, 5, 0));
400 return (int)(res
+ (i
<< 6));
403 for (i
= i
- 1; i
>= 0; i
--) {
407 return (int)((i
<< 6) + bit_first(map
[i
]));
414 bitmap_lsb_next(const bitmap_t
*map
, uint nbits
, uint prev
)
416 if ((prev
+ 1) >= nbits
) {
420 uint64_t i
= bitmap_index(prev
+ 1);
421 uint b
= bits((prev
+ 1), 5, 0) - 1;
422 int32_t res
= lsb_next((uint64_t)map
[i
], (int)b
);
424 return (int)((uint64_t)res
+ (i
<< 6));
427 for (i
= i
+ 1; i
<= bitmap_index(nbits
- 1); i
++) {
431 return (int)((i
<< 6) + (uint64_t)lsb_first(map
[i
]));