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 : 27 : spdk_cpuset_alloc(void)
11 : : {
12 : 27 : return (struct spdk_cpuset *)calloc(1, sizeof(struct spdk_cpuset));
13 : : }
14 : :
15 : : void
16 : 27 : spdk_cpuset_free(struct spdk_cpuset *set)
17 : : {
18 : 27 : free(set);
19 : 27 : }
20 : :
21 : : bool
22 : 1171 : spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
23 : : {
24 [ + + # # ]: 1171 : assert(set1 != NULL);
25 [ + + # # ]: 1171 : assert(set2 != NULL);
26 [ + + + + : 1171 : return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
+ - + - ]
27 : : }
28 : :
29 : : void
30 : 29233 : spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
31 : : {
32 [ + + # # ]: 29233 : assert(dst != NULL);
33 [ + + # # ]: 29233 : assert(src != NULL);
34 [ + + + + : 29233 : memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
+ - + - ]
35 : 29233 : }
36 : :
37 : : void
38 : 3048 : spdk_cpuset_negate(struct spdk_cpuset *set)
39 : : {
40 : : unsigned int i;
41 [ + + # # ]: 3048 : assert(set != NULL);
42 [ + + ]: 393192 : for (i = 0; i < sizeof(set->cpus); i++) {
43 [ + - + - : 390144 : set->cpus[i] = ~set->cpus[i];
+ - + - +
- + - ]
44 : 38272 : }
45 : 3048 : }
46 : :
47 : : void
48 : 7394 : spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
49 : : {
50 : : unsigned int i;
51 [ + + # # ]: 7394 : assert(dst != NULL);
52 [ + + # # ]: 7394 : assert(src != NULL);
53 [ + + ]: 953826 : for (i = 0; i < sizeof(src->cpus); i++) {
54 [ + - + - : 946432 : dst->cpus[i] &= src->cpus[i];
+ - + - +
- + - ]
55 : 49792 : }
56 : 7394 : }
57 : :
58 : : void
59 : 2471 : spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
60 : : {
61 : : unsigned int i;
62 [ + + # # ]: 2471 : assert(dst != NULL);
63 [ + + # # ]: 2471 : assert(src != NULL);
64 [ + + ]: 318759 : for (i = 0; i < sizeof(src->cpus); i++) {
65 [ + - + - : 316288 : dst->cpus[i] |= src->cpus[i];
+ - + - +
- + - ]
66 : 29568 : }
67 : 2471 : }
68 : :
69 : : void
70 : 6988 : spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
71 : : {
72 : : unsigned int i;
73 [ + + # # ]: 6988 : assert(dst != NULL);
74 [ + + # # ]: 6988 : assert(src != NULL);
75 [ + + ]: 901452 : for (i = 0; i < sizeof(src->cpus); i++) {
76 [ + - + - : 894464 : dst->cpus[i] ^= src->cpus[i];
+ - + - +
- + - ]
77 : 50432 : }
78 : 6988 : }
79 : :
80 : : void
81 : 18775 : spdk_cpuset_zero(struct spdk_cpuset *set)
82 : : {
83 [ + + # # ]: 18775 : assert(set != NULL);
84 [ + + + - ]: 18775 : memset(set->cpus, 0, sizeof(set->cpus));
85 : 18775 : }
86 : :
87 : : void
88 : 60595 : spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
89 : : {
90 [ + + # # ]: 60595 : assert(set != NULL);
91 [ + + # # ]: 60595 : assert(cpu < sizeof(set->cpus) * 8);
92 [ + + + + ]: 60595 : if (state) {
93 [ + + + - : 60337 : set->cpus[cpu / 8] |= (1U << (cpu % 8));
+ - + - +
- + - ]
94 : 4807 : } else {
95 [ + + + - : 258 : set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
+ - + - +
- + - ]
96 : : }
97 : 60595 : }
98 : :
99 : : bool
100 : 33533534 : spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
101 : : {
102 [ + + # # ]: 33533534 : assert(set != NULL);
103 [ + + # # ]: 33533534 : assert(cpu < sizeof(set->cpus) * 8);
104 [ + + + - : 33533534 : return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
+ - + - +
- + - ]
105 : : }
106 : :
107 : : void
108 : 8353 : 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 [ + + ]: 1077537 : for (i = 0; i < sizeof(set->cpus); i++) {
114 [ - + - + : 1069184 : n = set->cpus[i];
- + ]
115 [ + + ]: 9622656 : for (j = 0; j < 8; j++) {
116 [ + + + + : 8553472 : if (n & (1 << j)) {
+ + ]
117 [ - + + - ]: 15402 : fn(ctx, i * 8 + j);
118 : 1684 : }
119 : 522240 : }
120 : 65280 : }
121 : 8353 : }
122 : :
123 : : static void
124 : 15302 : count_fn(void *ctx, uint32_t cpu)
125 : : {
126 : 15302 : uint32_t *count = ctx;
127 : :
128 : 15302 : (*count)++;
129 : 15302 : }
130 : :
131 : : uint32_t
132 : 8325 : spdk_cpuset_count(const struct spdk_cpuset *set)
133 : : {
134 : 8325 : uint32_t count = 0;
135 : :
136 : 8325 : spdk_cpuset_for_each_cpu(set, count_fn, &count);
137 : 8325 : return count;
138 : : }
139 : :
140 : : const char *
141 : 2790 : spdk_cpuset_fmt(struct spdk_cpuset *set)
142 : : {
143 : 2790 : uint32_t lcore, lcore_max = 0;
144 : : int val, i, n;
145 : : char *ptr;
146 : : static const char *hex = "0123456789abcdef";
147 : :
148 [ + + # # ]: 2790 : assert(set != NULL);
149 : :
150 [ + + ]: 2859750 : for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
151 [ + + ]: 2856960 : if (spdk_cpuset_get_cpu(set, lcore)) {
152 : 9256 : lcore_max = lcore;
153 : 1286 : }
154 : 128000 : }
155 : :
156 [ # # ]: 2790 : ptr = set->str;
157 [ # # ]: 2790 : n = lcore_max / 8;
158 [ # # # # : 2790 : val = set->cpus[n];
# # ]
159 : :
160 : : /* Store first number only if it is not leading zero */
161 [ + + ]: 2790 : if ((val & 0xf0) != 0) {
162 [ # # # # : 227 : *(ptr++) = hex[(val & 0xf0) >> 4];
# # # # #
# ]
163 : 20 : }
164 [ # # # # : 2790 : *(ptr++) = hex[val & 0x0f];
# # # # ]
165 : :
166 [ + + # # : 4343 : for (i = n - 1; i >= 0; i--) {
# # ]
167 [ # # # # : 1553 : val = set->cpus[i];
# # ]
168 [ # # # # : 1553 : *(ptr++) = hex[(val & 0xf0) >> 4];
# # # # #
# ]
169 [ # # # # : 1553 : *(ptr++) = hex[val & 0x0f];
# # # # ]
170 : 129 : }
171 [ # # ]: 2790 : *ptr = '\0';
172 : :
173 [ # # ]: 2790 : return set->str;
174 : : }
175 : :
176 : : static int
177 : 3473 : 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 [ + - + - : 3473 : return val[c] - 1;
+ - + - ]
189 : : }
190 : :
191 : : static int
192 : 62 : parse_list(const char *mask, struct spdk_cpuset *set)
193 : : {
194 : 51 : char *end;
195 : 62 : const char *ptr = mask;
196 : : uint32_t lcore;
197 : : uint32_t lcore_min, lcore_max;
198 : :
199 : 62 : spdk_cpuset_zero(set);
200 : 62 : lcore_min = UINT32_MAX;
201 : :
202 [ # # ]: 62 : ptr++;
203 : 62 : end = (char *)ptr;
204 : 11 : do {
205 [ - + # # : 116 : while (isblank(*ptr)) {
# # # # #
# ]
206 [ # # ]: 0 : ptr++;
207 : : }
208 [ + + + + : 116 : if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
+ + + + #
# # # # #
# # ]
209 : 20 : goto invalid_character;
210 : : }
211 : :
212 [ # # ]: 96 : errno = 0;
213 [ - + ]: 96 : lcore = strtoul(ptr, &end, 10);
214 [ + + # # ]: 96 : if (errno) {
215 : 4 : SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
216 : 4 : return -1;
217 : : }
218 : :
219 [ + + ]: 92 : if (lcore >= sizeof(set->cpus) * 8) {
220 : 4 : SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
221 : 4 : return -1;
222 : : }
223 : :
224 [ - + # # : 88 : while (isblank(*end)) {
# # # # #
# ]
225 [ # # ]: 0 : end++;
226 : : }
227 : :
228 [ + + # # ]: 88 : if (*end == '-') {
229 : 24 : lcore_min = lcore;
230 [ + + + + : 70 : } else if (*end == ',' || *end == ']') {
# # # # ]
231 : 64 : lcore_max = lcore;
232 [ + + ]: 64 : if (lcore_min == UINT32_MAX) {
233 : 44 : lcore_min = lcore;
234 : 2 : }
235 [ + + ]: 64 : if (lcore_min > lcore_max) {
236 : 4 : SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
237 : : lcore_min, lcore_max);
238 : 4 : return -1;
239 : : }
240 [ + + ]: 4760 : for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
241 : 4700 : spdk_cpuset_set_cpu(set, lcore, true);
242 : 1166 : }
243 : 60 : lcore_min = UINT32_MAX;
244 : 6 : } else {
245 : 0 : goto invalid_character;
246 : : }
247 : :
248 [ # # ]: 84 : ptr = end + 1;
249 : :
250 [ + + # # ]: 84 : } while (*end != ']');
251 : :
252 : 30 : return 0;
253 : :
254 : 15 : invalid_character:
255 [ + + # # ]: 20 : if (*end == '\0') {
256 : 4 : SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
257 : 1 : } else {
258 [ # # ]: 16 : SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
259 : : }
260 : 20 : return -1;
261 : 11 : }
262 : :
263 : : static int
264 : 557 : parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
265 : : {
266 : : int i, j;
267 : : char c;
268 : : int val;
269 : 557 : uint32_t lcore = 0;
270 : :
271 [ + + + + : 557 : if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
+ + + - +
- + + + -
+ - - + ]
272 [ + - ]: 341 : mask += 2;
273 : 341 : len -= 2;
274 : 29 : }
275 : :
276 : 557 : spdk_cpuset_zero(set);
277 [ + + + - ]: 4362 : for (i = len - 1; i >= 0; i--) {
278 [ + - + - ]: 3805 : c = mask[i];
279 [ + + ]: 3805 : if (c == ',') {
280 : : /* Linux puts comma delimiters in its cpumasks, just skip them. */
281 : 332 : continue;
282 : : }
283 : 3473 : val = hex_value(c);
284 [ + + ]: 3473 : 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 [ + + + + : 17365 : for (j = 0; j < 4 && lcore < SPDK_CPUSET_SIZE; j++, lcore++) {
+ - ]
290 [ + + + + : 13892 : if ((1 << j) & val) {
+ + ]
291 : 1585 : spdk_cpuset_set_cpu(set, lcore, true);
292 : 207 : }
293 : 924 : }
294 : 231 : }
295 : :
296 : 557 : return 0;
297 : 35 : }
298 : :
299 : : int
300 : 631 : spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
301 : : {
302 : : int ret;
303 : : size_t len;
304 : :
305 [ + + + + ]: 631 : if (mask == NULL || set == NULL) {
306 : 8 : return -1;
307 : : }
308 : :
309 [ + + + - : 623 : while (isblank(*mask)) {
+ - + - -
+ ]
310 [ # # ]: 0 : mask++;
311 : : }
312 : :
313 [ + + ]: 623 : len = strlen(mask);
314 [ + + + + : 623 : while (len > 0 && isblank(mask[len - 1])) {
+ - + - +
- + - -
+ ]
315 : 0 : len--;
316 : : }
317 : :
318 [ + + ]: 623 : if (len == 0) {
319 : 4 : return -1;
320 : : }
321 : :
322 [ + + + - : 619 : if (mask[0] == '[') {
- + ]
323 : 62 : ret = parse_list(mask, set);
324 : 11 : } else {
325 : 557 : ret = parse_mask(mask, set, len);
326 : : }
327 : :
328 : 619 : return ret;
329 : 49 : }
|