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 /* true if src1 is a subset of src2 */ 62 static inline bool cpumask_subset(const struct cpumask *src1, const struct cpumask *src2) 63 { 64 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 65 int i; 66 67 for (i = 0; i < BIT_WORD(nr_cpus); ++i) { 68 if (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) 69 return false; 70 } 71 72 return !lastmask || !((cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask); 73 } 74 75 /* false if dst is empty */ 76 static inline bool cpumask_and(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) 77 { 78 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 79 unsigned long ret = 0; 80 int i; 81 82 for (i = 0; i < BIT_WORD(nr_cpus); ++i) { 83 cpumask_bits(dst)[i] = cpumask_bits(src1)[i] & cpumask_bits(src2)[i]; 84 ret |= cpumask_bits(dst)[i]; 85 } 86 87 cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] & cpumask_bits(src2)[i]) & lastmask; 88 89 return ret | cpumask_bits(dst)[i]; 90 } 91 92 static inline void cpumask_or(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) 93 { 94 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 95 int i; 96 97 for (i = 0; i < BIT_WORD(nr_cpus); ++i) 98 cpumask_bits(dst)[i] = cpumask_bits(src1)[i] | cpumask_bits(src2)[i]; 99 100 cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] | cpumask_bits(src2)[i]) & lastmask; 101 } 102 103 static inline void cpumask_xor(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) 104 { 105 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 106 int i; 107 108 for (i = 0; i < BIT_WORD(nr_cpus); ++i) 109 cpumask_bits(dst)[i] = cpumask_bits(src1)[i] ^ cpumask_bits(src2)[i]; 110 111 cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] ^ cpumask_bits(src2)[i]) & lastmask; 112 } 113 114 /* false if dst is empty */ 115 static inline bool cpumask_andnot(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2) 116 { 117 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 118 unsigned long ret = 0; 119 int i; 120 121 for (i = 0; i < BIT_WORD(nr_cpus); ++i) { 122 cpumask_bits(dst)[i] = cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]; 123 ret |= cpumask_bits(dst)[i]; 124 } 125 126 cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask; 127 128 return ret | cpumask_bits(dst)[i]; 129 } 130 131 static inline bool cpumask_equal(const struct cpumask *src1, const struct cpumask *src2) 132 { 133 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 134 int i; 135 136 for (i = 0; i < BIT_WORD(nr_cpus); ++i) { 137 if (cpumask_bits(src1)[i] != cpumask_bits(src2)[i]) 138 return false; 139 } 140 141 return !lastmask || (cpumask_bits(src1)[i] & lastmask) == (cpumask_bits(src2)[i] & lastmask); 142 } 143 144 static inline bool cpumask_empty(const cpumask_t *mask) 145 { 146 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 147 148 for (int i = 0; i < BIT_WORD(nr_cpus); ++i) 149 if (cpumask_bits(mask)[i]) 150 return false; 151 152 return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask); 153 } 154 155 static inline bool cpumask_full(const cpumask_t *mask) 156 { 157 unsigned long lastmask = BIT_MASK(nr_cpus) - 1; 158 159 for (int i = 0; i < BIT_WORD(nr_cpus); ++i) 160 if (cpumask_bits(mask)[i] != ULONG_MAX) 161 return false; 162 163 return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask; 164 } 165 166 static inline int cpumask_weight(const cpumask_t *mask) 167 { 168 int w = 0, i; 169 170 for (i = 0; i < nr_cpus; ++i) 171 if (cpumask_test_cpu(i, mask)) 172 ++w; 173 return w; 174 } 175 176 static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src) 177 { 178 memcpy(cpumask_bits(dst), cpumask_bits(src), 179 CPUMASK_NR_LONGS * sizeof(long)); 180 } 181 182 static inline int cpumask_next(int cpu, const cpumask_t *mask) 183 { 184 while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask)) 185 ; 186 return cpu; 187 } 188 189 #define for_each_cpu(cpu, mask) \ 190 for ((cpu) = cpumask_next(-1, mask); \ 191 (cpu) < nr_cpus; \ 192 (cpu) = cpumask_next(cpu, mask)) 193 194 extern cpumask_t cpu_present_mask; 195 extern cpumask_t cpu_online_mask; 196 extern cpumask_t cpu_idle_mask; 197 #define cpu_present(cpu) cpumask_test_cpu(cpu, &cpu_present_mask) 198 #define cpu_online(cpu) cpumask_test_cpu(cpu, &cpu_online_mask) 199 #define cpu_idle(cpu) cpumask_test_cpu(cpu, &cpu_idle_mask) 200 #define for_each_present_cpu(cpu) for_each_cpu(cpu, &cpu_present_mask) 201 #define for_each_online_cpu(cpu) for_each_cpu(cpu, &cpu_online_mask) 202 203 static inline void set_cpu_present(int cpu, bool present) 204 { 205 if (present) 206 cpumask_set_cpu(cpu, &cpu_present_mask); 207 else 208 cpumask_clear_cpu(cpu, &cpu_present_mask); 209 } 210 211 static inline void set_cpu_online(int cpu, bool online) 212 { 213 if (online) 214 cpumask_set_cpu(cpu, &cpu_online_mask); 215 else 216 cpumask_clear_cpu(cpu, &cpu_online_mask); 217 } 218 219 static inline void set_cpu_idle(int cpu, bool idle) 220 { 221 if (idle) 222 cpumask_set_cpu(cpu, &cpu_idle_mask); 223 else 224 cpumask_clear_cpu(cpu, &cpu_idle_mask); 225 } 226 227 #endif /* _CPUMASK_H_ */ 228