File: | build-scan/../src/basic/cpu-set-util.c |
Warning: | line 415, column 11 Potential leak of memory pointed to by 'nodes' |
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 < 0) | |||
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_A20 = ((cpu_upper)); const typeof(((2147483647 *2U +1U)-1)) __unique_prefix_B21 = (((2147483647 *2U +1U)-1)); __unique_prefix_A20 < __unique_prefix_B21 ? __unique_prefix_A20 : __unique_prefix_B21; }) + 1; cpu_p1 > cpu_lower; cpu_p1--) { | |||
230 | r = cpu_set_add(&c, cpu_p1 - 1); | |||
231 | if (r < 0) | |||
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_X22 = ((policy->nodes.allocated)); const typeof((sizeof(unsigned long))) __unique_prefix_Y23 = ((sizeof (unsigned long))); (__unique_prefix_X22 / __unique_prefix_Y23 + !!(__unique_prefix_X22 % __unique_prefix_Y23)); })), 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
| |||
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); }; |