| // Copyright 2016 The Fuchsia Authors |
| // |
| // Use of this source code is governed by a MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT |
| |
| #ifndef ZIRCON_KERNEL_INCLUDE_KERNEL_CPU_H_ |
| #define ZIRCON_KERNEL_INCLUDE_KERNEL_CPU_H_ |
| |
| #include <assert.h> |
| #include <stdint.h> |
| |
| // types and routines for dealing with lists of cpus and cpu masks |
| |
| typedef uint32_t cpu_mask_t; |
| typedef uint32_t cpu_num_t; |
| |
| static_assert(SMP_MAX_CPUS <= sizeof(cpu_mask_t) * CHAR_BIT, ""); |
| |
| #define INVALID_CPU ((cpu_num_t)-1) |
| #define CPU_MASK_ALL ((cpu_mask_t)-1) |
| |
| static inline bool is_valid_cpu_num(cpu_num_t num) { return (num < SMP_MAX_CPUS); } |
| |
| static inline cpu_mask_t cpu_num_to_mask(cpu_num_t num) { |
| if (!is_valid_cpu_num(num)) { |
| return 0; |
| } |
| |
| return ((cpu_mask_t)1u << num); |
| } |
| |
| static inline cpu_mask_t mask_all_but_one(cpu_num_t num) { |
| return CPU_MASK_ALL ^ cpu_num_to_mask(num); |
| } |
| |
| static inline cpu_num_t highest_cpu_set(cpu_mask_t mask) { |
| if (mask == 0) { |
| return 0; |
| } |
| |
| return (cpu_num_t)(sizeof(cpu_mask_t) * CHAR_BIT - 1) - __builtin_clz(mask); |
| } |
| |
| static inline cpu_num_t lowest_cpu_set(cpu_mask_t mask) { |
| if (mask == 0) { |
| return 0; |
| } |
| |
| return (cpu_num_t)(__builtin_ctz(mask)); |
| } |
| |
| // Removes one CPU from the mask and returns its ID. |
| // |
| // Returns INVALID_CPU if the mask is empty. |
| static inline cpu_num_t remove_cpu_from_mask(cpu_mask_t& mask) { |
| if (mask == 0) { |
| return INVALID_CPU; |
| } |
| cpu_num_t index_of_lowest_set_bit = __builtin_ffsl(mask) - 1; |
| mask &= ~cpu_num_to_mask(index_of_lowest_set_bit); |
| return index_of_lowest_set_bit; |
| } |
| |
| #endif // ZIRCON_KERNEL_INCLUDE_KERNEL_CPU_H_ |