]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/cpu-set-util.c
tree-wide: use TAKE_PTR() and TAKE_FD() macros
[thirdparty/systemd.git] / src / basic / cpu-set-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
618234a5
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010-2015 Lennart Poettering
6 Copyright 2015 Filipe Brandenburger
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
11c3a366
TA
22#include <errno.h>
23#include <stddef.h>
24#include <syslog.h>
25
b5efdb8a 26#include "alloc-util.h"
6bedfcbb 27#include "cpu-set-util.h"
84ac7bea 28#include "extract-word.h"
11c3a366
TA
29#include "log.h"
30#include "macro.h"
93cc7779 31#include "parse-util.h"
b11d6a7b 32#include "string-util.h"
618234a5
LP
33
34cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
35 cpu_set_t *c;
36 unsigned n = 1024;
37
38 /* Allocates the cpuset in the right size */
39
40 for (;;) {
41 c = CPU_ALLOC(n);
42 if (!c)
43 return NULL;
44
45 if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) {
46 CPU_ZERO_S(CPU_ALLOC_SIZE(n), c);
47
48 if (ncpus)
49 *ncpus = n;
50
51 return c;
52 }
53
54 CPU_FREE(c);
55
56 if (errno != EINVAL)
57 return NULL;
58
59 n *= 2;
60 }
61}
62
6d8a29b2 63int parse_cpu_set_internal(
618234a5
LP
64 const char *rvalue,
65 cpu_set_t **cpu_set,
6d8a29b2 66 bool warn,
618234a5
LP
67 const char *unit,
68 const char *filename,
69 unsigned line,
70 const char *lvalue) {
71
618234a5 72 _cleanup_cpu_free_ cpu_set_t *c = NULL;
6d8a29b2 73 const char *p = rvalue;
618234a5
LP
74 unsigned ncpus = 0;
75
618234a5
LP
76 assert(rvalue);
77
78 for (;;) {
79 _cleanup_free_ char *word = NULL;
a26662ce 80 unsigned cpu, cpu_lower, cpu_upper;
618234a5
LP
81 int r;
82
6d8a29b2
YW
83 r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_QUOTES);
84 if (r == -ENOMEM)
85 return warn ? log_oom() : -ENOMEM;
a26662ce 86 if (r < 0)
6d8a29b2 87 return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, rvalue) : r;
618234a5
LP
88 if (r == 0)
89 break;
90
91 if (!c) {
92 c = cpu_set_malloc(&ncpus);
93 if (!c)
6d8a29b2 94 return warn ? log_oom() : -ENOMEM;
618234a5
LP
95 }
96
a26662ce
FB
97 r = parse_range(word, &cpu_lower, &cpu_upper);
98 if (r < 0)
6d8a29b2 99 return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word) : r;
a26662ce 100 if (cpu_lower >= ncpus || cpu_upper >= ncpus)
6d8a29b2 101 return warn ? log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus) : -EINVAL;
032cf8e4 102
6d8a29b2
YW
103 if (cpu_lower > cpu_upper) {
104 if (warn)
105 log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring", word, cpu_lower, cpu_upper);
106 continue;
032cf8e4
YW
107 }
108
6d8a29b2
YW
109 for (cpu = cpu_lower; cpu <= cpu_upper; cpu++)
110 CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
032cf8e4
YW
111 }
112
113 /* On success, sets *cpu_set and returns ncpus for the system. */
1cc6c93a
YW
114 if (c)
115 *cpu_set = TAKE_PTR(c);
032cf8e4
YW
116
117 return (int) ncpus;
118}