]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/bits.h
xnu-6153.11.26.tar.gz
[apple/xnu.git] / osfmk / kern / bits.h
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 #include <kern/assert.h>
35 #include <kern/kalloc.h>
36 #include <stdbool.h>
37 #include <stdint.h>
38
39 typedef unsigned int uint;
40
41 #define BIT(b) (1ULL << (b))
42
43 #define mask(width) (width >= 64 ? -1 : (BIT(width) - 1))
44 #define extract(x, shift, width) ((((uint64_t)(x)) >> (shift)) & mask(width))
45 #define bits(x, hi, lo) extract((x), (lo), (hi) - (lo) + 1)
46
47 #define bit_set(x, b) ((x) |= BIT(b))
48 #define bit_clear(x, b) ((x) &= ~BIT(b))
49 #define bit_test(x, b) ((bool)((x) & BIT(b)))
50
51 inline static uint64_t
52 bit_ror64(uint64_t bitmap, uint n)
53 {
54 #if defined(__arm64__)
55 uint64_t result;
56 uint64_t _n = (uint64_t)n;
57 asm volatile ("ror %0, %1, %2" : "=r" (result) : "r" (bitmap), "r" (_n));
58 return result;
59 #else
60 n = n & 63;
61 return (bitmap >> n) | (bitmap << (64 - n));
62 #endif
63 }
64
65 inline static uint64_t
66 bit_rol64(uint64_t bitmap, uint n)
67 {
68 #if defined(__arm64__)
69 return bit_ror64(bitmap, 64U - n);
70 #else
71 n = n & 63;
72 return (bitmap << n) | (bitmap >> (64 - n));
73 #endif
74 }
75
76 /* Non-atomically clear the bit and returns whether the bit value was changed */
77 inline static bool
78 bit_clear_if_set(uint64_t bitmap, int bit)
79 {
80 bool bit_is_set = bit_test(bitmap, bit);
81 bit_clear(bitmap, bit);
82 return bit_is_set;
83 }
84
85 /* Non-atomically set the bit and returns whether the bit value was changed */
86 inline static bool
87 bit_set_if_clear(uint64_t bitmap, int bit)
88 {
89 bool bit_is_set = bit_test(bitmap, bit);
90 bit_set(bitmap, bit);
91 return !bit_is_set;
92 }
93
94 /* Returns the most significant '1' bit, or -1 if all zeros */
95 inline static int
96 bit_first(uint64_t bitmap)
97 {
98 #if defined(__arm64__)
99 int64_t result;
100 asm volatile ("clz %0, %1" : "=r" (result) : "r" (bitmap));
101 return 63 - (int)result;
102 #else
103 return (bitmap == 0) ? -1 : 63 - __builtin_clzll(bitmap);
104 #endif
105 }
106
107
108 inline static int
109 __bit_next(uint64_t bitmap, int previous_bit)
110 {
111 uint64_t mask = previous_bit ? mask(previous_bit) : ~0ULL;
112
113 return bit_first(bitmap & mask);
114 }
115
116 /* Returns the most significant '1' bit that is less significant than previous_bit,
117 * or -1 if no such bit exists.
118 */
119 inline static int
120 bit_next(uint64_t bitmap, int previous_bit)
121 {
122 if (previous_bit == 0) {
123 return -1;
124 } else {
125 return __bit_next(bitmap, previous_bit);
126 }
127 }
128
129 /* Returns the least significant '1' bit, or -1 if all zeros */
130 inline static int
131 lsb_first(uint64_t bitmap)
132 {
133 return __builtin_ffsll(bitmap) - 1;
134 }
135
136 /* Returns the least significant '1' bit that is more significant than previous_bit,
137 * or -1 if no such bit exists.
138 * previous_bit may be -1, in which case this is equivalent to lsb_first()
139 */
140 inline static int
141 lsb_next(uint64_t bitmap, int previous_bit)
142 {
143 uint64_t mask = mask(previous_bit + 1);
144
145 return lsb_first(bitmap & ~mask);
146 }
147
148 inline static int
149 bit_count(uint64_t x)
150 {
151 return __builtin_popcountll(x);
152 }
153
154 /* Return the highest power of 2 that is <= n, or -1 if n == 0 */
155 inline static int
156 bit_floor(uint64_t n)
157 {
158 return bit_first(n);
159 }
160
161 /* Return the lowest power of 2 that is >= n, or -1 if n == 0 */
162 inline static int
163 bit_ceiling(uint64_t n)
164 {
165 if (n == 0) {
166 return -1;
167 }
168 return bit_first(n - 1) + 1;
169 }
170
171 /* If n is a power of 2, bit_log2(n) == bit_floor(n) == bit_ceiling(n) */
172 #define bit_log2(n) bit_floor((uint64_t)(n))
173
174 typedef uint64_t bitmap_t;
175
176
177 inline static bool
178 atomic_bit_set(_Atomic bitmap_t *map, int n, int mem_order)
179 {
180 bitmap_t prev;
181 prev = __c11_atomic_fetch_or(map, BIT(n), mem_order);
182 return bit_test(prev, n);
183 }
184
185 inline static bool
186 atomic_bit_clear(_Atomic bitmap_t *map, int n, int mem_order)
187 {
188 bitmap_t prev;
189 prev = __c11_atomic_fetch_and(map, ~BIT(n), mem_order);
190 return bit_test(prev, n);
191 }
192
193
194 #define BITMAP_LEN(n) (((uint)(n) + 63) >> 6) /* Round to 64bit bitmap_t */
195 #define BITMAP_SIZE(n) (size_t)(BITMAP_LEN(n) << 3) /* Round to 64bit bitmap_t, then convert to bytes */
196 #define bitmap_bit(n) bits(n, 5, 0)
197 #define bitmap_index(n) bits(n, 63, 6)
198
199 inline static bitmap_t *
200 bitmap_zero(bitmap_t *map, uint nbits)
201 {
202 return (bitmap_t *)memset((void *)map, 0, BITMAP_SIZE(nbits));
203 }
204
205 inline static bitmap_t *
206 bitmap_full(bitmap_t *map, uint nbits)
207 {
208 return (bitmap_t *)memset((void *)map, ~0, BITMAP_SIZE(nbits));
209 }
210
211 inline static bitmap_t *
212 bitmap_alloc(uint nbits)
213 {
214 assert(nbits > 0);
215 bitmap_t *map = (bitmap_t *)kalloc(BITMAP_SIZE(nbits));
216 if (map) {
217 bitmap_zero(map, nbits);
218 }
219 return map;
220 }
221
222 inline static void
223 bitmap_free(bitmap_t *map, uint nbits)
224 {
225 assert(nbits > 0);
226 kfree(map, BITMAP_SIZE(nbits));
227 }
228
229 inline static void
230 bitmap_set(bitmap_t *map, uint n)
231 {
232 bit_set(map[bitmap_index(n)], bitmap_bit(n));
233 }
234
235 inline static void
236 bitmap_clear(bitmap_t *map, uint n)
237 {
238 bit_clear(map[bitmap_index(n)], bitmap_bit(n));
239 }
240
241 inline static bool
242 atomic_bitmap_set(_Atomic bitmap_t *map, uint n, int mem_order)
243 {
244 return atomic_bit_set(&map[bitmap_index(n)], bitmap_bit(n), mem_order);
245 }
246
247 inline static bool
248 atomic_bitmap_clear(_Atomic bitmap_t *map, uint n, int mem_order)
249 {
250 return atomic_bit_clear(&map[bitmap_index(n)], bitmap_bit(n), mem_order);
251 }
252
253 inline static bool
254 bitmap_test(bitmap_t *map, uint n)
255 {
256 return bit_test(map[bitmap_index(n)], bitmap_bit(n));
257 }
258
259 inline static int
260 bitmap_first(bitmap_t *map, uint nbits)
261 {
262 for (int i = (int)bitmap_index(nbits - 1); i >= 0; i--) {
263 if (map[i] == 0) {
264 continue;
265 }
266 return (i << 6) + bit_first(map[i]);
267 }
268
269 return -1;
270 }
271
272 inline static int
273 bitmap_and_not_mask_first(bitmap_t *map, bitmap_t *mask, uint nbits)
274 {
275 for (int i = (int)bitmap_index(nbits - 1); i >= 0; i--) {
276 if ((map[i] & ~mask[i]) == 0) {
277 continue;
278 }
279 return (i << 6) + bit_first(map[i] & ~mask[i]);
280 }
281
282 return -1;
283 }
284
285 inline static int
286 bitmap_lsb_first(bitmap_t *map, uint nbits)
287 {
288 for (uint i = 0; i <= bitmap_index(nbits - 1); i++) {
289 if (map[i] == 0) {
290 continue;
291 }
292 return (int)((i << 6) + (uint32_t)lsb_first(map[i]));
293 }
294
295 return -1;
296 }
297
298 inline static int
299 bitmap_next(bitmap_t *map, uint prev)
300 {
301 if (prev == 0) {
302 return -1;
303 }
304
305 int64_t i = bitmap_index(prev - 1);
306 int res = __bit_next(map[i], bits(prev, 5, 0));
307 if (res >= 0) {
308 return (int)(res + (i << 6));
309 }
310
311 for (i = i - 1; i >= 0; i--) {
312 if (map[i] == 0) {
313 continue;
314 }
315 return (int)((i << 6) + bit_first(map[i]));
316 }
317
318 return -1;
319 }
320
321 inline static int
322 bitmap_lsb_next(bitmap_t *map, uint nbits, uint prev)
323 {
324 if ((prev + 1) >= nbits) {
325 return -1;
326 }
327
328 uint64_t i = bitmap_index(prev + 1);
329 uint b = bits((prev + 1), 5, 0) - 1;
330 int32_t res = lsb_next((uint64_t)map[i], (int)b);
331 if (res >= 0) {
332 return (int)((uint64_t)res + (i << 6));
333 }
334
335 for (i = i + 1; i <= bitmap_index(nbits - 1); i++) {
336 if (map[i] == 0) {
337 continue;
338 }
339 return (int)((i << 6) + (uint64_t)lsb_first(map[i]));
340 }
341
342 return -1;
343 }
344
345 #endif