• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 15986406979

30 Jun 2025 05:03PM UTC coverage: 72.045% (-0.09%) from 72.13%
15986406979

push

github

bluca
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options

ephemeral/ephemeral-import are described as possible '--mutable' options but
not present in the list. Note, "systemd-sysext --help" lists them correctly.

300514 of 417119 relevant lines covered (72.05%)

708586.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.7
/src/shared/cpu-set-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdio.h>
4
#include <syslog.h>
5
#include <unistd.h>
6

7
#include "alloc-util.h"
8
#include "bitfield.h"
9
#include "cpu-set-util.h"
10
#include "extract-word.h"
11
#include "hexdecoct.h"
12
#include "log.h"
13
#include "parse-util.h"
14
#include "string-util.h"
15

16
/* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */
17
#define CPU_SET_MAX_NCPU 8192
18

19
char* cpu_set_to_string(const CPUSet *c) {
17✔
20
        _cleanup_free_ char *str = NULL;
17✔
21

22
        assert(c);
17✔
23

24
        for (size_t i = 0; i < c->allocated * 8; i++) {
9,425✔
25
                if (!CPU_ISSET_S(i, c->allocated, c->set))
9,408✔
26
                        continue;
9,020✔
27

28
                if (strextendf_with_separator(&str, " ", "%zu", i) < 0)
388✔
29
                        return NULL;
30
        }
31

32
        return TAKE_PTR(str) ?: strdup("");
17✔
33
}
34

35
static int add_range(char **str, size_t start, size_t end) {
40✔
36
        assert(str);
40✔
37
        assert(start <= end);
40✔
38

39
        if (start == end)
40✔
40
                return strextendf_with_separator(str, " ", "%zu", start);
20✔
41

42
        return strextendf_with_separator(str, " ", "%zu-%zu", start, end);
20✔
43
}
44

45
char* cpu_set_to_range_string(const CPUSet *c) {
9,944✔
46
        _cleanup_free_ char *str = NULL;
9,944✔
47
        size_t start = 0, end;
9,944✔
48
        bool in_range = false;
9,944✔
49

50
        assert(c);
9,944✔
51

52
        for (size_t i = 0; i < c->allocated * 8; i++) {
19,992✔
53
                if (CPU_ISSET_S(i, c->allocated, c->set)) {
10,048✔
54
                        if (in_range)
399✔
55
                                end++;
359✔
56
                        else {
57
                                start = end = i;
58
                                in_range = true;
59
                        }
60
                        continue;
399✔
61
                }
62

63
                if (in_range && add_range(&str, start, end) < 0)
9,649✔
64
                        return NULL;
65

66
                in_range = false;
67
        }
68

69
        if (in_range && add_range(&str, start, end) < 0)
9,944✔
70
                return NULL;
71

72
        return TAKE_PTR(str) ?: strdup("");
9,944✔
73
}
74

75
char* cpu_set_to_mask_string(const CPUSet *c) {
25✔
76
        _cleanup_free_ char *str = NULL;
25✔
77
        bool found_nonzero = false;
25✔
78
        int r;
25✔
79

80
        assert(c);
25✔
81

82
        /* Return CPU set in hexadecimal bitmap mask, e.g.
83
         *   CPU   0 ->  "1"
84
         *   CPU   1 ->  "2"
85
         *   CPU 0,1 ->  "3"
86
         *   CPU 0-3 ->  "f"
87
         *   CPU 0-7 -> "ff"
88
         *   CPU 4-7 -> "f0"
89
         *   CPU   7 -> "80"
90
         *   None    ->  "0"
91
         *
92
         * When there are more than 32 CPUs, separate every 32 CPUs by comma, e.g.
93
         *  CPU 0-47 -> "ffff,ffffffff"
94
         *  CPU 0-63 -> "ffffffff,ffffffff"
95
         *  CPU 0-71 -> "ff,ffffffff,ffffffff" */
96

97
        for (size_t i = c->allocated * 8; i > 0; ) {
335✔
98
                uint32_t m = 0;
310✔
99

100
                for (int j = (i % 32 ?: 32) - 1; j >= 0; j--)
10,540✔
101
                        if (CPU_ISSET_S(--i, c->allocated, c->set))
9,920✔
102
                                SET_BIT(m, j);
399✔
103

104
                if (!found_nonzero) {
310✔
105
                        if (m == 0)
45✔
106
                                continue;
22✔
107

108
                        r = strextendf_with_separator(&str, ",", "%" PRIx32, m);
23✔
109
                } else
110
                        r = strextendf_with_separator(&str, ",", "%08" PRIx32, m);
265✔
111
                if (r < 0)
288✔
112
                        return NULL;
113

114
                found_nonzero = true;
115
        }
116

117
        return TAKE_PTR(str) ?: strdup("0");
25✔
118
}
119

