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

systemd / systemd / 15232239991

24 May 2025 08:01PM UTC coverage: 72.053% (-0.02%) from 72.07%
15232239991

push

github

web-flow
docs: add man pages for sd_device_enumerator_[new,ref,unref,unrefp] (#37586)

For #20929.

299160 of 415197 relevant lines covered (72.05%)

703671.29 hits per line

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

94.86
/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 "cpu-set-util.h"
9
#include "extract-word.h"
10
#include "hexdecoct.h"
11
#include "log.h"
12
#include "parse-util.h"
13
#include "string-util.h"
14

15
char* cpu_set_to_string(const CPUSet *a) {
14✔
16
        _cleanup_free_ char *str = NULL;
14✔
17
        size_t len = 0;
14✔
18
        int i, r;
14✔
19

20
        for (i = 0; (size_t) i < a->allocated * 8; i++) {
9,230✔
21
                if (!CPU_ISSET_S(i, a->allocated, a->set))
9,216✔
22
                        continue;
8,844✔
23

24
                if (!GREEDY_REALLOC(str, len + 1 + DECIMAL_STR_MAX(int)))
372✔
25
                        return NULL;
26

27
                r = sprintf(str + len, len > 0 ? " %d" : "%d", i);
372✔
28
                assert_se(r > 0);
372✔
29
                len += r;
372✔
30
        }
31

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

35
char* cpu_set_to_range_string(const CPUSet *set) {
9,924✔
36
        unsigned range_start = 0, range_end;
9,924✔
37
        _cleanup_free_ char *str = NULL;
9,924✔
38
        bool in_range = false;
9,924✔
39
        size_t len = 0;
9,924✔
40
        int r;
9,924✔
41

42
        for (unsigned i = 0; i < set->allocated * 8; i++)
19,268✔
43
                if (CPU_ISSET_S(i, set->allocated, set->set)) {
9,344✔
44
                        if (in_range)
258✔
45
                                range_end++;
233✔
46
                        else {
47
                                range_start = range_end = i;
48
                                in_range = true;
49
                        }
50
                } else if (in_range) {
9,086✔
51
                        in_range = false;
23✔
52

53
                        if (!GREEDY_REALLOC(str, len + 2 + 2 * DECIMAL_STR_MAX(unsigned)))
23✔
54
                                return NULL;
55

56
                        if (range_end > range_start)
23✔
57
                                r = sprintf(str + len, len > 0 ? " %u-%u" : "%u-%u", range_start, range_end);
17✔
58
                        else
59
                                r = sprintf(str + len, len > 0 ? " %u" : "%u", range_start);
24✔
60
                        assert_se(r > 0);
23✔
61
                        len += r;
23✔
62
                }
63

64
        if (in_range) {
9,924✔
65
                if (!GREEDY_REALLOC(str, len + 2 + 2 * DECIMAL_STR_MAX(int)))
2✔
66
                        return NULL;
67

68
                if (range_end > range_start)
2✔
69
                        r = sprintf(str + len, len > 0 ? " %u-%u" : "%u-%u", range_start, range_end);
2✔
70
                else
71
                        r = sprintf(str + len, len > 0 ? " %u" : "%u", range_start);
1✔
72
                assert_se(r > 0);
2✔
73
        }
74

75
        return TAKE_PTR(str) ?: strdup("");
9,924✔
76
}
77

78
char* cpu_set_to_mask_string(const CPUSet *a) {
20✔
79
        _cleanup_free_ char *str = NULL;
20✔
80
        size_t len = 0;
20✔
81
        bool found_nonzero = false;
20✔
82

83
        assert(a);
20✔
84

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

100
        for (ssize_t i = a->allocated * 8; i >= 0; i -= 4) {
2,376✔
101
                uint8_t m = 0;
102

103
                for (size_t j = 0; j < 4; j++)
11,780✔
104
                        if (CPU_ISSET_S(i + j, a->allocated, a->set))
9,424✔
105
                                m |= 1U << j;
272✔
106

107
                if (!found_nonzero)
2,356✔
108
                        found_nonzero = m > 0;
255✔
109

110
                if (!found_nonzero && m == 0)
2,356✔
111
                        /* Skip leading zeros */
112
                        continue;
238✔
113

114
                if (!GREEDY_REALLOC(str, len + 3))
2,118✔
115
                        return NULL;
116

117
                str[len++] = hexchar(m);
2,118✔
118
                if (i >= 4 && i % 32 == 0)
2,118✔
119
                        /* Separate by comma for each 32 CPUs. */
120
                        str[len++] = ',';
259✔
121
                str[len] = 0;
2,118✔
122
        }
123

124
        return TAKE_PTR(str) ?: strdup("0");
20✔
125
}
126

127
CPUSet* cpu_set_free(CPUSet *c) {
1,189✔
128
        if (!c)
1,189✔
129
                return c;
130

131
        cpu_set_reset(c);
9✔
132
        return mfree(c);
9✔
133
}
134

135
int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) {
653✔
136
        size_t need;
653✔
137

138
        assert(cpu_set);
653✔
139

140
        need = CPU_ALLOC_SIZE(ncpus);
653✔
141
        if (need > cpu_set->allocated) {
653✔
142
                cpu_set_t *t;
72✔
143

144
                t = realloc(cpu_set->set, need);
72✔
145
                if (!t)
72✔
146
                        return -ENOMEM;
147

148
                memzero((uint8_t*) t + cpu_set->allocated, need - cpu_set->allocated);
72✔
149

150
                cpu_set->set = t;
72✔
151
                cpu_set->allocated = need;
72✔
152
        }
153

154
        return 0;
155
}
156

157
int cpu_set_add(CPUSet *cpu_set, unsigned cpu) {
652✔
158
        int r;
652✔
159

160
        if (cpu >= 8192)
652✔
161
                /* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */
162
                return -ERANGE;
163

164
        r = cpu_set_realloc(cpu_set, cpu + 1);
652✔
165
        if (r < 0)
652✔
166
                return r;
167

168
        CPU_SET_S(cpu, cpu_set->allocated, cpu_set->set);
652✔
169
        return 0;
170
}
171

172
int cpu_set_add_all(CPUSet *a, const CPUSet *b) {
5✔
173
        int r;
5✔
174

175
        /* Do this backwards, so if we fail, we fail before changing anything. */
176
        for (unsigned cpu_p1 = b->allocated * 8; cpu_p1 > 0; cpu_p1--)
325✔
177
                if (CPU_ISSET_S(cpu_p1 - 1, b->allocated, b->set)) {
320✔
178
                        r = cpu_set_add(a, cpu_p1 - 1);
9✔
179
                        if (r < 0)
9✔
180
                                return r;
181
                }
182

183
        return 1;
184
}
185

186
int parse_cpu_set_full(
46,304✔
187
                const char *rvalue,
188
                CPUSet *cpu_set,
189
                bool warn,
190
                const char *unit,
191
                const char *filename,
192
                unsigned line,
193
                const char *lvalue) {
194

195
        _cleanup_(cpu_set_reset) CPUSet c = {};
46,304✔
196
        const char *p = ASSERT_PTR(rvalue);
46,304✔
197

198
        assert(cpu_set);
46,304✔
199

200
        for (;;) {
46,530✔
201
                _cleanup_free_ char *word = NULL;
118✔
202
                unsigned cpu_lower, cpu_upper;
46,417✔
203
                int r;
46,417✔
204

205
                r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_UNQUOTE);
46,417✔
206
                if (r == -ENOMEM)
46,417✔
207
                        return warn ? log_oom() : -ENOMEM;
×
208
                if (r < 0)
46,417✔
209
                        return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, rvalue) : r;
1✔
210
                if (r == 0)
46,416✔
211
                        break;
212

213
                r = parse_range(word, &cpu_lower, &cpu_upper);
117✔
214
                if (r < 0)
117✔
215
                        return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word) : r;
