]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/bits.h
   2  * Copyright (c) 2015-2016 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28  * Bit manipulation functions 
  34 #include <kern/assert.h> 
  35 #include <kern/kalloc.h> 
  39 typedef unsigned int                    uint
; 
  41 #define BIT(b)                          (1ULL << (b)) 
  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) 
  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))) 
  51 inline static uint64_t 
  52 bit_ror64(uint64_t bitmap
, uint n
) 
  54 #if defined(__arm64__) 
  56         uint64_t _n 
= (uint64_t)n
; 
  57         asm volatile ("ror %0, %1, %2" : "=r" (result
) : "r" (bitmap
), "r" (_n
)); 
  61         return (bitmap 
>> n
) | (bitmap 
<< (64 - n
)); 
  65 inline static uint64_t 
  66 bit_rol64(uint64_t bitmap
, uint n
) 
  68 #if defined(__arm64__) 
  69         return bit_ror64(bitmap
, 64U - n
); 
  72         return (bitmap 
<< n
) | (bitmap 
>> (64 - n
)); 
  76 /* Non-atomically clear the bit and returns whether the bit value was changed */ 
  78 bit_clear_if_set(uint64_t bitmap
, int bit
) 
  80         bool bit_is_set 
= bit_test(bitmap
, bit
); 
  81         bit_clear(bitmap
, bit
); 
  85 /* Non-atomically set the bit and returns whether the bit value was changed */ 
  87 bit_set_if_clear(uint64_t bitmap
, int bit
) 
  89         bool bit_is_set 
= bit_test(bitmap
, bit
); 
  94 /* Returns the most significant '1' bit, or -1 if all zeros */ 
  96 bit_first(uint64_t bitmap
) 
  98 #if defined(__arm64__) 
 100         asm volatile ("clz %0, %1" : "=r" (result
) : "r" (bitmap
)); 
 101         return 63 - (int)result
; 
 103         return (bitmap 
== 0) ? -1 : 63 - __builtin_clzll(bitmap
); 
 109 __bit_next(uint64_t bitmap
, int previous_bit
) 
 111         uint64_t mask 
= previous_bit 
? mask(previous_bit
) : ~0ULL; 
 113         return bit_first(bitmap 
& mask
); 
 116 /* Returns the most significant '1' bit that is less significant than previous_bit, 
 117  * or -1 if no such bit exists. 
 120 bit_next(uint64_t bitmap
, int previous_bit
) 
 122         if (previous_bit 
== 0) { 
 125                 return __bit_next(bitmap
, previous_bit
); 
 129 /* Returns the least significant '1' bit, or -1 if all zeros */ 
 131 lsb_first(uint64_t bitmap
) 
 133         return __builtin_ffsll(bitmap
) - 1; 
 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() 
 141 lsb_next(uint64_t bitmap
, int previous_bit
) 
 143         uint64_t mask 
= mask(previous_bit 
+ 1); 
 145         return lsb_first(bitmap 
& ~mask
); 
 149 bit_count(uint64_t x
) 
 151         return __builtin_popcountll(x
); 
 154 /* Return the highest power of 2 that is <= n, or -1 if n == 0 */ 
 156 bit_floor(uint64_t n
) 
 161 /* Return the lowest power of 2 that is >= n, or -1 if n == 0 */ 
 163 bit_ceiling(uint64_t n
) 
 168         return bit_first(n 
- 1) + 1; 
 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)) 
 174 typedef uint64_t                bitmap_t
; 
 178 atomic_bit_set(_Atomic bitmap_t 
*map
, int n
, int mem_order
) 
 181         prev 
= __c11_atomic_fetch_or(map
, BIT(n
), mem_order
); 
 182         return bit_test(prev
, n
); 
 186 atomic_bit_clear(_Atomic bitmap_t 
*map
, int n
, int mem_order
) 
 189         prev 
