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