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