Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation. All rights reserved.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/cpuset.h"
7 : : #include "spdk/log.h"
8 : :
9 : : struct spdk_cpuset *
10 : 21 : spdk_cpuset_alloc(void)
11 : : {
12 : 21 : return (struct spdk_cpuset *)calloc(1, sizeof(struct spdk_cpuset));
13 : : }
14 : :
15 : : void
16 : 21 : spdk_cpuset_free(struct spdk_cpuset *set)
17 : : {
18 : 21 : free(set);
19 : 21 : }
20 : :
21 : : bool
22 : 964 : spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
23 : : {
24 [ + + # # ]: 964 : assert(set1 != NULL);
25 [ + + # # ]: 964 : assert(set2 != NULL);
26 [ + + + + : 964 : return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
+ - + - ]
27 : : }
28 : :
29 : : void
30 : 23730 : spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
31 : : {
32 [ + + # # ]: 23730 : assert(dst != NULL);
33 [ + + # # ]: 23730 : assert(src != NULL);
34 [ + + + + : 23730 : memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
+ - + - ]
35 : 23730 : }
36 : :
37 : : void
38 : 2609 : spdk_cpuset_negate(struct spdk_cpuset *set)
39 : : {
40 : : unsigned int i;
41 [ + + # # ]: 2609 : assert(set != NULL);
42 [ + + ]: 336561 : for (i = 0; i < sizeof(set->cpus); i++) {
43 [ + - + - : 333952 : set->cpus[i] = ~set->cpus[i];
+ - + - +
- + - ]
44 : 8960 : }
45 : 2609 : }
46 : :
47 : : void
48 : 6592 : spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
49 : : {
50 : : unsigned int i;
51 [ + + # # ]: 6592 : assert(dst != NULL);
52 [ + + # # ]: 6592 : assert(src != NULL);
53 [ + + ]: 850368 : for (i = 0; i < sizeof(src->cpus); i++) {
54 [ + - + - : 843776 : dst->cpus[i] &= src->cpus[i];
+ - + - +
- + - ]
55 : 21632 : }
56 : 6592 : }
57 : :
58 : : void
59 : 2046 : spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
60 : : {
61 : : unsigned int i;
62 [ + + # # ]: 2046 : assert(dst != NULL);
63 [ + + # # ]: 2046 : assert(src != NULL);
64 [ + + ]: 263934 : for (i = 0; i < sizeof(src->cpus); i++) {
65 [ + - + - : 261888 : dst->cpus[i] |= src->cpus[i];
+ - + - +
- + - ]
66 : 512 : }
67 : 2046 : }
68 : :
69 : : void
70 : 6270 : spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
71 : : {
72 : : unsigned int i;
73 [ + + # # ]: 6270 : assert(dst != NULL);
74 [ + + # # ]: 6270 : assert(src != NULL);
75 [ + + ]: 808830 : for (i = 0; i < sizeof(src->cpus); i++) {
76 [ + - + - : 802560 : dst->cpus[i] ^= src->cpus[i];
+ - + - +
- + - ]
77 : 21632 : }
78 : 6270 : }
79 : :
80 : : void
81 : 16966 : spdk_cpuset_zero(struct spdk_cpuset *set)
82 : : {
83 [ + + # # ]: 16966 : assert(set != NULL);
84 [ + + + - ]: 16966 : memset(set->cpus, 0, sizeof(set->cpus));
85 : 16966 : }
86 : :
87 : : void
88 : 50418 : spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
89 : : {
90 [ + + # # ]: 50418 : assert(set != NULL);
91 [ + + # # ]: 50418 : assert(cpu < sizeof(set->cpus) * 8);
92 [ + + + + ]: 50418 : if (state) {
93 [ + + + - : 50073 : set->cpus[cpu / 8] |= (1U << (cpu % 8));
+ - + - +
- + - ]
94 : 646 : } else {
95 [ + + + - : 345 : set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
+ - + - +
- + - ]
96 : : }
97 : 50418 : }
98 : :
99 : : bool
100 : 30417720 : spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
101 : : {
102 [ + + # # ]: 30417720 : assert(set != NULL);
103 [ + + # # ]: 30417720 : assert(cpu < sizeof(set->cpus) * 8);
104 [ + + + - : 30417720 : return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
+ - + - +
- + - ]
105 : : }
106 : :
107 : : void
108 : 7411 : spdk_cpuset_for_each_cpu(const struct spdk_cpuset *set,
109 : : void (*fn)(void *ctx, uint32_t cpu), void *ctx)
110 : : {
111 : : uint8_t n;
112 : : unsigned int i, j;
113 [ + + ]: 956019 : for (i = 0; i < sizeof(set->cpus); i++) {
114 [ - + - + : 948608 : n = set->cpus[i];
- + ]
115 [ + + ]: 8537472 : for (j = 0; j < 8; j++) {
116 [ + + + + : 7588864 : if (n & (1 << j)) {
+ + ]
117 [ - + + - ]: 12948 : fn(ctx, i * 8 + j);
118 : 182 : }
119 : 172032 : }
120 : 21504 : }
121 : 7411 : }
122 : :
123 : : static void
124 : 12877 : count_fn(void *ctx, uint32_t cpu)
125 : : {
126 : 12877 : uint32_t *count = ctx;
127 : :
128 : 12877 : (*count)++;
129 : 12877 : }
130 : :
131 : : uint32_t
132 : 7392 : spdk_cpuset_count(const struct spdk_cpuset *set)
133 : : {
134 : 7392 : uint32_t count = 0;
135 : :
136 : 7392 : spdk_cpuset_for_each_cpu(set, count_fn, &count);
137 : 7392 : return count;
138 : : }
139 : :
140 : : const char *
141 : 2417 : spdk_cpuset_fmt(struct spdk_cpuset *set)
142 : : {
143 : 2417 : uint32_t lcore, lcore_max = 0;
144 : : int val, i, n;
145 : : char *ptr;
146 : : static const char *hex = "0123456789abcdef";
147 : :
148 [ - + # # ]: 2417 : assert(set != NULL);
149 : :
150 [ + + ]: 2477425 : for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
151 [ + + ]: 2475008 : if (spdk_cpuset_get_cpu(set, lcore)) {
152 : 7386 : lcore_max = lcore;
153 : 0 : }
154 : 0 : }
155 : :
156 [ # # ]: 2417 : ptr = set->str;
157 [ # # ]: 2417 : n = lcore_max / 8;
158 [ # # # # : 2417 : val = set->cpus[n];
# # ]
159 : :
160 : : /* Store first number only if it is not leading zero */
161 [ + + ]: 2417 : if ((val & 0xf0) != 0) {
162 [ # # # # : 179 : *(ptr++) = hex[(val & 0xf0) >> 4];
# # # # #
# ]
163 : 0 : }
164 [ # # # # : 2417 : *(ptr++) = hex[val & 0x0f];
# # # # ]
165 : :
166 [ + + # # : 3499 : for (i = n - 1; i >= 0; i--) {
# # ]
167 [ # # # # : 1082 : val = set->cpus[i];
# # ]
168 [ # # # # : 1082 : *(ptr++) = hex[(val & 0xf0) >> 4];
# # # # #
# ]
169 [ # # # # : 1082 : *(ptr++) = hex[val & 0x0f];
# # # # ]
170 : 0 : }
171 [ # # ]: 2417 : *ptr = '\0';
172 : :
173 [ # # ]: 2417 : return set->str;
174 : : }
175 : :
176 : : static int
177 : 3226 : hex_value(uint8_t c)
178 : : {
179 : : #define V(x, y) [x] = y + 1
180 : : static const int8_t val[256] = {
181 : : V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
182 : : V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
183 : : V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
184 : : V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
185 : : };
186 : : #undef V
187 : :
188 [ + - + - : 3226 : return val[c] - 1;
+ - + - ]
189 : : }
190 : :
191 : : static int
192 : 51 : parse_list(const char *mask, struct spdk_cpuset *set)
193 : : {
194 : 39 : char *end;
195 : 51 : const char *ptr = mask;
196 : : uint32_t lcore;
197 : : uint32_t lcore_min, lcore_max;
198 : :
199 : 51 : spdk_cpuset_zero(set);
200 : 51 : lcore_min = UINT32_MAX;
201 : :
202 [ # # ]: 51 : ptr++;
203 : 51 : end = (char *)ptr;
204 : 0 : do {
205 [ - + # # : 96 : while (isblank(*ptr)) {
# # # # #
# ]
206 [ # # ]: 0 : ptr++;
207 : : }
208 [ + + + + : 96 : if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
+ + + + #
# # # # #
# # ]
209 : 15 : goto invalid_character;
210 : : }
211 : :
212 [ # # ]: 81 : errno = 0;
213 [ - + ]: 81 : lcore = strtoul(ptr, &end, 10);
214 [ + + # # ]: 81 : if (errno) {
215 : 3 : SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
216 : 3 : return -1;
217 : : }
218 : :
219 [ + + ]: 78 : if (lcore >= sizeof(set->cpus) * 8) {
220 : 3 : SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
221 : 3 : return -1;
222 : : }
223 : :
224 [ - + # # : 75 : while (isblank(*end)) {
# # # # #
# ]
225 [ # # ]: 0 : end++;
226 : : }
227 : :
228 [ + + # # ]: 75 : if (*end == '-') {
229 : 18 : lcore_min = lcore;
230 [ + + + - : 57 : } else if (*end == ',' || *end == ']') {
# # # # ]
231 : 57 : lcore_max = lcore;
232 [ + + ]: 57 : if (lcore_min == UINT32_MAX) {
233 : 42 : lcore_min = lcore;
234 : 0 : }
235 [ + + ]: 57 : if (lcore_min > lcore_max) {
236 : 3 : SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
237 : : lcore_min, lcore_max);
238 : 3 : return -1;
239 : : }
240 [ + + ]: 3588 : for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
241 : 3534 : spdk_cpuset_set_cpu(set, lcore, true);
242 : 0 : }
243 : 54 : lcore_min = UINT32_MAX;
244 : 0 : } else {
245 : 0 : goto invalid_character;
246 : : }
247 : :
248 [ # # ]: 72 : ptr = end + 1;
249 : :
250 [ + + # # ]: 72 : } while (*end != ']');
251 : :
252 : 27 : return 0;
253 : :
254 : 15 : invalid_character:
255 [ + + # # ]: 15 : if (*end == '\0') {
256 : 3 : SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
257 : 0 : } else {
258 [ # # ]: 12 : SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
259 : : }
260 : 15 : return -1;
261 : 0 : }
262 : :
263 : : static int
264 : 514 : parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
265 : : {
266 : : int i, j;
267 : : char c;
268 : : int val;
269 : 514 : uint32_t lcore = 0;
270 : :
271 [ + + + + : 514 : if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
+ + + - +
- + + + -
+ - - + ]
272 [ + - ]: 312 : mask += 2;
273 : 312 : len -= 2;
274 : 8 : }
275 : :
276 : 514 : spdk_cpuset_zero(set);
277 [ + + + - ]: 4049 : for (i = len - 1; i >= 0; i--) {
278 [ + - + - ]: 3535 : c = mask[i];
279 [ + + ]: 3535 : if (c == ',') {
280 : : /* Linux puts comma delimiters in its cpumasks, just skip them. */
281 : 309 : continue;
282 : : }
283 : 3226 : val = hex_value(c);
284 [ + + ]: 3226 : if (val < 0) {
285 : : /* Invalid character */
286 : 0 : SPDK_ERRLOG("Invalid character in core mask '%s' (%c)\n", mask, c);
287 : 0 : return -1;
288 : : }
289 [ + + + + : 16130 : for (j = 0; j < 4 && lcore < SPDK_CPUSET_SIZE; j++, lcore++) {
+ - ]
290 [ + + + + : 12904 : if ((1 << j) & val) {
+ + ]
291 : 1362 : spdk_cpuset_set_cpu(set, lcore, true);
292 : 16 : }
293 : 480 : }
294 : 120 : }
295 : :
296 : 514 : return 0;
297 : 12 : }
298 : :
299 : : int
300 : 574 : spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
301 : : {
302 : : int ret;
303 : : size_t len;
304 : :
305 [ + + + + ]: 574 : if (mask == NULL || set == NULL) {
306 : 6 : return -1;
307 : : }
308 : :
309 [ + + + - : 568 : while (isblank(*mask)) {
+ - + - -
+ ]
310 [ # # ]: 0 : mask++;
311 : : }
312 : :
313 [ + + ]: 568 : len = strlen(mask);
314 [ + + + + : 568 : while (len > 0 && isblank(mask[len - 1])) {
+ - + - +
- + - -
+ ]
315 : 0 : len--;
316 : : }
317 : :
318 [ + + ]: 568 : if (len == 0) {
319 : 3 : return -1;
320 : : }
321 : :
322 [ + + + - : 565 : if (mask[0] == '[') {
- + ]
323 : 51 : ret = parse_list(mask, set);
324 : 0 : } else {
325 : 514 : ret = parse_mask(mask, set, len);
326 : : }
327 : :
328 : 565 : return ret;
329 : 12 : }
|