xref: /kvm-unit-tests/lib/cpumask.h (revision 9c86d8cd8507b94cde974158eceed0df4476bc3b)
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 
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 
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 
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 
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 
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 
51f20e2561SAndrew Jones static inline void cpumask_setall(cpumask_t *mask)
52f20e2561SAndrew Jones {
537213c4d6SAndrew Jones 	memset(mask, 0xff, sizeof(*mask));
54f20e2561SAndrew Jones }
55f20e2561SAndrew Jones 
56f20e2561SAndrew Jones static inline void cpumask_clear(cpumask_t *mask)
57f20e2561SAndrew Jones {
587213c4d6SAndrew Jones 	memset(mask, 0, sizeof(*mask));
59f20e2561SAndrew Jones }
60f20e2561SAndrew Jones 
61*9c86d8cdSAndrew Jones /* true if src1 is a subset of src2 */
62*9c86d8cdSAndrew Jones static inline bool cpumask_subset(const struct cpumask *src1, const struct cpumask *src2)
63*9c86d8cdSAndrew Jones {
64*9c86d8cdSAndrew Jones 	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
65*9c86d8cdSAndrew Jones 	int i;
66*9c86d8cdSAndrew Jones 
67*9c86d8cdSAndrew Jones 	for (i = 0; i < BIT_WORD(nr_cpus); ++i) {
68*9c86d8cdSAndrew Jones 		if (cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i])
69*9c86d8cdSAndrew Jones 			return false;
70*9c86d8cdSAndrew Jones 	}
71*9c86d8cdSAndrew Jones 
72*9c86d8cdSAndrew Jones 	return !lastmask || !((cpumask_bits(src1)[i] & ~cpumask_bits(src2)[i]) & lastmask);
73*9c86d8cdSAndrew Jones }
74*9c86d8cdSAndrew Jones 
75f20e2561SAndrew Jones static inline bool cpumask_empty(const cpumask_t *mask)
76f20e2561SAndrew Jones {
777213c4d6SAndrew Jones 	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
787213c4d6SAndrew Jones 
797213c4d6SAndrew Jones 	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
807213c4d6SAndrew Jones 		if (cpumask_bits(mask)[i])
81f20e2561SAndrew Jones 			return false;
827213c4d6SAndrew Jones 
837213c4d6SAndrew Jones 	return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask);
84f20e2561SAndrew Jones }
85f20e2561SAndrew Jones 
86f20e2561SAndrew Jones static inline bool cpumask_full(const cpumask_t *mask)
87f20e2561SAndrew Jones {
887213c4d6SAndrew Jones 	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
897213c4d6SAndrew Jones 
907213c4d6SAndrew Jones 	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
917213c4d6SAndrew Jones 		if (cpumask_bits(mask)[i] != ULONG_MAX)
92f20e2561SAndrew Jones 			return false;
937213c4d6SAndrew Jones 
947213c4d6SAndrew Jones 	return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask;
95f20e2561SAndrew Jones }
96f20e2561SAndrew Jones 
97f20e2561SAndrew Jones static inline int cpumask_weight(const cpumask_t *mask)
98f20e2561SAndrew Jones {
99f20e2561SAndrew Jones 	int w = 0, i;
100f20e2561SAndrew Jones 
101f20e2561SAndrew Jones 	for (i = 0; i < nr_cpus; ++i)
102f20e2561SAndrew Jones 		if (cpumask_test_cpu(i, mask))
103f20e2561SAndrew Jones 			++w;
104f20e2561SAndrew Jones 	return w;
105f20e2561SAndrew Jones }
106f20e2561SAndrew Jones 
107f20e2561SAndrew Jones static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src)
108f20e2561SAndrew Jones {
109f20e2561SAndrew Jones 	memcpy(cpumask_bits(dst), cpumask_bits(src),
110f20e2561SAndrew Jones 			CPUMASK_NR_LONGS * sizeof(long));
111f20e2561SAndrew Jones }
112f20e2561SAndrew Jones 
113f20e2561SAndrew Jones static inline int cpumask_next(int cpu, const cpumask_t *mask)
114f20e2561SAndrew Jones {
115fdab948bSNikos Nikoleris 	while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask))
116f20e2561SAndrew Jones 		;
117f20e2561SAndrew Jones 	return cpu;
118f20e2561SAndrew Jones }
119f20e2561SAndrew Jones 
120f20e2561SAndrew Jones #define for_each_cpu(cpu, mask)					\
121f20e2561SAndrew Jones 	for ((cpu) = cpumask_next(-1, mask);			\
122f20e2561SAndrew Jones 			(cpu) < nr_cpus; 			\
123f20e2561SAndrew Jones 			(cpu) = cpumask_next(cpu, mask))
124f20e2561SAndrew Jones 
125905b0e66SAndrew Jones extern cpumask_t cpu_present_mask;
126905b0e66SAndrew Jones extern cpumask_t cpu_online_mask;
127905b0e66SAndrew Jones extern cpumask_t cpu_idle_mask;
128905b0e66SAndrew Jones #define cpu_present(cpu)		cpumask_test_cpu(cpu, &cpu_present_mask)
129905b0e66SAndrew Jones #define cpu_online(cpu)			cpumask_test_cpu(cpu, &cpu_online_mask)
130905b0e66SAndrew Jones #define cpu_idle(cpu)			cpumask_test_cpu(cpu, &cpu_idle_mask)
131905b0e66SAndrew Jones #define for_each_present_cpu(cpu)	for_each_cpu(cpu, &cpu_present_mask)
132905b0e66SAndrew Jones #define for_each_online_cpu(cpu)	for_each_cpu(cpu, &cpu_online_mask)
133905b0e66SAndrew Jones 
134905b0e66SAndrew Jones static inline void set_cpu_present(int cpu, bool present)
135905b0e66SAndrew Jones {
136905b0e66SAndrew Jones 	if (present)
137905b0e66SAndrew Jones 		cpumask_set_cpu(cpu, &cpu_present_mask);
138905b0e66SAndrew Jones 	else
139905b0e66SAndrew Jones 		cpumask_clear_cpu(cpu, &cpu_present_mask);
140905b0e66SAndrew Jones }
141905b0e66SAndrew Jones 
142905b0e66SAndrew Jones static inline void set_cpu_online(int cpu, bool online)
143905b0e66SAndrew Jones {
144905b0e66SAndrew Jones 	if (online)
145905b0e66SAndrew Jones 		cpumask_set_cpu(cpu, &cpu_online_mask);
146905b0e66SAndrew Jones 	else
147905b0e66SAndrew Jones 		cpumask_clear_cpu(cpu, &cpu_online_mask);
148905b0e66SAndrew Jones }
149905b0e66SAndrew Jones 
150905b0e66SAndrew Jones static inline void set_cpu_idle(int cpu, bool idle)
151905b0e66SAndrew Jones {
152905b0e66SAndrew Jones 	if (idle)
153905b0e66SAndrew Jones 		cpumask_set_cpu(cpu, &cpu_idle_mask);
154905b0e66SAndrew Jones 	else
155905b0e66SAndrew Jones 		cpumask_clear_cpu(cpu, &cpu_idle_mask);
156905b0e66SAndrew Jones }
157905b0e66SAndrew Jones 
158dfc1fec2SAndrew Jones #endif /* _CPUMASK_H_ */
159