= __c11_atomic_fetch_and(map
, ~BIT(n
), mem_order
); 
 190         return bit_test(prev
, n
); 
 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) 
 199 inline static bitmap_t 
* 
 200 bitmap_zero(bitmap_t 
*map
, uint nbits
) 
 202         return (bitmap_t 
*)memset((void *)map
, 0, BITMAP_SIZE(nbits
)); 
 205 inline static bitmap_t 
* 
 206 bitmap_full(bitmap_t 
*map
, uint nbits
) 
 208         return (bitmap_t 
*)memset((void *)map
, ~0, BITMAP_SIZE(nbits
)); 
 211 inline static bitmap_t 
* 
 212 bitmap_alloc(uint nbits
) 
 215         bitmap_t 
*map 
= (bitmap_t 
*)kalloc(BITMAP_SIZE(nbits
)); 
 217                 bitmap_zero(map
, nbits
); 
 223 bitmap_free(bitmap_t 
*map
, uint nbits
) 
 226         kfree(map
, BITMAP_SIZE(nbits
)); 
 230 bitmap_set(bitmap_t 
*map
, uint n
) 
 232         bit_set(map
[bitmap_index(n
)], bitmap_bit(n
)); 
 236 bitmap_clear(bitmap_t 
*map
, uint n
) 
 238         bit_clear(map
[bitmap_index(n
)], bitmap_bit(n
)); 
 242 atomic_bitmap_set(_Atomic bitmap_t 
*map
, uint n
, int mem_order
) 
 244         return atomic_bit_set(&map
[bitmap_index(n
)], bitmap_bit(n
), mem_order
); 
 248 atomic_bitmap_clear(_Atomic bitmap_t 
*map
, uint n
, int mem_order
) 
 250         return atomic_bit_clear(&map
[bitmap_index(n
)], bitmap_bit(n
), mem_order
); 
 254 bitmap_test(bitmap_t 
*map
, uint n
) 
 256         return bit_test(map
[bitmap_index(n
)], bitmap_bit(n
)); 
 260 bitmap_first(bitmap_t 
*map
, uint nbits
) 
 262         for (int i 
= (int)bitmap_index(nbits 
- 1); i 
>= 0; i
--) { 
 266                 return (i 
<< 6) + bit_first(map
[i
]); 
 273 bitmap_and_not_mask_first(bitmap_t 
*map
, bitmap_t 
*mask
, uint nbits
) 
 275         for (int i 
= (int)bitmap_index(nbits 
- 1); i 
>= 0; i
--) { 
 276                 if ((map
[i
] & ~mask
[i
]) == 0) { 
 279                 return (i 
<< 6) + bit_first(map
[i
] & ~mask
[i
]); 
 286 bitmap_lsb_first(bitmap_t 
*map
, uint nbits
) 
 288         for (uint i 
= 0; i 
<= bitmap_index(nbits 
- 1); i
++) { 
 292                 return (int)((i 
<< 6) + (uint32_t)lsb_first(map
[i
])); 
 299 bitmap_next(bitmap_t 
*map
, uint prev
) 
 305         int64_t i 
= bitmap_index(prev 
- 1); 
 306         int res 
= __bit_next(map
[i
], bits(prev
, 5, 0)); 
 308                 return (int)(res 
+ (i 
<< 6)); 
 311         for (i 
= i 
- 1; i 
>= 0; i
--) { 
 315                 return (int)((i 
<< 6) + bit_first(map
[i
])); 
 322 bitmap_lsb_next(bitmap_t 
*map
, uint nbits
, uint prev
) 
 324         if ((prev 
+ 1) >= nbits
) { 
 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
); 
 332                 return (int)((uint64_t)res 
+ (i 
<< 6)); 
 335         for (i 
= i 
+ 1; i 
<= bitmap_index(nbits 
- 1); i
++) { 
 339                 return (int)((i 
<< 6) + (uint64_t)lsb_first(map
[i
]));