xref: /kvm-unit-tests/lib/cpumask.h (revision 498a191a72339f2e6ec901284292913d24655918)
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 
619c86d8cdSAndrew Jones /* true if src1 is a subset of 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*498a191aSCade Richard static inline bool cpumask_equal(const struct cpumask *src1, const struct cpumask *src2)
76*498a191aSCade Richard {
77*498a191aSCade Richard 	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
78*498a191aSCade Richard 	int i;
79*498a191aSCade Richard 
80*498a191aSCade Richard 	for (i = 0; i < BIT_WORD(nr_cpus); ++i) {
81*498a191aSCade Richard 		if (cpumask_bits(src1)[i] != cpumask_bits(src2)[i])
82*498a191aSCade Richard 			return false;
83*498a191aSCade Richard 	}
84*498a191aSCade Richard 
85*498a191aSCade Richard 	return !lastmask || (cpumask_bits(src1)[i] & lastmask) == (cpumask_bits(src2)[i] & lastmask);
86*498a191aSCade Richard }
87*498a191aSCade Richard 
88f20e2561SAndrew Jones static inline bool cpumask_empty(const cpumask_t *mask)
89f20e2561SAndrew Jones {
907213c4d6SAndrew Jones 	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
917213c4d6SAndrew Jones 
927213c4d6SAndrew Jones 	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
937213c4d6SAndrew Jones 		if (cpumask_bits(mask)[i])
94f20e2561SAndrew Jones 			return false;
957213c4d6SAndrew Jones 
967213c4d6SAndrew Jones 	return !lastmask || !(cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask);
97f20e2561SAndrew Jones }
98f20e2561SAndrew Jones 
99f20e2561SAndrew Jones static inline bool cpumask_full(const cpumask_t *mask)
100f20e2561SAndrew Jones {
1017213c4d6SAndrew Jones 	unsigned long lastmask = BIT_MASK(nr_cpus) - 1;
1027213c4d6SAndrew Jones 
1037213c4d6SAndrew Jones 	for (int i = 0; i < BIT_WORD(nr_cpus); ++i)
1047213c4d6SAndrew Jones 		if (cpumask_bits(mask)[i] != ULONG_MAX)
105f20e2561SAndrew Jones 			return false;
1067213c4d6SAndrew Jones 
1077213c4d6SAndrew Jones 	return !lastmask || (cpumask_bits(mask)[BIT_WORD(nr_cpus)] & lastmask) == lastmask;
108f20e2561SAndrew Jones }
109f20e2561SAndrew Jones 
110f20e2561SAndrew Jones static inline int cpumask_weight(const cpumask_t *mask)
111f20e2561SAndrew Jones {
112f20e2561SAndrew Jones 	int w = 0, i;
113f20e2561SAndrew Jones 
114f20e2561SAndrew Jones 	for (i = 0; i < nr_cpus; ++i)
115f20e2561SAndrew Jones 		if (cpumask_test_cpu(i, mask))
116f20e2561SAndrew Jones 			++w;
117f20e2561SAndrew Jones 	return w;
118f20e2561SAndrew Jones }
119f20e2561SAndrew Jones 
120f20e2561SAndrew Jones static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src)
121f20e2561SAndrew Jones {
122f20e2561SAndrew Jones 	memcpy(cpumask_bits(dst), cpumask_bits(src),
123f20e2561SAndrew Jones 			CPUMASK_NR_LONGS * sizeof(long));
124f20e2561SAndrew Jones }
125f20e2561SAndrew Jones 
126f20e2561SAndrew Jones static inline int cpumask_next(int cpu, const cpumask_t *mask)
127f20e2561SAndrew Jones {
128fdab948bSNikos Nikoleris 	while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask))
129f20e2561SAndrew Jones 		;
130f20e2561SAndrew Jones 	return cpu;
131f20e2561SAndrew Jones }
132f20e2561SAndrew Jones 
133f20e2561SAndrew Jones #define for_each_cpu(cpu, mask)					\
134f20e2561SAndrew Jones 	for ((cpu) = cpumask_next(-1, mask);			\
135f20e2561SAndrew Jones 			(cpu) < nr_cpus; 			\
136f20e2561SAndrew Jones 			(cpu) = cpumask_next(cpu, mask))
137f20e2561SAndrew Jones 
138905b0e66SAndrew Jones extern cpumask_t cpu_present_mask;
139905b0e66SAndrew Jones extern cpumask_t cpu_online_mask;
140905b0e66SAndrew Jones extern cpumask_t cpu_idle_mask;
141905b0e66SAndrew Jones #define cpu_present(cpu)		cpumask_test_cpu(cpu, &cpu_present_mask)
142905b0e66SAndrew Jones #define cpu_online(cpu)			cpumask_test_cpu(cpu, &cpu_online_mask)
143905b0e66SAndrew Jones #define cpu_idle(cpu)			cpumask_test_cpu(cpu, &cpu_idle_mask)
144905b0e66SAndrew Jones #define for_each_present_cpu(cpu)	for_each_cpu(cpu, &cpu_present_mask)
145905b0e66SAndrew Jones #define for_each_online_cpu(cpu)	for_each_cpu(cpu, &cpu_online_mask)
146905b0e66SAndrew Jones 
147905b0e66SAndrew Jones static inline void set_cpu_present(int cpu, bool present)
148905b0e66SAndrew Jones {
149905b0e66SAndrew Jones 	if (present)
150905b0e66SAndrew Jones 		cpumask_set_cpu(cpu, &cpu_present_mask);
151905b0e66SAndrew Jones 	else
152905b0e66SAndrew Jones 		cpumask_clear_cpu(cpu, &cpu_present_mask);
153905b0e66SAndrew Jones }
154905b0e66SAndrew Jones 
155905b0e66SAndrew Jones static inline void set_cpu_online(int cpu, bool online)
156905b0e66SAndrew Jones {
157905b0e66SAndrew Jones 	if (online)
158905b0e66SAndrew Jones 		cpumask_set_cpu(cpu, &cpu_online_mask);
159905b0e66SAndrew Jones 	else
160905b0e66SAndrew Jones 		cpumask_clear_cpu(cpu, &cpu_online_mask);
161905b0e66SAndrew Jones }
162905b0e66SAndrew Jones 
163905b0e66SAndrew Jones static inline void set_cpu_idle(int cpu, bool idle)
164905b0e66SAndrew Jones {
165905b0e66SAndrew Jones 	if (idle)
166905b0e66SAndrew Jones 		cpumask_set_cpu(cpu, &cpu_idle_mask);
167905b0e66SAndrew Jones 	else
168905b0e66SAndrew Jones 		cpumask_clear_cpu(cpu, &cpu_idle_mask);
169905b0e66SAndrew Jones }
170905b0e66SAndrew Jones 
171dfc1fec2SAndrew Jones #endif /* _CPUMASK_H_ */
172