/ duct-tape / xnu / osfmk / kern / bits.h
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  #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(x) malloc(x)
 41  #define kfree(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
 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
 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  inline static bool
 86  bit_clear_if_set(uint64_t *bitmap, int bit)
 87  {
 88  	bool bit_is_set = bit_test(*bitmap, bit);
 89  	bit_clear(*bitmap, bit);
 90  	return bit_is_set;
 91  }
 92  
 93  /* Non-atomically set the bit and returns whether the bit value was changed */
 94  inline static bool
 95  bit_set_if_clear(uint64_t *bitmap, int bit)
 96  {
 97  	bool bit_is_set = bit_test(*bitmap, bit);
 98  	bit_set(*bitmap, bit);
 99  	return !bit_is_set;
100  }
101  
102  /* Returns the most significant '1' bit, or -1 if all zeros */
103  inline static int
104  bit_first(uint64_t bitmap)
105  {
106  #if defined(__arm64__)
107  	int64_t result;
108  	asm volatile ("clz %0, %1" : "=r" (result) : "r" (bitmap));
109  	return 63 - (int)result;
110  #else
111  	return (bitmap == 0) ? -1 : 63 - __builtin_clzll(bitmap);
112  #endif
113  }
114  
115  
116  inline 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   */
127  inline static int
128  bit_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 */
138  inline static int
139  lsb_first(uint64_t bitmap)
140  {
141  	return __builtin_ffsll((long long)bitmap) - 1;
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   */
148  inline static int
149  lsb_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  
156  inline static int
157  bit_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 */
163  inline static int
164  bit_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 */
170  inline static int
171  bit_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) */
180  #define bit_log2(n)             bit_floor((uint64_t)(n))
181  
182  typedef uint64_t                bitmap_t;
183  
184  
185  inline static bool
186  atomic_bit_set(_Atomic bitmap_t *map, int n, int mem_order)
187  {
188  	bitmap_t prev;
189  	prev = __c11_atomic_fetch_or(map, BIT(n), mem_order);
190  	return bit_test(prev, n);
191  }
192  
193  inline static bool
194  atomic_bit_clear(_Atomic bitmap_t *map, int n, int mem_order)
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  
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)
206  
207  inline static bitmap_t *
208  bitmap_zero(bitmap_t *map, uint nbits)
209  {
210  	return (bitmap_t *)memset((void *)map, 0, BITMAP_SIZE(nbits));
211  }
212  
213  inline static bitmap_t *
214  bitmap_full(bitmap_t *map, uint nbits)
215  {
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  
231  inline static bool
232  bitmap_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;
249  }
250  
251  inline static bitmap_t *
252  bitmap_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  
262  inline static void
263  bitmap_free(bitmap_t *map, uint nbits)
264  {
265  	assert(nbits > 0);
266  	kfree(map, BITMAP_SIZE(nbits));
267  }
268  
269  inline static void
270  bitmap_set(bitmap_t *map, uint n)
271  {
272  	bit_set(map[bitmap_index(n)], bitmap_bit(n));
273  }
274  
275  inline static void
276  bitmap_clear(bitmap_t *map, uint n)
277  {
278  	bit_clear(map[bitmap_index(n)], bitmap_bit(n));
279  }
280  
281  inline static bool
282  atomic_bitmap_set(_Atomic bitmap_t *map, uint n, int mem_order)
283  {
284  	return atomic_bit_set(&map[bitmap_index(n)], bitmap_bit(n), mem_order);
285  }
286  
287  inline static bool
288  atomic_bitmap_clear(_Atomic bitmap_t *map, uint n, int mem_order)
289  {
290  	return atomic_bit_clear(&map[bitmap_index(n)], bitmap_bit(n), mem_order);
291  }
292  
293  inline static bool
294  bitmap_test(const bitmap_t *map, uint n)
295  {
296  	return bit_test(map[bitmap_index(n)], bitmap_bit(n));
297  }
298  
299  inline static int
300  bitmap_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  
312  inline static void
313  bitmap_not(bitmap_t *out, const bitmap_t *in, uint nbits)
314  {
315  	uint i;
316  
317  	for (i = 0; i < bitmap_index(nbits - 1); i++) {
318  		out[i] = ~in[i];
319  	}
320  
321  	uint nbits_complete = i * 64;
322  
323  	if (nbits > nbits_complete) {
324  		out[i] = ~in[i] & mask(nbits - nbits_complete);
325  	}
326  }
327  
328  inline static void
329  bitmap_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  
336  inline static void
337  bitmap_and_not(bitmap_t *out, const bitmap_t *in1, const bitmap_t *in2, uint nbits)
338  {
339  	uint i;
340  
341  	for (i = 0; i < bitmap_index(nbits - 1); i++) {
342  		out[i] = in1[i] & ~in2[i];
343  	}
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  	}
350  }
351  
352  inline static bool
353  bitmap_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  
364  inline static int
365  bitmap_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  
377  inline static int
378  bitmap_lsb_first(const bitmap_t *map, uint nbits)
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  
390  inline static int
391  bitmap_next(const bitmap_t *map, uint prev)
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  
413  inline static int
414  bitmap_lsb_next(const bitmap_t *map, uint nbits, uint prev)
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