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
cpumask_set_cpu(int cpu,cpumask_t * mask)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
cpumask_clear_cpu(int cpu,cpumask_t * mask)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
cpumask_test_cpu(int cpu,const cpumask_t * mask)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
cpumask_test_and_set_cpu(int cpu,cpumask_t * mask)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
cpumask_test_and_clear_cpu(int cpu,cpumask_t * mask)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
cpumask_setall(cpumask_t * mask)51 static inline void cpumask_setall(cpumask_t *mask)
52 {
53 memset(mask, 0xff, sizeof(*mask));
54 }
55
cpumask_clear(cpumask_t * mask)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 */
cpumask_subset(const struct cpumask * src1,const struct cpumask * 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 */
cpumask_and(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)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
cpumask_or(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)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
cpumask_xor(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)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 */
cpumask_andnot(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)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
cpumask_equal(const struct cpumask * src1,const struct cpumask * src2)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
cpumask_empty(const cpumask_t * mask)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
cpumask_full(const cpumask_t * mask)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
cpumask_weight(const cpumask_t * mask)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
cpumask_copy(cpumask_t * dst,const cpumask_t * src)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
cpumask_next(int cpu,const cpumask_t * mask)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
set_cpu_present(int cpu,bool present)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
set_cpu_online(int cpu,bool online)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
set_cpu_idle(int cpu,bool idle)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