xref: /kvm-unit-tests/lib/cpumask.h (revision 386ed5c2f9e98a2605817748c44c0cefa60dc88e)
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 <asm/setup.h>
10 #include <bitops.h>
11 
12 #define CPUMASK_NR_LONGS ((NR_CPUS + BITS_PER_LONG - 1) / BITS_PER_LONG)
13 
14 typedef struct cpumask {
15 	unsigned long bits[CPUMASK_NR_LONGS];
16 } cpumask_t;
17 
18 #define cpumask_bits(maskp) ((maskp)->bits)
19 
20 static inline void cpumask_set_cpu(int cpu, cpumask_t *mask)
21 {
22 	assert(cpu >= 0 && cpu < nr_cpus);
23 	set_bit(cpu, cpumask_bits(mask));
24 }
25 
26 static inline void cpumask_clear_cpu(int cpu, cpumask_t *mask)
27 {
28 	assert(cpu >= 0 && cpu < nr_cpus);
29 	clear_bit(cpu, cpumask_bits(mask));
30 }
31 
32 static inline int cpumask_test_cpu(int cpu, const cpumask_t *mask)
33 {
34 	assert(cpu >= 0 && cpu < nr_cpus);
35 	return test_bit(cpu, cpumask_bits(mask));
36 }
37 
38 static inline int cpumask_test_and_set_cpu(int cpu, cpumask_t *mask)
39 {
40 	assert(cpu >= 0 && cpu < nr_cpus);
41 	return test_and_set_bit(cpu, cpumask_bits(mask));
42 }
43 
44 static inline int cpumask_test_and_clear_cpu(int cpu, cpumask_t *mask)
45 {
46 	assert(cpu >= 0 && cpu < nr_cpus);
47 	return test_and_clear_bit(cpu, cpumask_bits(mask));
48 }
49 
50 static inline void cpumask_setall(cpumask_t *mask)
51 {
52 	int i;
53 	for (i = 0; i < nr_cpus; i += BITS_PER_LONG)
54 		cpumask_bits(mask)[BIT_WORD(i)] = ~0UL;
55 	i -= BITS_PER_LONG;
56 	if ((nr_cpus - i) < BITS_PER_LONG)
57 		cpumask_bits(mask)[BIT_WORD(i)] = BIT_MASK(nr_cpus - i) - 1;
58 }
59 
60 static inline void cpumask_clear(cpumask_t *mask)
61 {
62 	int i;
63 	for (i = 0; i < nr_cpus; i += BITS_PER_LONG)
64 		cpumask_bits(mask)[BIT_WORD(i)] = 0UL;
65 }
66 
67 static inline bool cpumask_empty(const cpumask_t *mask)
68 {
69 	int i;
70 	for (i = 0; i < nr_cpus; i += BITS_PER_LONG) {
71 		if (i < NR_CPUS) { /* silence crazy compiler warning */
72 			if (cpumask_bits(mask)[BIT_WORD(i)] != 0UL)
73 				return false;
74 		}
75 	}
76 	return true;
77 }
78 
79 static inline bool cpumask_full(const cpumask_t *mask)
80 {
81 	int i;
82 	for (i = 0; i < nr_cpus; i += BITS_PER_LONG) {
83 		if (cpumask_bits(mask)[BIT_WORD(i)] != ~0UL) {
84 			if ((nr_cpus - i) >= BITS_PER_LONG)
85 				return false;
86 			if (cpumask_bits(mask)[BIT_WORD(i)]
87 					!= BIT_MASK(nr_cpus - i) - 1)
88 				return false;
89 		}
90 	}
91 	return true;
92 }
93 
94 static inline int cpumask_weight(const cpumask_t *mask)
95 {
96 	int w = 0, i;
97 
98 	for (i = 0; i < nr_cpus; ++i)
99 		if (cpumask_test_cpu(i, mask))
100 			++w;
101 	return w;
102 }
103 
104 static inline void cpumask_copy(cpumask_t *dst, const cpumask_t *src)
105 {
106 	memcpy(cpumask_bits(dst), cpumask_bits(src),
107 			CPUMASK_NR_LONGS * sizeof(long));
108 }
109 
110 static inline int cpumask_next(int cpu, const cpumask_t *mask)
111 {
112 	while (++cpu < nr_cpus && !cpumask_test_cpu(cpu, mask))
113 		;
114 	return cpu;
115 }
116 
117 #define for_each_cpu(cpu, mask)					\
118 	for ((cpu) = cpumask_next(-1, mask);			\
119 			(cpu) < nr_cpus; 			\
120 			(cpu) = cpumask_next(cpu, mask))
121 
122 extern cpumask_t cpu_present_mask;
123 extern cpumask_t cpu_online_mask;
124 extern cpumask_t cpu_idle_mask;
125 #define cpu_present(cpu)		cpumask_test_cpu(cpu, &cpu_present_mask)
126 #define cpu_online(cpu)			cpumask_test_cpu(cpu, &cpu_online_mask)
127 #define cpu_idle(cpu)			cpumask_test_cpu(cpu, &cpu_idle_mask)
128 #define for_each_present_cpu(cpu)	for_each_cpu(cpu, &cpu_present_mask)
129 #define for_each_online_cpu(cpu)	for_each_cpu(cpu, &cpu_online_mask)
130 
131 static inline void set_cpu_present(int cpu, bool present)
132 {
133 	if (present)
134 		cpumask_set_cpu(cpu, &cpu_present_mask);
135 	else
136 		cpumask_clear_cpu(cpu, &cpu_present_mask);
137 }
138 
139 static inline void set_cpu_online(int cpu, bool online)
140 {
141 	if (online)
142 		cpumask_set_cpu(cpu, &cpu_online_mask);
143 	else
144 		cpumask_clear_cpu(cpu, &cpu_online_mask);
145 }
146 
147 static inline void set_cpu_idle(int cpu, bool idle)
148 {
149 	if (idle)
150 		cpumask_set_cpu(cpu, &cpu_idle_mask);
151 	else
152 		cpumask_clear_cpu(cpu, &cpu_idle_mask);
153 }
154 
155 #endif /* _CPUMASK_H_ */
156