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