1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Simple cpumask implementation 4 * 5 * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com> 6 */ 7 #ifndef _CPUMASK_H_ 8 #define _CPUMASK_H_ 9 #include <bitops.h> 10 #include <limits.h> 11 #include <asm/setup.h> 12 13 #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG) 14 15 typedef struct cpumask { 16 unsigned long bits[CPUMASK_NR_LONGS]; 17 } cpumask_t; 18 19 #define cpumask_bits(maskp) ((maskp)->bits) 20 21 static inline void cpumask_set_cpu(int cpu, cpumask_t *mask) 22 { 23 assert(cpu >= 0 && cpu < nr_cpus); 24 set_bit(cpu, cpumask_bits(mask)); 25 } 26 27 static inline void cpumask_clear_cpu(int cpu, cpumask_t *mask) 28 { 29 assert(cpu >= 0 && cpu < nr_cpus); 30 clear_bit(cpu, cpumask_bits(mask)); 31 } 32 33 static inline int cpumask_test_cpu(int cpu, const cpumask_t *mask) 34 { 35 assert(cpu >= 0 && cpu < nr_cpus); 36 return test_bit(cpu, cpumask_bits(mask)); 37 } 38 39 static inline int cpumask_test_and_set_cpu(int cpu, cpumask_t *mask) 40 { 41 assert(cpu >= 0 && cpu < nr_cpus); 42 return test_and_set_bit(cpu, cpumask_bits(mask)); 43 } 44 45 static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask) 46 { 47 assert(cpu >= 0 && cpu < nr_cpus); 48 return test_and_clear_bit(cpu, cpumask_bits(mask)); 49 } 50 51 static inline void cpumask_setall(cpumask_t *mask) 52 { 53 memset(mask, 0xff, sizeof(*mask)); 54 } 55 56 static inline void cpumask_clear(cpumask_t *mask) 57 { 58 memset(mask, 0, sizeof(*mask)); 59 } 60 61 static inline bool cpumask_empty(const cpumask_t *mask) 62 { 63 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 64 65 for (int i = 0; i < BIT_WORD(nr_cpus); ++i) 66 if (cpumask_bits(mask)[i]) 67 return false; 68 69 return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask); 70 } 71 72 static inline bool cpumask_full(const cpumask_t *mask) 73 { 74 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 75 76 for (int i = 0; i < BIT_WORD(nr_cpus); ++i) 77 if (cpumask_bits(mask)[i] != ULONG_MAX) 78 return false; 79 80 return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask; 81 } 82 83 static inline int cpumask_weight(const cpumask_t *mask) 84 { 85 int w = 0, i; 86 87 for (i = 0; i < nr_cpus; ++i) 88 if (cpumask_test_cpu(i, mask)) 89 ++w; 90 return w; 91 } 92 93 static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src) 94 { 95 memcpy(cpumask_bits(dst), cpumask_bits(src), 96 CPUMASK_NR_LONGS * sizeof(long)); 97 } 98 99 static inline int cpumask_next(int cpu, const cpumask_t *mask) 100 { 101 while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask)) 102 ; 103 return cpu; 104 } 105 106 #define for_each_cpu(cpu, mask) \ 107 for ((cpu) = cpumask_next(-1, mask); \ 108 (cpu) < nr_cpus; \ 109 (cpu) = cpumask_next(cpu, mask)) 110 111 extern cpumask_t cpu_present_mask; 112 extern cpumask_t cpu_online_mask; 113 extern cpumask_t cpu_idle_mask; 114 #define cpu_present(cpu) cpumask_test_cpu(cpu, &cpu_present_mask) 115 #define cpu_online(cpu) cpumask_test_cpu(cpu, &cpu_online_mask) 116 #define cpu_idle(cpu) cpumask_test_cpu(cpu, &cpu_idle_mask) 117 #define for_each_present_cpu(cpu) for_each_cpu(cpu, &cpu_present_mask) 118 #define for_each_online_cpu(cpu) for_each_cpu(cpu, &cpu_online_mask) 119 120 static inline void set_cpu_present(int cpu, bool present) 121 { 122 if (present) 123 cpumask_set_cpu(cpu, &cpu_present_mask); 124 else 125 cpumask_clear_cpu(cpu, &cpu_present_mask); 126 } 127 128 static inline void set_cpu_online(int cpu, bool online) 129 { 130 if (online) 131 cpumask_set_cpu(cpu, &cpu_online_mask); 132 else 133 cpumask_clear_cpu(cpu, &cpu_online_mask); 134 } 135 136 static inline void set_cpu_idle(int cpu, bool idle) 137 { 138 if (idle) 139 cpumask_set_cpu(cpu, &cpu_idle_mask); 140 else 141 cpumask_clear_cpu(cpu, &cpu_idle_mask); 142 } 143 144 #endif /* _CPUMASK_H_ */ 145