4✔
216

217
                if (cpu_lower > cpu_upper) {
113✔
218
                        if (warn)
1✔
219
                                log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring.",
1✔
220
                                           word, cpu_lower, cpu_upper);
221

222
                        /* Make sure something is allocated, to distinguish this from the empty case */
223
                        r = cpu_set_realloc(&c, 1);
1✔
224
                        if (r < 0)
1✔
225
                                return r;
226
                }
227

228
                for (unsigned cpu_p1 = MIN(cpu_upper, UINT_MAX-1) + 1; cpu_p1 > cpu_lower; cpu_p1--) {
637✔
229
                        r = cpu_set_add(&c, cpu_p1 - 1);
524✔
230
                        if (r < 0)
524✔
231
                                return warn ? log_syntax(unit, LOG_ERR, filename, line, r,
×
232
                                                         "Cannot add CPU %u to set: %m", cpu_p1 - 1) : r;
×
233
                }
234
        }
235

236
        *cpu_set = TAKE_STRUCT(c);
46,299✔
237

238
        return 0;
46,299✔
239
}
240

241
int parse_cpu_set_extend(
18✔
242
                const char *rvalue,
243
                CPUSet *old,
244
                bool warn,
245
                const char *unit,
246
                const char *filename,
247
                unsigned line,
248
                const char *lvalue) {
249

250
        _cleanup_(cpu_set_reset) CPUSet cpuset = {};
18✔
251
        int r;
18✔
252

253
        assert(old);
18✔
254

255
        r = parse_cpu_set_full(rvalue, &cpuset, true, unit, filename, line, lvalue);
18✔
256
        if (r < 0)
18✔
257
                return r;
258

259
        if (!cpuset.set) {
16✔
260
                /* An empty assignment resets the CPU list */
261
                cpu_set_reset(old);
1✔
262
                return 0;
263
        }
264

265
        if (!old->set) {
15✔
266
                *old = TAKE_STRUCT(cpuset);
14✔
267
                return 1;
14✔
268
        }
269

270
        return cpu_set_add_all(old, &cpuset);
1✔
271
}
272

