1/* @title: CPU Mask */
2#pragma once
3#include <math/div.h>
4#include <stdbool.h>
5#include <stddef.h>
6#include <stdint.h>
7#include <string.h>
8#include <structures/bitmap.h>
9
10#ifndef CPU_MASK_BITS
11#define CPU_MASK_BITS 128
12#endif
13
14#define CPU_MASK_WORD_BITS 64
15#define CPU_MASK_WORDS BITMAP_WORDS(CPU_MASK_BITS)
16
17struct cpu_mask {
18 bitmap_word_t bits[CPU_MASK_WORDS];
19};
20
21#define CPU_MASK_INIT \
22 (struct cpu_mask) { \
23 .bits = {0} \
24 }
25
26/* Used to overload cpu_mask to carry an error at times */
27#define CPU_MASK_ERR(e) \
28 (struct cpu_mask) { \
29 .bits = {(bitmap_word_t) (e)} \
30 }
31
32static inline bool cpu_mask_init(struct cpu_mask *m, size_t nbits) {
33 (void) nbits;
34 memset(m->bits, 0, sizeof(m->bits));
35 return true;
36}
37
38static inline void cpu_mask_deinit(struct cpu_mask *m) {
39 (void) m;
40}
41
42struct cpu_mask *cpu_mask_create(void);
43void cpu_mask_free(struct cpu_mask *m);
44
45static inline void cpu_mask_copy(struct cpu_mask *dst,
46 const struct cpu_mask *src) {
47 *dst = *src;
48}
49
50static inline void cpu_mask_set(struct cpu_mask *m, size_t cpu) {
51 if (cpu < CPU_MASK_BITS) {
52 bitmap_set(map: m->bits, bit: cpu);
53 }
54}
55
56static inline void cpu_mask_clear(struct cpu_mask *m, size_t cpu) {
57 if (cpu < CPU_MASK_BITS) {
58 bitmap_clear(map: m->bits, bit: cpu);
59 }
60}
61
62static inline void cpu_mask_toggle(struct cpu_mask *m, size_t cpu) {
63 if (cpu < CPU_MASK_BITS) {
64 bitmap_toggle(map: m->bits, bit: cpu);
65 }
66}
67
68static inline bool cpu_mask_test(const struct cpu_mask *m, size_t cpu) {
69 return (cpu < CPU_MASK_BITS) ? bitmap_test(map: m->bits, bit: cpu) : false;
70}
71
72static inline bool cpu_mask_test_and_set(struct cpu_mask *m, size_t cpu) {
73 return (cpu < CPU_MASK_BITS) ? bitmap_test_and_set(map: m->bits, bit: cpu) : false;
74}
75
76static inline bool cpu_mask_test_and_clear(struct cpu_mask *m, size_t cpu) {
77 return (cpu < CPU_MASK_BITS) ? bitmap_test_and_clear(map: m->bits, bit: cpu) : false;
78}
79
80static inline void cpu_mask_set_atomic(struct cpu_mask *m, size_t cpu) {
81 if (cpu < CPU_MASK_BITS) {
82 bitmap_atomic_set(map: m->bits, bit: cpu);
83 }
84}
85
86static inline void cpu_mask_clear_atomic(struct cpu_mask *m, size_t cpu) {
87 if (cpu < CPU_MASK_BITS) {
88 bitmap_atomic_clear(map: m->bits, bit: cpu);
89 }
90}
91
92static inline void cpu_mask_toggle_atomic(struct cpu_mask *m, size_t cpu) {
93 if (cpu < CPU_MASK_BITS) {
94 bitmap_atomic_toggle(map: m->bits, bit: cpu);
95 }
96}
97
98static inline bool cpu_mask_test_atomic(const struct cpu_mask *m, size_t cpu) {
99 return (cpu < CPU_MASK_BITS) ? bitmap_atomic_test(map: m->bits, bit: cpu) : false;
100}
101
102static inline bool cpu_mask_test_and_set_atomic(struct cpu_mask *m,
103 size_t cpu) {
104 return (cpu < CPU_MASK_BITS) ? bitmap_atomic_test_and_set(map: m->bits, bit: cpu)
105 : false;
106}
107
108static inline bool cpu_mask_test_and_clear_atomic(struct cpu_mask *m,
109 size_t cpu) {
110 return (cpu < CPU_MASK_BITS) ? bitmap_atomic_test_and_clear(map: m->bits, bit: cpu)
111 : false;
112}
113
114static inline void cpu_mask_clear_all(struct cpu_mask *m) {
115 bitmap_zero(map: m->bits, CPU_MASK_BITS);
116}
117
118static inline void cpu_mask_zero(struct cpu_mask *m) {
119 bitmap_zero(map: m->bits, CPU_MASK_BITS);
120}
121
122static inline void cpu_mask_fill(struct cpu_mask *m) {
123 bitmap_fill(map: m->bits, CPU_MASK_BITS);
124}
125
126#define cpu_mask_active_bits() \
127 (global.core_count ? global.core_count : CPU_MASK_BITS)
128
129#define cpu_mask_set_all(m) bitmap_fill((m)->bits, cpu_mask_active_bits())
130
131static inline void cpu_mask_set_range(struct cpu_mask *m, size_t start,
132 size_t len) {
133 bitmap_set_range(map: m->bits, start, len);
134}
135
136static inline void cpu_mask_clear_range(struct cpu_mask *m, size_t start,
137 size_t len) {
138 bitmap_clear_range(map: m->bits, start, len);
139}
140
141static inline void cpu_mask_or(struct cpu_mask *dst, const struct cpu_mask *b) {
142 bitmap_or(dst: dst->bits, src1: dst->bits, src2: b->bits, CPU_MASK_BITS);
143}
144
145static inline void cpu_mask_or2(struct cpu_mask *dst, const struct cpu_mask *a,
146 const struct cpu_mask *b) {
147 bitmap_or(dst: dst->bits, src1: a->bits, src2: b->bits, CPU_MASK_BITS);
148}
149
150static inline void cpu_mask_and(struct cpu_mask *dst, const struct cpu_mask *a,
151 const struct cpu_mask *b) {
152 bitmap_and(dst: dst->bits, src1: a->bits, src2: b->bits, CPU_MASK_BITS);
153}
154
155static inline void cpu_mask_xor(struct cpu_mask *dst, const struct cpu_mask *a,
156 const struct cpu_mask *b) {
157 bitmap_xor(dst: dst->bits, src1: a->bits, src2: b->bits, CPU_MASK_BITS);
158}
159
160static inline void cpu_mask_andnot(struct cpu_mask *dst,
161 const struct cpu_mask *a,
162 const struct cpu_mask *b) {
163 bitmap_andnot(dst: dst->bits, src1: a->bits, src2: b->bits, CPU_MASK_BITS);
164}
165
166static inline bool cpu_mask_intersects(const struct cpu_mask *a,
167 const struct cpu_mask *b) {
168 return bitmap_intersects(src1: a->bits, src2: b->bits, CPU_MASK_BITS);
169}
170
171static inline bool cpu_mask_equal(const struct cpu_mask *a,
172 const struct cpu_mask *b) {
173 return bitmap_equal(src1: a->bits, src2: b->bits, CPU_MASK_BITS);
174}
175
176static inline bool cpu_mask_subset(const struct cpu_mask *subset,
177 const struct cpu_mask *superset) {
178 return bitmap_subset(subset: subset->bits, superset: superset->bits, CPU_MASK_BITS);
179}
180
181static inline size_t cpu_mask_popcount(const struct cpu_mask *m) {
182 return bitmap_weight(map: m->bits, CPU_MASK_BITS);
183}
184
185static inline size_t cpu_mask_weight(const struct cpu_mask *m) {
186 return bitmap_weight(map: m->bits, CPU_MASK_BITS);
187}
188
189static inline bool cpu_mask_empty(const struct cpu_mask *m) {
190 return bitmap_empty(map: m->bits, CPU_MASK_BITS);
191}
192
193static inline bool cpu_mask_full(const struct cpu_mask *m) {
194 return bitmap_full(map: m->bits, CPU_MASK_BITS);
195}
196
197static inline size_t cpu_mask_first_set(const struct cpu_mask *m) {
198 return bitmap_find_first_set(map: m->bits, CPU_MASK_BITS);
199}
200
201static inline size_t cpu_mask_first_clear(const struct cpu_mask *m) {
202 return bitmap_find_first_zero(map: m->bits, CPU_MASK_BITS);
203}
204
205static inline size_t cpu_mask_next_set(const struct cpu_mask *m, size_t start) {
206 return bitmap_find_next_bit(map: m->bits, CPU_MASK_BITS, start);
207}
208
209static inline size_t cpu_mask_next_clear(const struct cpu_mask *m,
210 size_t start) {
211 return bitmap_find_next_zero_bit(map: m->bits, CPU_MASK_BITS, start);
212}
213
214#define for_each_cpu(cpu, mask_ptr) \
215 for ((cpu) = \
216 bitmap_find_first_set((mask_ptr)->bits, cpu_mask_active_bits()); \
217 (cpu) < cpu_mask_active_bits(); \
218 (cpu) = bitmap_find_next_bit((mask_ptr)->bits, \
219 cpu_mask_active_bits(), (cpu) + 1))
220
221#define cpu_mask_for_each(iter, mask) \
222 for (iter = 0; iter < cpu_mask_active_bits(); iter++) \
223 if (bitmap_test((mask).bits, iter))
224
225#define cpu_mask_for_each_clear(iter, mask) \
226 for (iter = 0; iter < cpu_mask_active_bits(); iter++) \
227 if (!bitmap_test((mask).bits, iter))
228
229#define cpu_mask_for_all(iter, mask) \
230 for (iter = 0; iter < cpu_mask_active_bits(); iter++)
231
232#define cpu_mask_for_each_in(iter, mask, start, end) \
233 for (iter = (start); iter < cpu_mask_active_bits() && iter <= (end); \
234 iter++) \
235 if (bitmap_test((mask).bits, iter))
236
237#define cpu_mask_for_each_clear_in(iter, mask, start, end) \
238 for (iter = (start); iter < cpu_mask_active_bits() && iter <= (end); \
239 iter++) \
240 if (!bitmap_test((mask).bits, iter))
241