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