120
void cpu_set_done(CPUSet *c) {
454,078✔
121
        assert(c);
454,078✔
122

123
        if (c->set)
454,078✔
124
                CPU_FREE(c->set);
51✔
125

126
        *c = (CPUSet) {};
454,078✔
127
}
454,078✔
128

129
int cpu_set_realloc(CPUSet *c, size_t n) {
146✔
130
        assert(c);
146✔
131

132
        if (n > CPU_SET_MAX_NCPU)
146✔
133
                return -ERANGE;
134

135
        n = CPU_ALLOC_SIZE(n);
146✔
136
        if (n <= c->allocated)
146✔
137
                return 0;
138

139
        if (!GREEDY_REALLOC0(c->set, DIV_ROUND_UP(n, sizeof(cpu_set_t))))
70✔
140
                return -ENOMEM;
141

142
        c->allocated = n;
70✔
143
        return 0;
70✔
144
}
145

146
int cpu_set_add(CPUSet *c, size_t i) {
×
147
        int r;
×
148

149
        assert(c);
×
150

151
        /* cpu_set_realloc() has similar check, but for avoiding overflow. */
152
        if (i >= CPU_SET_MAX_NCPU)
×
153
                return -ERANGE;
154

155
        r = cpu_set_realloc(c, i + 1);
×
156
        if (r < 0)
×
157
                return r;
158

159
        CPU_SET_S(i, c->allocated, c->set);
×
160
        return 0;
161
}
162

163
int cpu_set_add_set(CPUSet *c, const CPUSet *src) {
4✔
164
        int r;
4✔
165

166
        assert(c);
4✔
167
        assert(src);
4✔
168

169
        r = cpu_set_realloc(c, src->allocated * 8);
4✔
170
        if (r < 0)
4✔
171
                return r;
172

173
        for (size_t i = 0; i < src->allocated * 8; i++)
196✔
174
                if (CPU_ISSET_S(i, src->allocated, src->set))
192✔
175
                        CPU_SET_S(i, c->allocated, c->set);
5✔
176

177
        return 1;
178
}
179

180
static int cpu_set_add_range(CPUSet *c, size_t start, size_t end) {
114✔
181
        int r;
114✔
182

183
        assert(c);
114✔
184
        assert(start <= end);
114✔
185

186
        /* cpu_set_realloc() has similar check, but for avoiding overflow. */
187
        if (end >= CPU_SET_MAX_NCPU)
114✔
188
                return -ERANGE;
189

190
        r = cpu_set_realloc(c, end + 1);
114✔
191
        if (r < 0)
114✔
192
                return r;
193

194
        for (size_t i = start; i <= end; i++)
642✔
195
                CPU_SET_S(i, c->allocated, c->set);
528✔
196

197
        return 0;
198
}
199

200
int cpu_set_add_all(CPUSet *c) {
2✔
201
        assert(c);
2✔
202

203
        long m = sysconf(_SC_NPROCESSORS_ONLN);
2✔
204
        if (m < 0)
2✔
205
                return -errno;
×
206
        if (m == 0)
2✔
207
                return -ENXIO;
208

209
        return cpu_set_add_range(c, 0, m - 1);
2✔
210
}
211

212
int config_parse_cpu_set(
46,942✔
213
                const char *unit,
214
                const char *filename,
215
                unsigned line,
216
                const char *section,
217
                unsigned section_line,
218
                const char *lvalue,
219
                int ltype, /* 0 when used as conf parser, 1 when used as usual parser */
220
                const char *rvalue,
221
                void *data,
222
                void *userdata) {
223

224
        CPUSet *c = ASSERT_PTR(data);
46,942✔
225
        int r, level = ltype ? LOG_DEBUG : LOG_DEBUG;
46,942✔
226
        bool critical = ltype;
46,942✔
227

228
        assert(critical || lvalue);
46,942✔
229

230
        if (isempty(rvalue)) {
46,942✔
231
                cpu_set_done(c);
46,887✔
232
                return 1;
46,942✔
233
        }
234

235
        _cleanup_(cpu_set_done) CPUSet cpuset = {};
55✔
236
        for (const char *p = rvalue;;) {
55✔
237
                _cleanup_free_ char *word = NULL;
118✔
238

239
                r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_UNQUOTE);
169✔
240
                if (r == -ENOMEM)
169✔
241
                        return log_oom_full(level);
×
242
                if (r < 0) {
169✔
243
                        if (critical)
1✔
244
                                return log_debug_errno(r, "Failed to parse CPU set: %s", rvalue);
1✔
245

246
                        log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= setting, ignoring assignment: %s",
×
247
                                   lvalue, rvalue);
248
                        return 0;
×
249
                }
250
                if (r == 0)
168✔
251
                        break;
252

253
                unsigned lower, upper;
117✔
254
                r = parse_range(word, &lower, &upper);
