]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/cpu-set-util.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / basic / cpu-set-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright 2015 Filipe Brandenburger
4 ***/
5
6 #include <errno.h>
7 #include <stddef.h>
8 #include <syslog.h>
9
10 #include "alloc-util.h"
11 #include "cpu-set-util.h"
12 #include "extract-word.h"
13 #include "log.h"
14 #include "macro.h"
15 #include "parse-util.h"
16 #include "string-util.h"
17
18 cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
19 cpu_set_t *c;
20 unsigned n = 1024;
21
22 /* Allocates the cpuset in the right size */
23
24 for (;;) {
25 c = CPU_ALLOC(n);
26 if (!c)
27 return NULL;
28
29 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) {
30 CPU_ZERO_S(CPU_ALLOC_SIZE(n), c);
31
32 if (ncpus)
33 *ncpus = n;
34
35 return c;
36 }
37
38 CPU_FREE(c);
39
40 if (errno != EINVAL)
41 return NULL;
42
43 n *= 2;
44 }
45 }
46
47 int parse_cpu_set_internal(
48 const char *rvalue,
49 cpu_set_t **cpu_set,
50 bool warn,
51 const char *unit,
52 const char *filename,
53 unsigned line,
54 const char *lvalue) {
55
56 _cleanup_cpu_free_ cpu_set_t *c = NULL;
57 const char *p = rvalue;
58 unsigned ncpus = 0;
59
60 assert(rvalue);
61
62 for (;;) {
63 _cleanup_free_ char *word = NULL;
64 unsigned cpu, cpu_lower, cpu_upper;
65 int r;
66
67 r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_QUOTES);
68 if (r == -ENOMEM)
69 return warn ? log_oom() : -ENOMEM;
70 if (r < 0)
71 return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, rvalue) : r;
72 if (r == 0)
73 break;
74
75 if (!c) {
76 c = cpu_set_malloc(&ncpus);
77 if (!c)
78 return warn ? log_oom() : -ENOMEM;
79 }
80
81 r = parse_range(word, &cpu_lower, &cpu_upper);
82 if (r < 0)
83 return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word) : r;
84 if (cpu_lower >= ncpus || cpu_upper >= ncpus)
85 return warn ? log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus) : -EINVAL;
86
87 if (cpu_lower > cpu_upper) {
88 if (warn)
89 log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring", word, cpu_lower, cpu_upper);
90 continue;
91 }
92
93 for (cpu = cpu_lower; cpu <= cpu_upper; cpu++)
94 CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
95 }
96
97 /* On success, sets *cpu_set and returns ncpus for the system. */
98 if (c)
99 *cpu_set = TAKE_PTR(c);
100
101 return (int) ncpus;
102 }