Bug Summary

File:build-scan/../src/basic/cpu-set-util.c
Warning:line 208, column 32
Potential leak of memory pointed to by 'c.set'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name cpu-set-util.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/basic/libbasic.a.p -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/blkid -I /usr/include/libmount -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/basic/cpu-set-util.c

../src/basic/cpu-set-util.c

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
28char* 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
48char *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 */
92char *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
136int 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)
;
42
Taking false branch
43
Loop condition is false. Exiting loop
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) {
44
Assuming 'need' is > field 'allocated'
45
Taking true branch
143 cpu_set_t *t;
144
145 t = realloc(cpu_set->set, need);
46
Memory is allocated
146 if (!t)
47
Assuming 't' is non-null
48
Taking false branch
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_); })
;
49
'?' condition is false
150
151 cpu_set->set = t;
152 cpu_set->allocated = need;
153 }
154
155 return 0;
156}
157
158static int cpu_set_add(CPUSet *cpu_set, unsigned cpu) {
159 int r;
160
161 if (cpu >= 8192)
39
Assuming 'cpu' is < 8192
40
Taking false branch
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);
41
Calling 'cpu_set_realloc'
50
Returned allocated memory
166 if (r
50.1
'r' is >= 0
50.1
'r' is >= 0
< 0)
51
Taking false branch
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; }))
;
52
Assuming the condition is false
53
'?' condition is false
170 return 0;
171}
172
173int 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
187int 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)
;
20
Assuming 'p' is non-null
21
Taking false branch
22
Loop condition is false. Exiting loop
200
201 for (;;) {
23
Loop condition is true. Entering loop body
58
Loop condition is true. Entering loop body
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)
24
Assuming the condition is false
25
Taking false branch
59
Assuming the condition is true
60
Taking true branch
208 return warn ? log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/basic/cpu-set-util.c"
, 208, __func__)
: -ENOMEM12;
61
Potential leak of memory pointed to by 'c.set'
209 if (r < 0)
26
Assuming 'r' is >= 0
27
Taking false branch
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)
28
Assuming 'r' is not equal to 0
29
Taking false branch
212 break;
213
214 r = parse_range(word, &cpu_lower, &cpu_upper);
215 if (r < 0)
30
Assuming 'r' is >= 0
31
Taking false branch
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) {
32
Assuming 'cpu_lower' is <= 'cpu_upper'
33
Taking false branch
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--) {
34
Assuming '__unique_prefix_A8' is < '__unique_prefix_B9'
35
'?' condition is true
36
Assuming 'cpu_p1' is > 'cpu_lower'
37
Loop condition is true. Entering loop body
56
Assuming 'cpu_p1' is <= 'cpu_lower'
57
Loop condition is false. Execution continues on line 201
230 r = cpu_set_add(&c, cpu_p1 - 1);
38
Calling 'cpu_set_add'
54
Returned allocated memory
231 if (r
54.1
'r' is >= 0
54.1
'r' is >= 0
< 0)
55
Taking false branch
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
244int 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
275int 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
309int 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
328int 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
347bool_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
365static 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
398int 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
422int 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)
;
1
Assuming 'policy' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
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)
;
4
Assuming 'ret' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
429
430 for (i = 0; i < policy->nodes.allocated * 8; i++) {
7
Assuming the condition is true
8
Loop condition is true. Entering loop body
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; }))
)
9
Assuming the condition is true
10
'?' condition is true
11
Assuming the condition is true
12
Taking false branch
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)
;
13
Assuming the condition is true
14
Taking false branch
15
Loop condition is false. Exiting loop
439
440 r = read_one_line_file(p, &l);
441 if (r < 0)
16
Assuming 'r' is >= 0
17
Taking false branch
442 return r;
443
444 r = parse_cpu_set(l, &part);
18
Calling 'parse_cpu_set'
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
459static 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
467DEFINE_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); }
;

../src/basic/cpu-set-util.h

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. */
14typedef struct CPUSet {
15 cpu_set_t *set;
16 size_t allocated; /* in bytes */
17} CPUSet;
18
19static 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
26int cpu_set_add_all(CPUSet *a, const CPUSet *b);
27
28char* cpu_set_to_string(const CPUSet *a);
29char *cpu_set_to_range_string(const CPUSet *a);
30char *cpu_set_to_range_string_kernel(const CPUSet *a);
31int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus);
32
33int 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);
40int 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
49static 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));
19
Calling 'parse_cpu_set_full'
51}
52
53int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated);
54int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set);
55
56int cpus_in_affinity_mask(void);
57
58static inline bool_Bool mpol_is_valid(int t) {
59 return t >= MPOL_DEFAULT && t <= MPOL_LOCAL;
60}
61
62typedef struct NUMAPolicy {
63 /* Always use numa_policy_get_type() to read the value */
64 int type;
65 CPUSet nodes;
66} NUMAPolicy;
67
68bool_Bool numa_policy_is_valid(const NUMAPolicy *p);
69
70static inline int numa_policy_get_type(const NUMAPolicy *p) {
71 return p->type < 0 ? (p->nodes.set ? MPOL_PREFERRED : -1) : p->type;
72}
73
74static 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
80int apply_numa_policy(const NUMAPolicy *policy);
81int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret);
82
83const char* mpol_to_string(int i) _const___attribute__ ((const));
84int mpol_from_string(const char *s) _pure___attribute__ ((pure));