273
int cpus_in_affinity_mask(void) {
76✔
274
        size_t n = 16;
76✔
275
        int r;
76✔
276

277
        for (;;) {
76✔
278
                cpu_set_t *c;
76✔
279

280
                c = CPU_ALLOC(n);
76✔
281
                if (!c)
76✔
282
                        return -ENOMEM;
283

284
                if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) {
76✔
285
                        int k;
76✔
286

287
                        k = CPU_COUNT_S(CPU_ALLOC_SIZE(n), c);
76✔
288
                        CPU_FREE(c);
76✔
289

290
                        if (k <= 0)
76✔
291
                                return -EINVAL;
292

293
                        return k;
76✔
294
                }
295

296
                r = -errno;
×
297
                CPU_FREE(c);
×
298

299
                if (r != -EINVAL)
×
300
                        return r;
301
                if (n > SIZE_MAX/2)
×
302
                        return -ENOMEM;
303
                n *= 2;
×
304
        }
305
}
306

307
int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated) {
10,617✔
308
        uint8_t *out;
10,617✔
309

310
        assert(set);
10,617✔
311
        assert(ret);
10,617✔
312

313
        out = new0(uint8_t, set->allocated);
10,617✔
314
        if (!out)
10,617✔
315
                return -ENOMEM;
316

317
        for (unsigned cpu = 0; cpu < set->allocated * 8; cpu++)
11,257✔
318
                if (CPU_ISSET_S(cpu, set->allocated, set->set))
640✔
319
                        out[cpu / 8] |= 1u << (cpu % 8);
110✔
320

321
        *ret = out;
10,617✔
322
        *allocated = set->allocated;
10,617✔
323
        return 0;
10,617✔
324
}
325

326
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) {
27✔
327
        _cleanup_(cpu_set_reset) CPUSet s = {};
27✔
328
        int r;
27✔
329

330
        assert(bits);
27✔
331
        assert(set);
27✔
332

333
        for (unsigned cpu = size * 8; cpu > 0; cpu--)
923✔
334
                if (bits[(cpu - 1) / 8] & (1u << ((cpu - 1) % 8))) {
896✔
335
                        r = cpu_set_add(&s, cpu - 1);
115✔
336
                        if (r < 0)
115✔
337
                                return r;
338
                }
339

340
        *set = TAKE_STRUCT(s);
27✔
341
        return 0;
27✔
342
}
343

344
int cpu_mask_add_all(CPUSet *mask) {
2✔
345
        long m;
2✔
346
        int r;
2✔
347

348
        assert(mask);
2✔
349

350
        m = sysconf(_SC_NPROCESSORS_ONLN);
2✔
351
        if (m < 0)
2✔
352
                return -errno;
×
353

354
        for (unsigned i = 0; i < (unsigned) m; i++) {
6✔
355
                r = cpu_set_add(mask, i);
4✔
356
                if (r < 0)
4✔
357
                        return r;
358
        }
359

360
        return 0;
361
}
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