File: | build-scan/../src/basic/cpu-set-util.c |
Warning: | line 208, column 32 Potential leak of memory pointed to by 'c.set' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | ||||
2 | /*** | ||||
3 | Copyright © 2015 Filipe Brandenburger | ||||
4 | ***/ | ||||
5 | |||||
6 | #include <errno(*__errno_location ()).h> | ||||
7 | #include <stddef.h> | ||||
8 | #include <stdio.h> | ||||
9 | #include <syslog.h> | ||||
10 | |||||
11 | #include "alloc-util.h" | ||||
12 | #include "cpu-set-util.h" | ||||
13 | #include "dirent-util.h" | ||||
14 | #include "extract-word.h" | ||||
15 | #include "fileio.h" | ||||
16 | #include "fd-util.h" | ||||
17 | #include "log.h" | ||||
18 | #include "macro.h" | ||||
19 | #include "missing.h" | ||||
20 | #include "parse-util.h" | ||||
21 | #include "stat-util.h" | ||||
22 | #include "stdio-util.h" | ||||
23 | #include "string-util.h" | ||||
24 | #include "string-table.h" | ||||
25 | #include "strv.h" | ||||
26 | #include "util.h" | ||||
27 | |||||
28 | char* cpu_set_to_string(const CPUSet *a) { | ||||
29 | _cleanup_free___attribute__((cleanup(freep))) char *str = NULL((void*)0); | ||||
30 | size_t allocated = 0, len = 0; | ||||
31 | int i, r; | ||||
32 | |||||
33 | for (i = 0; (size_t) i < a->allocated * 8; i++) { | ||||
34 | if (!CPU_ISSET_S(i, a->allocated, a->set)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (a->allocated ) ? ((((const __cpu_mask *) ((a->set)->__bits))[((__cpu ) / (8 * sizeof (__cpu_mask)))] & ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask)))))) != 0 : 0; }))) | ||||
35 | continue; | ||||
36 | |||||
37 | if (!GREEDY_REALLOC(str, allocated, len + 1 + DECIMAL_STR_MAX(int))greedy_realloc((void**) &(str), &(allocated), (len + 1 + (2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))), sizeof((str)[0]))) | ||||
38 | return NULL((void*)0); | ||||
39 | |||||
40 | r = sprintf(str + len, len > 0 ? " %d" : "%d", i); | ||||
41 | assert_se(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("r > 0"), "../src/basic/cpu-set-util.c" , 41, __PRETTY_FUNCTION__); } while (0); | ||||
42 | len += r; | ||||
43 | } | ||||
44 | |||||
45 | return TAKE_PTR(str)({ typeof(str) _ptr_ = (str); (str) = ((void*)0); _ptr_; }) ?: strdup(""); | ||||
46 | } | ||||
47 | |||||
48 | char *cpu_set_to_range_string(const CPUSet *set) { | ||||
49 | unsigned range_start = 0, range_end; | ||||
50 | _cleanup_free___attribute__((cleanup(freep))) char *str = NULL((void*)0); | ||||
51 | size_t allocated = 0, len = 0; | ||||
52 | bool_Bool in_range = false0; | ||||
53 | int r; | ||||
54 | |||||
55 | for (unsigned i = 0; i < set->allocated * 8; i++) | ||||
56 | if (CPU_ISSET_S(i, set->allocated, set->set)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (set-> allocated) ? ((((const __cpu_mask *) ((set->set)->__bits ))[((__cpu) / (8 * sizeof (__cpu_mask)))] & ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask)))))) != 0 : 0 ; }))) { | ||||
57 | if (in_range) | ||||
58 | range_end++; | ||||
59 | else { | ||||
60 | range_start = range_end = i; | ||||
61 | in_range = true1; | ||||
62 | } | ||||
63 | } else if (in_range) { | ||||
64 | in_range = false0; | ||||
65 | |||||
66 | if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))greedy_realloc((void**) &(str), &(allocated), (len + 2 + 2 * (2+(sizeof(unsigned) <= 1 ? 3 : sizeof(unsigned) <= 2 ? 5 : sizeof(unsigned) <= 4 ? 10 : sizeof(unsigned) <= 8 ? 20 : sizeof(int[-2*(sizeof(unsigned) > 8)])))), sizeof ((str)[0]))) | ||||
67 | return NULL((void*)0); | ||||
68 | |||||
69 | if (range_end > range_start) | ||||
70 | r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); | ||||
71 | else | ||||
72 | r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); | ||||
73 | assert_se(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("r > 0"), "../src/basic/cpu-set-util.c" , 73, __PRETTY_FUNCTION__); } while (0); | ||||
74 | len += r; | ||||
75 | } | ||||
76 | |||||
77 | if (in_range) { | ||||
78 | if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))greedy_realloc((void**) &(str), &(allocated), (len + 2 + 2 * (2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof(int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof (int[-2*(sizeof(int) > 8)])))), sizeof((str)[0]))) | ||||
79 | return NULL((void*)0); | ||||
80 | |||||
81 | if (range_end > range_start) | ||||
82 | r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); | ||||
83 | else | ||||
84 | r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); | ||||
85 | assert_se(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("r > 0"), "../src/basic/cpu-set-util.c" , 85, __PRETTY_FUNCTION__); } while (0); | ||||
86 | } | ||||
87 | |||||
88 | return TAKE_PTR(str)({ typeof(str) _ptr_ = (str); (str) = ((void*)0); _ptr_; }) ?: strdup(""); | ||||
89 | } | ||||
90 | |||||
91 | /* XXX(msekleta): this is the workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1819152, remove in 8.3 */ | ||||
92 | char *cpu_set_to_range_string_kernel(const CPUSet *set) { | ||||
93 | unsigned range_start = 0, range_end; | ||||
94 | _cleanup_free___attribute__((cleanup(freep))) char *str = NULL((void*)0); | ||||
95 | size_t allocated = 0, len = 0; | ||||
96 | bool_Bool in_range = false0; | ||||
97 | int r; | ||||
98 | |||||
99 | for (unsigned i = 0; i < set->allocated * 8; i++) | ||||
100 | if (CPU_ISSET_S(i, set->allocated, set->set)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (set-> allocated) ? ((((const __cpu_mask *) ((set->set)->__bits ))[((__cpu) / (8 * sizeof (__cpu_mask)))] & ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask)))))) != 0 : 0 ; }))) { | ||||
101 | if (in_range) | ||||
102 | range_end++; | ||||
103 | else { | ||||
104 | range_start = range_end = i; | ||||
105 | in_range = true1; | ||||
106 | } | ||||
107 | } else if (in_range) { | ||||
108 | in_range = false0; | ||||
109 | |||||
110 | if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))greedy_realloc((void**) &(str), &(allocated), (len + 2 + 2 * (2+(sizeof(unsigned) <= 1 ? 3 : sizeof(unsigned) <= 2 ? 5 : sizeof(unsigned) <= 4 ? 10 : sizeof(unsigned) <= 8 ? 20 : sizeof(int[-2*(sizeof(unsigned) > 8)])))), sizeof ((str)[0]))) | ||||
111 | return NULL((void*)0); | ||||
112 | |||||
113 | if (range_end > range_start) | ||||
114 | r = sprintf(str + len, len > 0 ? ",%d-%d" : "%d-%d", range_start, range_end); | ||||
115 | else | ||||
116 | r = sprintf(str + len, len > 0 ? ",%d" : "%d", range_start); | ||||
117 | assert_se(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("r > 0"), "../src/basic/cpu-set-util.c" , 117, __PRETTY_FUNCTION__); } while (0); | ||||
118 | len += r; | ||||
119 | } | ||||
120 | |||||
121 | if (in_range) { | ||||
122 | if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))greedy_realloc((void**) &(str), &(allocated), (len + 2 + 2 * (2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof(int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof (int[-2*(sizeof(int) > 8)])))), sizeof((str)[0]))) | ||||
123 | return NULL((void*)0); | ||||
124 | |||||
125 | if (range_end > range_start) | ||||
126 | r = sprintf(str + len, len > 0 ? ",%d-%d" : "%d-%d", range_start, range_end); | ||||
127 | else | ||||
128 | r = sprintf(str + len, len > 0 ? ",%d" : "%d", range_start); | ||||
129 | assert_se(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("r > 0"), "../src/basic/cpu-set-util.c" , 129, __PRETTY_FUNCTION__); } while (0); | ||||
130 | } | ||||
131 | |||||
132 | return TAKE_PTR(str)({ typeof(str) _ptr_ = (str); (str) = ((void*)0); _ptr_; }) ?: strdup(""); | ||||
133 | } | ||||
134 | |||||
135 | |||||
136 | int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { | ||||
137 | size_t need; | ||||
138 | |||||
139 | assert(cpu_set)do { if ((__builtin_expect(!!(!(cpu_set)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("cpu_set"), "../src/basic/cpu-set-util.c" , 139, __PRETTY_FUNCTION__); } while (0); | ||||
140 | |||||
141 | need = CPU_ALLOC_SIZE(ncpus)((((ncpus) + (8 * sizeof (__cpu_mask)) - 1) / (8 * sizeof (__cpu_mask ))) * sizeof (__cpu_mask)); | ||||
142 | if (need > cpu_set->allocated) { | ||||
143 | cpu_set_t *t; | ||||
144 | |||||
145 | t = realloc(cpu_set->set, need); | ||||
146 | if (!t) | ||||
147 | return -ENOMEM12; | ||||
148 | |||||
149 | memzero((uint8_t*) t + cpu_set->allocated, need - cpu_set->allocated)({ size_t _l_ = (need - cpu_set->allocated); void *_x_ = ( (uint8_t*) t + cpu_set->allocated); _l_ == 0 ? _x_ : memset (_x_, 0, _l_); }); | ||||
150 | |||||
151 | cpu_set->set = t; | ||||
152 | cpu_set->allocated = need; | ||||
153 | } | ||||
154 | |||||
155 | return 0; | ||||
156 | } | ||||
157 | |||||
158 | static int cpu_set_add(CPUSet *cpu_set, unsigned cpu) { | ||||
159 | int r; | ||||
160 | |||||
161 | if (cpu >= 8192) | ||||
162 | /* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */ | ||||
163 | return -ERANGE34; | ||||
164 | |||||
165 | r = cpu_set_realloc(cpu_set, cpu + 1); | ||||
166 | if (r
| ||||
167 | return r; | ||||
168 | |||||
169 | CPU_SET_S(cpu, cpu_set->allocated, cpu_set->set)(__extension__ ({ size_t __cpu = (cpu); __cpu / 8 < (cpu_set ->allocated) ? (((__cpu_mask *) ((cpu_set->set)->__bits ))[((__cpu) / (8 * sizeof (__cpu_mask)))] |= ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask))))) : 0; })); | ||||
170 | return 0; | ||||
171 | } | ||||
172 | |||||
173 | int cpu_set_add_all(CPUSet *a, const CPUSet *b) { | ||||
174 | int r; | ||||
175 | |||||
176 | /* Do this backwards, so if we fail, we fail before changing anything. */ | ||||
177 | for (unsigned cpu_p1 = b->allocated * 8; cpu_p1 > 0; cpu_p1--) | ||||
178 | if (CPU_ISSET_S(cpu_p1 - 1, b->allocated, b->set)(__extension__ ({ size_t __cpu = (cpu_p1 - 1); __cpu / 8 < (b->allocated) ? ((((const __cpu_mask *) ((b->set)-> __bits))[((__cpu) / (8 * sizeof (__cpu_mask)))] & ((__cpu_mask ) 1 << ((__cpu) % (8 * sizeof (__cpu_mask)))))) != 0 : 0 ; }))) { | ||||
179 | r = cpu_set_add(a, cpu_p1 - 1); | ||||
180 | if (r < 0) | ||||
181 | return r; | ||||
182 | } | ||||
183 | |||||
184 | return 1; | ||||
185 | } | ||||
186 | |||||
187 | int parse_cpu_set_full( | ||||
188 | const char *rvalue, | ||||
189 | CPUSet *cpu_set, | ||||
190 | bool_Bool warn, | ||||
191 | const char *unit, | ||||
192 | const char *filename, | ||||
193 | unsigned line, | ||||
194 | const char *lvalue) { | ||||
195 | |||||
196 | _cleanup_(cpu_set_reset)__attribute__((cleanup(cpu_set_reset))) CPUSet c = {}; | ||||
197 | const char *p = rvalue; | ||||
198 | |||||
199 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/basic/cpu-set-util.c", 199 , __PRETTY_FUNCTION__); } while (0); | ||||
200 | |||||
201 | for (;;) { | ||||
202 | _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0); | ||||
203 | unsigned cpu_lower, cpu_upper; | ||||
204 | int r; | ||||
205 | |||||
206 | r = extract_first_word(&p, &word, WHITESPACE" \t\n\r" ",", EXTRACT_QUOTES); | ||||
207 | if (r == -ENOMEM12) | ||||
208 | return warn ? log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/basic/cpu-set-util.c" , 208, __func__) : -ENOMEM12; | ||||
| |||||
209 | if (r < 0) | ||||
210 | return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, rvalue)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/basic/cpu-set-util.c", 210, __func__ , "Invalid value for %s: %s", lvalue, rvalue) : -abs(_e); }) : r; | ||||
211 | if (r == 0) | ||||
212 | break; | ||||
213 | |||||
214 | r = parse_range(word, &cpu_lower, &cpu_upper); | ||||
215 | if (r < 0) | ||||
216 | return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/basic/cpu-set-util.c", 216, __func__ , "Failed to parse CPU affinity '%s'", word) : -abs(_e); }) : r; | ||||
217 | |||||
218 | if (cpu_lower > cpu_upper) { | ||||
219 | if (warn) | ||||
220 | log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring.",({ int _level = (4), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/basic/cpu-set-util.c", 221, __func__ , "Range '%s' is invalid, %u > %u, ignoring.", word, cpu_lower , cpu_upper) : -abs(_e); }) | ||||
221 | word, cpu_lower, cpu_upper)({ int _level = (4), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/basic/cpu-set-util.c", 221, __func__ , "Range '%s' is invalid, %u > %u, ignoring.", word, cpu_lower , cpu_upper) : -abs(_e); }); | ||||
222 | |||||
223 | /* Make sure something is allocated, to distinguish this from the empty case */ | ||||
224 | r = cpu_set_realloc(&c, 1); | ||||
225 | if (r < 0) | ||||
226 | return r; | ||||
227 | } | ||||
228 | |||||
229 | for (unsigned cpu_p1 = MIN(cpu_upper, UINT_MAX-1)__extension__ ({ const typeof((cpu_upper)) __unique_prefix_A16 = ((cpu_upper)); const typeof(((2147483647 *2U +1U)-1)) __unique_prefix_B17 = (((2147483647 *2U +1U)-1)); __unique_prefix_A16 < __unique_prefix_B17 ? __unique_prefix_A16 : __unique_prefix_B17; }) + 1; cpu_p1 > cpu_lower; cpu_p1--) { | ||||
230 | r = cpu_set_add(&c, cpu_p1 - 1); | ||||
231 | if (r
| ||||
232 | return warn ? log_syntax(unit, LOG_ERR, filename, line, r,({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/basic/cpu-set-util.c", 233, __func__ , "Cannot add CPU %u to set: %m", cpu_p1 - 1) : -abs(_e); }) | ||||
233 | "Cannot add CPU %u to set: %m", cpu_p1 - 1)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/basic/cpu-set-util.c", 233, __func__ , "Cannot add CPU %u to set: %m", cpu_p1 - 1) : -abs(_e); }) : r; | ||||
234 | } | ||||
235 | } | ||||
236 | |||||
237 | /* On success, transfer ownership to the output variable */ | ||||
238 | *cpu_set = c; | ||||
239 | c = (CPUSet) {}; | ||||
240 | |||||
241 | return 0; | ||||
242 | } | ||||
243 | |||||
244 | int parse_cpu_set_extend( | ||||
245 | const char *rvalue, | ||||
246 | CPUSet *old, | ||||
247 | bool_Bool warn, | ||||
248 | const char *unit, | ||||
249 | const char *filename, | ||||
250 | unsigned line, | ||||
251 | const char *lvalue) { | ||||
252 | |||||
253 | _cleanup_(cpu_set_reset)__attribute__((cleanup(cpu_set_reset))) CPUSet cpuset = {}; | ||||
254 | int r; | ||||
255 | |||||
256 | r = parse_cpu_set_full(rvalue, &cpuset, true1, unit, filename, line, lvalue); | ||||
257 | if (r < 0) | ||||
258 | return r; | ||||
259 | |||||
260 | if (!cpuset.set) { | ||||
261 | /* An empty assignment resets the CPU list */ | ||||
262 | cpu_set_reset(old); | ||||
263 | return 0; | ||||
264 | } | ||||
265 | |||||
266 | if (!old->set) { | ||||
267 | *old = cpuset; | ||||
268 | cpuset = (CPUSet) {}; | ||||
269 | return 1; | ||||
270 | } | ||||
271 | |||||
272 | return cpu_set_add_all(old, &cpuset); | ||||
273 | } | ||||
274 | |||||
275 | int cpus_in_affinity_mask(void) { | ||||
276 | size_t n = 16; | ||||
277 | int r; | ||||
278 | |||||
279 | for (;;) { | ||||
280 | cpu_set_t *c; | ||||
281 | |||||
282 | c = CPU_ALLOC(n)__sched_cpualloc (n); | ||||
283 | if (!c) | ||||
284 | return -ENOMEM12; | ||||
285 | |||||
286 | if (sched_getaffinity(0, CPU_ALLOC_SIZE(n)((((n) + (8 * sizeof (__cpu_mask)) - 1) / (8 * sizeof (__cpu_mask ))) * sizeof (__cpu_mask)), c) >= 0) { | ||||
287 | int k; | ||||
288 | |||||
289 | k = CPU_COUNT_S(CPU_ALLOC_SIZE(n), c)__sched_cpucount (((((n) + (8 * sizeof (__cpu_mask)) - 1) / ( 8 * sizeof (__cpu_mask))) * sizeof (__cpu_mask)), c); | ||||
290 | CPU_FREE(c)__sched_cpufree (c); | ||||
291 | |||||
292 | if (k <= 0) | ||||
293 | return -EINVAL22; | ||||
294 | |||||
295 | return k; | ||||
296 | } | ||||
297 | |||||
298 | r = -errno(*__errno_location ()); | ||||
299 | CPU_FREE(c)__sched_cpufree (c); | ||||
300 | |||||
301 | if (r != -EINVAL22) | ||||
302 | return r; | ||||
303 | if (n > SIZE_MAX(18446744073709551615UL)/2) | ||||
304 | return -ENOMEM12; | ||||
305 | n *= 2; | ||||
306 | } | ||||
307 | } | ||||
308 | |||||
309 | int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated) { | ||||
310 | uint8_t *out; | ||||
311 | |||||
312 | assert(set)do { if ((__builtin_expect(!!(!(set)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("set"), "../src/basic/cpu-set-util.c", 312 , __PRETTY_FUNCTION__); } while (0); | ||||
313 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/basic/cpu-set-util.c", 313 , __PRETTY_FUNCTION__); } while (0); | ||||
314 | |||||
315 | out = new0(uint8_t, set->allocated)((uint8_t*) calloc((set->allocated), sizeof(uint8_t))); | ||||
316 | if (!out) | ||||
317 | return -ENOMEM12; | ||||
318 | |||||
319 | for (unsigned cpu = 0; cpu < set->allocated * 8; cpu++) | ||||
320 | if (CPU_ISSET_S(cpu, set->allocated, set->set)(__extension__ ({ size_t __cpu = (cpu); __cpu / 8 < (set-> allocated) ? ((((const __cpu_mask *) ((set->set)->__bits ))[((__cpu) / (8 * sizeof (__cpu_mask)))] & ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask)))))) != 0 : 0 ; }))) | ||||
321 | out[cpu / 8] |= 1u << (cpu % 8); | ||||
322 | |||||
323 | *ret = out; | ||||
324 | *allocated = set->allocated; | ||||
325 | return 0; | ||||
326 | } | ||||
327 | |||||
328 | int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) { | ||||
329 | _cleanup_(cpu_set_reset)__attribute__((cleanup(cpu_set_reset))) CPUSet s = {}; | ||||
330 | int r; | ||||
331 | |||||
332 | assert(bits)do { if ((__builtin_expect(!!(!(bits)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("bits"), "../src/basic/cpu-set-util.c", 332 , __PRETTY_FUNCTION__); } while (0); | ||||
333 | assert(set)do { if ((__builtin_expect(!!(!(set)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("set"), "../src/basic/cpu-set-util.c", 333 , __PRETTY_FUNCTION__); } while (0); | ||||
334 | |||||
335 | for (unsigned cpu = size * 8; cpu > 0; cpu--) | ||||
336 | if (bits[(cpu - 1) / 8] & (1u << ((cpu - 1) % 8))) { | ||||
337 | r = cpu_set_add(&s, cpu - 1); | ||||
338 | if (r < 0) | ||||
339 | return r; | ||||
340 | } | ||||
341 | |||||
342 | *set = s; | ||||
343 | s = (CPUSet) {}; | ||||
344 | return 0; | ||||
345 | } | ||||
346 | |||||
347 | bool_Bool numa_policy_is_valid(const NUMAPolicy *policy) { | ||||
348 | assert(policy)do { if ((__builtin_expect(!!(!(policy)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("policy"), "../src/basic/cpu-set-util.c" , 348, __PRETTY_FUNCTION__); } while (0); | ||||
349 | |||||
350 | if (!mpol_is_valid(numa_policy_get_type(policy))) | ||||
351 | return false0; | ||||
352 | |||||
353 | if (!policy->nodes.set && | ||||
354 | !IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL, MPOL_PREFERRED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MPOL_DEFAULT, MPOL_LOCAL, MPOL_PREFERRED })/sizeof(int)]; switch(numa_policy_get_type(policy)) { case MPOL_DEFAULT : case MPOL_LOCAL: case MPOL_PREFERRED: _found = 1; break; default : break; } _found; })) | ||||
355 | return false0; | ||||
356 | |||||
357 | if (policy->nodes.set && | ||||
358 | numa_policy_get_type(policy) == MPOL_PREFERRED && | ||||
359 | CPU_COUNT_S(policy->nodes.allocated, policy->nodes.set)__sched_cpucount (policy->nodes.allocated, policy->nodes .set) != 1) | ||||
360 | return false0; | ||||
361 | |||||
362 | return true1; | ||||
363 | } | ||||
364 | |||||
365 | static int numa_policy_to_mempolicy(const NUMAPolicy *policy, unsigned long *ret_maxnode, unsigned long **ret_nodes) { | ||||
366 | unsigned node, bits = 0, ulong_bits; | ||||
367 | _cleanup_free___attribute__((cleanup(freep))) unsigned long *out = NULL((void*)0); | ||||
368 | |||||
369 | assert(policy)do { if ((__builtin_expect(!!(!(policy)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("policy"), "../src/basic/cpu-set-util.c" , 369, __PRETTY_FUNCTION__); } while (0); | ||||
370 | assert(ret_maxnode)do { if ((__builtin_expect(!!(!(ret_maxnode)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_maxnode"), "../src/basic/cpu-set-util.c" , 370, __PRETTY_FUNCTION__); } while (0); | ||||
371 | assert(ret_nodes)do { if ((__builtin_expect(!!(!(ret_nodes)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_nodes"), "../src/basic/cpu-set-util.c" , 371, __PRETTY_FUNCTION__); } while (0); | ||||
372 | |||||
373 | if (IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MPOL_DEFAULT, MPOL_LOCAL})/sizeof(int)]; switch(numa_policy_get_type(policy)) { case MPOL_DEFAULT: case MPOL_LOCAL: _found = 1; break; default: break; } _found; }) || | ||||
374 | (numa_policy_get_type(policy) == MPOL_PREFERRED && !policy->nodes.set)) { | ||||
375 | *ret_nodes = NULL((void*)0); | ||||
376 | *ret_maxnode = 0; | ||||
377 | return 0; | ||||
378 | } | ||||
379 | |||||
380 | bits = policy->nodes.allocated * 8; | ||||
381 | ulong_bits = sizeof(unsigned long) * 8; | ||||
382 | |||||
383 | out = new0(unsigned long, DIV_ROUND_UP(policy->nodes.allocated, sizeof(unsigned long)))((unsigned long*) calloc((({ const typeof((policy->nodes.allocated )) __unique_prefix_X18 = ((policy->nodes.allocated)); const typeof((sizeof(unsigned long))) __unique_prefix_Y19 = ((sizeof (unsigned long))); (__unique_prefix_X18 / __unique_prefix_Y19 + !!(__unique_prefix_X18 % __unique_prefix_Y19)); })), sizeof (unsigned long))); | ||||
384 | if (!out) | ||||
385 | return -ENOMEM12; | ||||
386 | |||||
387 | /* We don't make any assumptions about internal type libc is using to store NUMA node mask. | ||||
388 | Hence we need to convert the node mask to the representation expected by set_mempolicy() */ | ||||
389 | for (node = 0; node < bits; node++) | ||||
390 | if (CPU_ISSET_S(node, policy->nodes.allocated, policy->nodes.set)(__extension__ ({ size_t __cpu = (node); __cpu / 8 < (policy ->nodes.allocated) ? ((((const __cpu_mask *) ((policy-> nodes.set)->__bits))[((__cpu) / (8 * sizeof (__cpu_mask))) ] & ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask )))))) != 0 : 0; }))) | ||||
391 | out[node / ulong_bits] |= 1ul << (node % ulong_bits); | ||||
392 | |||||
393 | *ret_nodes = TAKE_PTR(out)({ typeof(out) _ptr_ = (out); (out) = ((void*)0); _ptr_; }); | ||||
394 | *ret_maxnode = bits + 1; | ||||
395 | return 0; | ||||
396 | } | ||||
397 | |||||
398 | int apply_numa_policy(const NUMAPolicy *policy) { | ||||
399 | int r; | ||||
400 | _cleanup_free___attribute__((cleanup(freep))) unsigned long *nodes = NULL((void*)0); | ||||
401 | unsigned long maxnode; | ||||
402 | |||||
403 | assert(policy)do { if ((__builtin_expect(!!(!(policy)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("policy"), "../src/basic/cpu-set-util.c" , 403, __PRETTY_FUNCTION__); } while (0); | ||||
404 | |||||
405 | if (get_mempolicymissing_get_mempolicy(NULL((void*)0), NULL((void*)0), 0, 0, 0) < 0 && errno(*__errno_location ()) == ENOSYS38) | ||||
406 | return -EOPNOTSUPP95; | ||||
407 | |||||
408 | if (!numa_policy_is_valid(policy)) | ||||
409 | return -EINVAL22; | ||||
410 | |||||
411 | r = numa_policy_to_mempolicy(policy, &maxnode, &nodes); | ||||
412 | if (r < 0) | ||||
413 | return r; | ||||
414 | |||||
415 | r = set_mempolicymissing_set_mempolicy(numa_policy_get_type(policy), nodes, maxnode); | ||||
416 | if (r < 0) | ||||
417 | return -errno(*__errno_location ()); | ||||
418 | |||||
419 | return 0; | ||||
420 | } | ||||
421 | |||||
422 | int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) { | ||||
423 | int r; | ||||
424 | size_t i; | ||||
425 | _cleanup_(cpu_set_reset)__attribute__((cleanup(cpu_set_reset))) CPUSet s = {}; | ||||
426 | |||||
427 | assert(policy)do { if ((__builtin_expect(!!(!(policy)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("policy"), "../src/basic/cpu-set-util.c" , 427, __PRETTY_FUNCTION__); } while (0); | ||||
| |||||
428 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/basic/cpu-set-util.c", 428 , __PRETTY_FUNCTION__); } while (0); | ||||
429 | |||||
430 | for (i = 0; i < policy->nodes.allocated * 8; i++) { | ||||
431 | _cleanup_free___attribute__((cleanup(freep))) char *l = NULL((void*)0); | ||||
432 | char p[STRLEN("/sys/devices/system/node/node//cpulist")(sizeof("""/sys/devices/system/node/node//cpulist""") - 1) + DECIMAL_STR_MAX(size_t)(2+(sizeof(size_t) <= 1 ? 3 : sizeof(size_t) <= 2 ? 5 : sizeof(size_t) <= 4 ? 10 : sizeof(size_t) <= 8 ? 20 : sizeof (int[-2*(sizeof(size_t) > 8)]))) + 1]; | ||||
433 | _cleanup_(cpu_set_reset)__attribute__((cleanup(cpu_set_reset))) CPUSet part = {}; | ||||
434 | |||||
435 | if (!CPU_ISSET_S(i, policy->nodes.allocated, policy->nodes.set)(__extension__ ({ size_t __cpu = (i); __cpu / 8 < (policy-> nodes.allocated) ? ((((const __cpu_mask *) ((policy->nodes .set)->__bits))[((__cpu) / (8 * sizeof (__cpu_mask)))] & ((__cpu_mask) 1 << ((__cpu) % (8 * sizeof (__cpu_mask) ))))) != 0 : 0; }))) | ||||
436 | continue; | ||||
437 | |||||
438 | xsprintf(p, "/sys/devices/system/node/node%zu/cpulist", i)do { if ((__builtin_expect(!!(!(((size_t) snprintf(p, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (p), typeof(&*(p))), sizeof(p)/sizeof((p)[0]), ((void)0)) ), "/sys/devices/system/node/node%zu/cpulist", i) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (p), typeof(&*(p))), sizeof(p)/sizeof((p)[0]), ((void)0)) ))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: " "p" "[] must be big enough"), "../src/basic/cpu-set-util.c", 438, __PRETTY_FUNCTION__); } while (0); | ||||
439 | |||||
440 | r = read_one_line_file(p, &l); | ||||
441 | if (r < 0) | ||||
442 | return r; | ||||
443 | |||||
444 | r = parse_cpu_set(l, &part); | ||||
445 | if (r < 0) | ||||
446 | return r; | ||||
447 | |||||
448 | r = cpu_set_add_all(&s, &part); | ||||
449 | if (r < 0) | ||||
450 | return r; | ||||
451 | } | ||||
452 | |||||
453 | *ret = s; | ||||
454 | s = (CPUSet) {}; | ||||
455 | |||||
456 | return 0; | ||||
457 | } | ||||
458 | |||||
459 | static const char* const mpol_table[] = { | ||||
460 | [MPOL_DEFAULT] = "default", | ||||
461 | [MPOL_PREFERRED] = "preferred", | ||||
462 | [MPOL_BIND] = "bind", | ||||
463 | [MPOL_INTERLEAVE] = "interleave", | ||||
464 | [MPOL_LOCAL] = "local", | ||||
465 | }; | ||||
466 | |||||
467 | DEFINE_STRING_TABLE_LOOKUP(mpol, int)const char *mpol_to_string(int i) { if (i < 0 || i >= ( int) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(mpol_table), typeof(&*(mpol_table))), sizeof(mpol_table )/sizeof((mpol_table)[0]), ((void)0)))) return ((void*)0); return mpol_table[i]; } int mpol_from_string(const char *s) { return (int) string_table_lookup(mpol_table, __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(mpol_table), typeof(& *(mpol_table))), sizeof(mpol_table)/sizeof((mpol_table)[0]), ( (void)0))), s); }; |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #pragma once |
3 | |
4 | /*** |
5 | Copyright © 2015 Filipe Brandenburger |
6 | ***/ |
7 | |
8 | #include <sched.h> |
9 | |
10 | #include "macro.h" |
11 | #include "missing.h" |
12 | |
13 | /* This wraps the libc interface with a variable to keep the allocated size. */ |
14 | typedef struct CPUSet { |
15 | cpu_set_t *set; |
16 | size_t allocated; /* in bytes */ |
17 | } CPUSet; |
18 | |
19 | static inline void cpu_set_reset(CPUSet *a) { |
20 | assert((a->allocated > 0) == !!a->set)do { if ((__builtin_expect(!!(!((a->allocated > 0) == ! !a->set)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "(a->allocated > 0) == !!a->set"), "../src/basic/cpu-set-util.h" , 20, __PRETTY_FUNCTION__); } while (0); |
21 | if (a->set) |
22 | CPU_FREE(a->set)__sched_cpufree (a->set); |
23 | *a = (CPUSet) {}; |
24 | } |
25 | |
26 | int cpu_set_add_all(CPUSet *a, const CPUSet *b); |
27 | |
28 | char* cpu_set_to_string(const CPUSet *a); |
29 | char *cpu_set_to_range_string(const CPUSet *a); |
30 | char *cpu_set_to_range_string_kernel(const CPUSet *a); |
31 | int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus); |
32 | |
33 | int parse_cpu_set_full( |
34 | const char *rvalue, |
35 | CPUSet *cpu_set, |
36 | bool_Bool warn, |
37 | const char *unit, |
38 | const char *filename, unsigned line, |
39 | const char *lvalue); |
40 | int parse_cpu_set_extend( |
41 | const char *rvalue, |
42 | CPUSet *old, |
43 | bool_Bool warn, |
44 | const char *unit, |
45 | const char *filename, |
46 | unsigned line, |
47 | const char *lvalue); |
48 | |
49 | static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){ |
50 | return parse_cpu_set_full(rvalue, cpu_set, false0, NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)); |
51 | } |
52 | |
53 | int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated); |
54 | int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set); |
55 | |
56 | int cpus_in_affinity_mask(void); |
57 | |
58 | static inline bool_Bool mpol_is_valid(int t) { |
59 | return t >= MPOL_DEFAULT && t <= MPOL_LOCAL; |
60 | } |
61 | |
62 | typedef struct NUMAPolicy { |
63 | /* Always use numa_policy_get_type() to read the value */ |
64 | int type; |
65 | CPUSet nodes; |
66 | } NUMAPolicy; |
67 | |
68 | bool_Bool numa_policy_is_valid(const NUMAPolicy *p); |
69 | |
70 | static inline int numa_policy_get_type(const NUMAPolicy *p) { |
71 | return p->type < 0 ? (p->nodes.set ? MPOL_PREFERRED : -1) : p->type; |
72 | } |
73 | |
74 | static inline void numa_policy_reset(NUMAPolicy *p) { |
75 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/basic/cpu-set-util.h", 75, __PRETTY_FUNCTION__); } while (0); |
76 | cpu_set_reset(&p->nodes); |
77 | p->type = -1; |
78 | } |
79 | |
80 | int apply_numa_policy(const NUMAPolicy *policy); |
81 | int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret); |
82 | |
83 | const char* mpol_to_string(int i) _const___attribute__ ((const)); |
84 | int mpol_from_string(const char *s) _pure___attribute__ ((pure)); |