117✔
255
                if (r < 0) {
117✔
256
                        if (critical)
4✔
257
                                return log_debug_errno(r, "Failed to parse CPU range: %s", word);
2✔
258

259
                        log_syntax(unit, LOG_WARNING, filename, line, r,
2✔
260
                                   "Failed to parse CPU range, ignoring assignment: %s", word);
261
                        continue;
2✔
262
                }
263

264
                if (lower > upper) {
113✔
265
                        if (critical)
1✔
266
                                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
1✔
267
                                                       "Invalid CPU range (%u > %u): %s",
268
                                                       lower, upper, word);
269

270
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
271
                                   "Invalid CPU range (%u > %u), ignoring assignment: %s",
272
                                   lower, upper, word);
273
                        continue;
×
274
                }
275

276
                r = cpu_set_add_range(&cpuset, lower, upper);
112✔
277
                if (r == -ENOMEM)
112✔
278
                        return log_oom_full(level);
×
279
                if (r < 0) {
112✔
280
                        if (critical)
×
281
                                return log_debug_errno(r, "Failed to set CPU(s) '%s': %m", word);
×
282

283
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
284
                                   "Failed to set CPU(s), ignoring assignment: %s", word);
285
                }
286
        }
287

288
        if (!c->set) {
51✔
289
                *c = TAKE_STRUCT(cpuset);
49✔
290
                return 1;
49✔
291
        }
292

293
        r = cpu_set_add_set(c, &cpuset);
2✔
294
        if (r == -ENOMEM)
2✔
295
                return log_oom_full(level);
×
296
        assert(r >= 0);
2✔
297

298
        return 1;
299
}
300

301
int parse_cpu_set(const char *s, CPUSet *ret) {
46,923✔
302
        _cleanup_(cpu_set_done) CPUSet c = {};
46,923✔
303
        int r;
46,923✔
304

305
        assert(s);
46,923✔
306
        assert(ret);
46,923✔
307

308
        r = config_parse_cpu_set(
46,923✔
309
                        /* unit = */ NULL,
310
                        /* filename = */ NULL,
311
                        /* line = */ 0,
312
                        /* section = */ NULL,
313
                        /* section_line = */ 0,
314
                        /* lvalue = */ NULL,
315
                        /* ltype = */ 1,
316
                        /* rvalue = */ s,
317
                        /* data = */ &c,
318
                        /* userdata = */ NULL);
319
        if (r < 0)
46,923✔
320
                return r;
321

322
        *ret = TAKE_STRUCT(c);
46,919✔
323
        return 0;
46,919✔
324
}
325

326
int cpus_in_affinity_mask(void) {
76✔
327
        size_t n = 16;
76✔
328
        int r;
76✔
329

330
        for (;;) {
76✔
331
                cpu_set_t *c;
76✔
332

333
                c = CPU_ALLOC(n);
76✔
334
                if (!c)
76✔
335
                        return -ENOMEM;
336

337
                if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) {
76✔
338
                        int k;
76✔
339

340
                        k = CPU_COUNT_S(CPU_ALLOC_SIZE(n), c);
76✔
341
                        CPU_FREE(c);
76✔
342

343
                        if (k <= 0)
76✔
344
                                return -EINVAL;
345

346
                        return k;
76✔
347
                }
348

349
                r = -errno;
×
350
                CPU_FREE(c);
×
351

352
                if (r != -EINVAL)
×
353
                        return r;
354
                if (n > SIZE_MAX/2)
×
355
                        return -ENOMEM;
356
                n *= 2;
×
357
        }
358
}
359

360
int cpu_set_to_dbus(const CPUSet *c, uint8_t **ret, size_t *ret_size) {
11,865✔
361
        assert(c);
11,865✔
362
        assert(ret);
11,865✔
363
        assert(ret_size);
11,865✔
364

365
        uint8_t *buf = new0(uint8_t, c->allocated);
11,865✔
366
        if (!buf)
11,865✔
367
                return -ENOMEM;
368

369
        for (size_t i = 0; i < c->allocated * 8; i++)
12,505✔
370
                if (CPU_ISSET_S(i, c->allocated, c->set))
640✔
371
                        SET_BIT(buf[i / 8], i % 8);
110✔
372

373
        *ret = buf;
11,865✔
374
        *ret_size = c->allocated;
11,865✔
375
        return 0;
11,865✔
376
}
377

378
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *ret) {
27✔
379
        _cleanup_(cpu_set_done) CPUSet c = {};
27✔
380
        int r;
27✔
381

382
        assert(bits || size == 0);
27✔
383
        assert(ret);
27✔
384

385
        r = cpu_set_realloc(&c, size * 8);
27✔
386
        if (r < 0)
27✔
387
                return r;
388

389
        for (size_t i = 0; i < size * 8; i++)
923✔
390
                if (BIT_SET(bits[i / 8], i % 8))
896✔
391
                        CPU_SET_S(i, c.allocated, c.set);
115✔
392

393
        *ret = TAKE_STRUCT(c);
27✔
394
        return 0;
27✔
395
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc