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