1dfc1fec2SAndrew Jones /* SPDX-License-Identifier: GPL-2.0-only */
2f20e2561SAndrew Jones /*
3f20e2561SAndrew Jones * Simple cpumask implementation
4f20e2561SAndrew Jones *
5f20e2561SAndrew Jones * Copyright (C) 2015, Red Hat Inc, Andrew Jones <drjones@redhat.com>
6f20e2561SAndrew Jones */
7dfc1fec2SAndrew Jones #ifndef _CPUMASK_H_
8dfc1fec2SAndrew Jones #define _CPUMASK_H_
96ed97c50SPeter Feiner #include <bitops.h>
107213c4d6SAndrew Jones #include <limits.h>
117213c4d6SAndrew Jones #include <asm/setup.h>
12f20e2561SAndrew Jones
13f20e2561SAndrew Jones #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG)
14f20e2561SAndrew Jones
15f20e2561SAndrew Jones typedef struct cpumask {
16f20e2561SAndrew Jones unsigned long bits[CPUMASK_NR_LONGS];
17f20e2561SAndrew Jones } cpumask_t;
18f20e2561SAndrew Jones
19f20e2561SAndrew Jones #define cpumask_bits(maskp) ((maskp)->bits)
20f20e2561SAndrew Jones
cpumask_set_cpu(int cpu,cpumask_t * mask)21f20e2561SAndrew Jones static inline void cpumask_set_cpu(int cpu, cpumask_t *mask)
22f20e2561SAndrew Jones {
23adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus);
24f20e2561SAndrew Jones set_bit(cpu, cpumask_bits(mask));
25f20e2561SAndrew Jones }
26f20e2561SAndrew Jones
cpumask_clear_cpu(int cpu,cpumask_t * mask)27f20e2561SAndrew Jones static inline void cpumask_clear_cpu(int cpu, cpumask_t *mask)
28f20e2561SAndrew Jones {
29adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus);
30f20e2561SAndrew Jones clear_bit(cpu, cpumask_bits(mask));
31f20e2561SAndrew Jones }
32f20e2561SAndrew Jones
cpumask_test_cpu(int cpu,const cpumask_t * mask)33f20e2561SAndrew Jones static inline int cpumask_test_cpu(int cpu, const cpumask_t *mask)
34f20e2561SAndrew Jones {
35adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus);
36f20e2561SAndrew Jones return test_bit(cpu, cpumask_bits(mask));
37f20e2561SAndrew Jones }
38f20e2561SAndrew Jones
cpumask_test_and_set_cpu(int cpu,cpumask_t * mask)39f20e2561SAndrew Jones static inline int cpumask_test_and_set_cpu(int cpu, cpumask_t *mask)
40f20e2561SAndrew Jones {
41adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus);
42f20e2561SAndrew Jones return test_and_set_bit(cpu, cpumask_bits(mask));
43f20e2561SAndrew Jones }
44f20e2561SAndrew Jones
cpumask_test_and_clear_cpu(int cpu,cpumask_t * mask)45f20e2561SAndrew Jones static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask)
46f20e2561SAndrew Jones {
47adae1302SNikos Nikoleris assert(cpu >= 0 && cpu < nr_cpus);
48f20e2561SAndrew Jones return test_and_clear_bit(cpu, cpumask_bits(mask));
49f20e2561SAndrew Jones }
50f20e2561SAndrew Jones
cpumask_setall(cpumask_t * mask)51f20e2561SAndrew Jones static inline void cpumask_setall(cpumask_t *mask)
52f20e2561SAndrew Jones {
537213c4d6SAndrew Jones memset(mask, 0xff, sizeof(*mask));
54f20e2561SAndrew Jones }
55f20e2561SAndrew Jones
cpumask_clear(cpumask_t * mask)56f20e2561SAndrew Jones static inline void cpumask_clear(cpumask_t *mask)
57f20e2561SAndrew Jones {
587213c4d6SAndrew Jones memset(mask, 0, sizeof(*mask));
59f20e2561SAndrew Jones }
60f20e2561SAndrew Jones
619c86d8cdSAndrew Jones /* true if src1 is a subset of src2 */
cpumask_subset(const struct cpumask * src1,const struct cpumask * src2)629c86d8cdSAndrew Jones static inline bool cpumask_subset(const struct cpumask *src1, const struct cpumask *src2)
639c86d8cdSAndrew Jones {
649c86d8cdSAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
659c86d8cdSAndrew Jones int i;
669c86d8cdSAndrew Jones
679c86d8cdSAndrew Jones for (i = 0; i < BIT_WORD(nr_cpus); ++i) {
689c86d8cdSAndrew Jones if (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i])
699c86d8cdSAndrew Jones return false;
709c86d8cdSAndrew Jones }
719c86d8cdSAndrew Jones
729c86d8cdSAndrew Jones return !lastmask || !((cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask);
739c86d8cdSAndrew Jones }
749c86d8cdSAndrew Jones
75*f3b9c870SAndrew Jones /* false if dst is empty */
cpumask_and(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)76*f3b9c870SAndrew Jones static inline bool cpumask_and(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2)
77*f3b9c870SAndrew Jones {
78*f3b9c870SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
79*f3b9c870SAndrew Jones unsigned long ret = 0;
80*f3b9c870SAndrew Jones int i;
81*f3b9c870SAndrew Jones
82*f3b9c870SAndrew Jones for (i = 0; i < BIT_WORD(nr_cpus); ++i) {
83*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = cpumask_bits(src1)[i] & cpumask_bits(src2)[i];
84*f3b9c870SAndrew Jones ret |= cpumask_bits(dst)[i];
85*f3b9c870SAndrew Jones }
86*f3b9c870SAndrew Jones
87*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] & cpumask_bits(src2)[i]) & lastmask;
88*f3b9c870SAndrew Jones
89*f3b9c870SAndrew Jones return ret | cpumask_bits(dst)[i];
90*f3b9c870SAndrew Jones }
91*f3b9c870SAndrew Jones
cpumask_or(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)92*f3b9c870SAndrew Jones static inline void cpumask_or(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2)
93*f3b9c870SAndrew Jones {
94*f3b9c870SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
95*f3b9c870SAndrew Jones int i;
96*f3b9c870SAndrew Jones
97*f3b9c870SAndrew Jones for (i = 0; i < BIT_WORD(nr_cpus); ++i)
98*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = cpumask_bits(src1)[i] | cpumask_bits(src2)[i];
99*f3b9c870SAndrew Jones
100*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] | cpumask_bits(src2)[i]) & lastmask;
101*f3b9c870SAndrew Jones }
102*f3b9c870SAndrew Jones
cpumask_xor(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)103*f3b9c870SAndrew Jones static inline void cpumask_xor(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2)
104*f3b9c870SAndrew Jones {
105*f3b9c870SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
106*f3b9c870SAndrew Jones int i;
107*f3b9c870SAndrew Jones
108*f3b9c870SAndrew Jones for (i = 0; i < BIT_WORD(nr_cpus); ++i)
109*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = cpumask_bits(src1)[i] ^ cpumask_bits(src2)[i];
110*f3b9c870SAndrew Jones
111*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] ^ cpumask_bits(src2)[i]) & lastmask;
112*f3b9c870SAndrew Jones }
113*f3b9c870SAndrew Jones
114*f3b9c870SAndrew Jones /* false if dst is empty */
cpumask_andnot(cpumask_t * dst,const cpumask_t * src1,const cpumask_t * src2)115*f3b9c870SAndrew Jones static inline bool cpumask_andnot(cpumask_t *dst, const cpumask_t *src1, const cpumask_t *src2)
116*f3b9c870SAndrew Jones {
117*f3b9c870SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
118*f3b9c870SAndrew Jones unsigned long ret = 0;
119*f3b9c870SAndrew Jones int i;
120*f3b9c870SAndrew Jones
121*f3b9c870SAndrew Jones for (i = 0; i < BIT_WORD(nr_cpus); ++i) {
122*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i];
123*f3b9c870SAndrew Jones ret |= cpumask_bits(dst)[i];
124*f3b9c870SAndrew Jones }
125*f3b9c870SAndrew Jones
126*f3b9c870SAndrew Jones cpumask_bits(dst)[i] = (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask;
127*f3b9c870SAndrew Jones
128*f3b9c870SAndrew Jones return ret | cpumask_bits(dst)[i];
129*f3b9c870SAndrew Jones }
130*f3b9c870SAndrew Jones
cpumask_equal(const struct cpumask * src1,const struct cpumask * src2)131498a191aSCade Richard static inline bool cpumask_equal(const struct cpumask *src1, const struct cpumask *src2)
132498a191aSCade Richard {
133498a191aSCade Richard unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
134498a191aSCade Richard int i;
135498a191aSCade Richard
136498a191aSCade Richard for (i = 0; i < BIT_WORD(nr_cpus); ++i) {
137498a191aSCade Richard if (cpumask_bits(src1)[i] != cpumask_bits(src2)[i])
138498a191aSCade Richard return false;
139498a191aSCade Richard }
140498a191aSCade Richard
141498a191aSCade Richard return !lastmask || (cpumask_bits(src1)[i] & lastmask) == (cpumask_bits(src2)[i] & lastmask);
142498a191aSCade Richard }
143498a191aSCade Richard
cpumask_empty(const cpumask_t * mask)144f20e2561SAndrew Jones static inline bool cpumask_empty(const cpumask_t *mask)
145f20e2561SAndrew Jones {
1467213c4d6SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
1477213c4d6SAndrew Jones
1487213c4d6SAndrew Jones for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
1497213c4d6SAndrew Jones if (cpumask_bits(mask)[i])
150f20e2561SAndrew Jones return false;
1517213c4d6SAndrew Jones
1527213c4d6SAndrew Jones return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask);
153f20e2561SAndrew Jones }
154f20e2561SAndrew Jones
cpumask_full(const cpumask_t * mask)155f20e2561SAndrew Jones static inline bool cpumask_full(const cpumask_t *mask)
156f20e2561SAndrew Jones {
1577213c4d6SAndrew Jones unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
1587213c4d6SAndrew Jones
1597213c4d6SAndrew Jones for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
1607213c4d6SAndrew Jones if (cpumask_bits(mask)[i] != ULONG_MAX)
161f20e2561SAndrew Jones return false;
1627213c4d6SAndrew Jones
1637213c4d6SAndrew Jones return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask;
164f20e2561SAndrew Jones }
165f20e2561SAndrew Jones
cpumask_weight(const cpumask_t * mask)166f20e2561SAndrew Jones static inline int cpumask_weight(const cpumask_t *mask)
167f20e2561SAndrew Jones {
168f20e2561SAndrew Jones int w = 0, i;
169f20e2561SAndrew Jones
170f20e2561SAndrew Jones for (i = 0; i < nr_cpus; ++i)
171f20e2561SAndrew Jones if (cpumask_test_cpu(i, mask))
172f20e2561SAndrew Jones ++w;
173f20e2561SAndrew Jones return w;
174f20e2561SAndrew Jones }
175f20e2561SAndrew Jones
cpumask_copy(cpumask_t * dst,const cpumask_t * src)176f20e2561SAndrew Jones static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src)
177f20e2561SAndrew Jones {
178f20e2561SAndrew Jones memcpy(cpumask_bits(dst), cpumask_bits(src),
179f20e2561SAndrew Jones CPUMASK_NR_LONGS * sizeof(long));
180f20e2561SAndrew Jones }
181f20e2561SAndrew Jones
cpumask_next(int cpu,const cpumask_t * mask)182f20e2561SAndrew Jones static inline int cpumask_next(int cpu, const cpumask_t *mask)
183f20e2561SAndrew Jones {
184fdab948bSNikos Nikoleris while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask))
185f20e2561SAndrew Jones ;
186f20e2561SAndrew Jones return cpu;
187f20e2561SAndrew Jones }
188f20e2561SAndrew Jones
189f20e2561SAndrew Jones #define for_each_cpu(cpu, mask) \
190f20e2561SAndrew Jones for ((cpu) = cpumask_next(-1, mask); \
191f20e2561SAndrew Jones (cpu) < nr_cpus; \
192f20e2561SAndrew Jones (cpu) = cpumask_next(cpu, mask))
193f20e2561SAndrew Jones
194905b0e66SAndrew Jones extern cpumask_t cpu_present_mask;
195905b0e66SAndrew Jones extern cpumask_t cpu_online_mask;
196905b0e66SAndrew Jones extern cpumask_t cpu_idle_mask;
197905b0e66SAndrew Jones #define cpu_present(cpu) cpumask_test_cpu(cpu, &cpu_present_mask)
198905b0e66SAndrew Jones #define cpu_online(cpu) cpumask_test_cpu(cpu, &cpu_online_mask)
199905b0e66SAndrew Jones #define cpu_idle(cpu) cpumask_test_cpu(cpu, &cpu_idle_mask)
200905b0e66SAndrew Jones #define for_each_present_cpu(cpu) for_each_cpu(cpu, &cpu_present_mask)
201905b0e66SAndrew Jones #define for_each_online_cpu(cpu) for_each_cpu(cpu, &cpu_online_mask)
202905b0e66SAndrew Jones
set_cpu_present(int cpu,bool present)203905b0e66SAndrew Jones static inline void set_cpu_present(int cpu, bool present)
204905b0e66SAndrew Jones {
205905b0e66SAndrew Jones if (present)
206905b0e66SAndrew Jones cpumask_set_cpu(cpu, &cpu_present_mask);
207905b0e66SAndrew Jones else
208905b0e66SAndrew Jones cpumask_clear_cpu(cpu, &cpu_present_mask);
209905b0e66SAndrew Jones }
210905b0e66SAndrew Jones
set_cpu_online(int cpu,bool online)211905b0e66SAndrew Jones static inline void set_cpu_online(int cpu, bool online)
212905b0e66SAndrew Jones {
213905b0e66SAndrew Jones if (online)
214905b0e66SAndrew Jones cpumask_set_cpu(cpu, &cpu_online_mask);
215905b0e66SAndrew Jones else
216905b0e66SAndrew Jones cpumask_clear_cpu(cpu, &cpu_online_mask);
217905b0e66SAndrew Jones }
218905b0e66SAndrew Jones
set_cpu_idle(int cpu,bool idle)219905b0e66SAndrew Jones static inline void set_cpu_idle(int cpu, bool idle)
220905b0e66SAndrew Jones {
221905b0e66SAndrew Jones if (idle)
222905b0e66SAndrew Jones cpumask_set_cpu(cpu, &cpu_idle_mask);
223905b0e66SAndrew Jones else
224905b0e66SAndrew Jones cpumask_clear_cpu(cpu, &cpu_idle_mask);
225905b0e66SAndrew Jones }
226905b0e66SAndrew Jones
227dfc1fec2SAndrew Jones #endif /* _CPUMASK_H_ */
228