xref: /kvm-unit-tests/lib/cpumask.h (revision f3b9c870a3a686d4c0c700c9b46fc125949bc851)
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