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 : 30 : spdk_cpuset_alloc(void)
11 : : {
12 : 30 : return (struct spdk_cpuset *)calloc(sizeof(struct spdk_cpuset), 1);
13 : : }
14 : :
15 : : void
16 : 30 : spdk_cpuset_free(struct spdk_cpuset *set)
17 : : {
18 : 30 : free(set);
19 : 30 : }
20 : :
21 : : bool
22 : 881 : spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
23 : : {
24 [ - + # # ]: 881 : assert(set1 != NULL);
25 [ - + # # ]: 881 : assert(set2 != NULL);
26 [ - + - + : 881 : return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
# # # # ]
27 : : }
28 : :
29 : : void
30 : 27248 : spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
31 : : {
32 [ + + # # ]: 27248 : assert(dst != NULL);
33 [ + + # # ]: 27248 : assert(src != NULL);
34 [ + + + + : 27248 : memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
+ - + - ]
35 : 27248 : }
36 : :
37 : : void
38 : 2919 : spdk_cpuset_negate(struct spdk_cpuset *set)
39 : : {
40 : 187 : unsigned int i;
41 [ + + # # ]: 2919 : assert(set != NULL);
42 [ + + ]: 376551 : for (i = 0; i < sizeof(set->cpus); i++) {
43 [ + - + - : 373632 : set->cpus[i] = ~set->cpus[i];
+ - + - +
- + - ]
44 : 32640 : }
45 : 2919 : }
46 : :
47 : : void
48 : 8098 : spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
49 : : {
50 : 30 : unsigned int i;
51 [ + + # # ]: 8098 : assert(dst != NULL);
52 [ + + # # ]: 8098 : assert(src != NULL);
53 [ + + ]: 1044642 : for (i = 0; i < sizeof(src->cpus); i++) {
54 [ + - + - : 1036544 : dst->cpus[i] &= src->cpus[i];
+ - + - +
- + - ]
55 : 37248 : }
56 : 8098 : }
57 : :
58 : : void
59 : 880 : spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
60 : : {
61 : 0 : unsigned int i;
62 [ - + # # ]: 880 : assert(dst != NULL);
63 [ - + # # ]: 880 : assert(src != NULL);
64 [ + + ]: 113520 : for (i = 0; i < sizeof(src->cpus); i++) {
65 [ # # # # : 112640 : dst->cpus[i] |= src->cpus[i];
# # # # #
# # # ]
66 : 0 : }
67 : 880 : }
68 : :
69 : : void
70 : 7780 : spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
71 : : {
72 : 21 : unsigned int i;
73 [ + + # # ]: 7780 : assert(dst != NULL);
74 [ + + # # ]: 7780 : assert(src != NULL);
75 [ + + ]: 1003620 : for (i = 0; i < sizeof(src->cpus); i++) {
76 [ + - + - : 995840 : dst->cpus[i] ^= src->cpus[i];
+ - + - +
- + - ]
77 : 36352 : }
78 : 7780 : }
79 : :
80 : : void
81 : 20095 : spdk_cpuset_zero(struct spdk_cpuset *set)
82 : : {
83 [ + + # # ]: 20095 : assert(set != NULL);
84 [ + + + - ]: 20095 : memset(set->cpus, 0, sizeof(set->cpus));
85 : 20095 : }
86 : :
87 : : void
88 : 64523 : spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
89 : : {
90 [ + + # # ]: 64523 : assert(set != NULL);
91 [ + + # # ]: 64523 : assert(cpu < sizeof(set->cpus) * 8);
92 [ + + + + ]: 64523 : if (state) {
93 [ + + + - : 64289 : set->cpus[cpu / 8] |= (1U << (cpu % 8));
+ - + - +
- + - ]
94 : 4341 : } else {
95 [ + + + - : 234 : set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
+ - + - +
- + - ]
96 : : }
97 : 64523 : }
98 : :
99 : : bool
100 : 28646995 : spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
101 : : {
102 [ + + # # ]: 28646995 : assert(set != NULL);
103 [ + + # # ]: 28646995 : assert(cpu < sizeof(set->cpus) * 8);
104 [ + + + - : 28646995 : return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
+ - + - +
- + - ]
105 : : }
106 : :
107 : : uint32_t
108 : 8795 : spdk_cpuset_count(const struct spdk_cpuset *set)
109 : : {
110 : 8795 : uint32_t count = 0;
111 : 37 : uint8_t n;
112 : 37 : unsigned int i;
113 [ + + ]: 1134555 : for (i = 0; i < sizeof(set->cpus); i++) {
114 [ - + - + : 1125760 : n = set->cpus[i];
- + ]
115 [ + + ]: 1142900 : while (n) {
116 [ - + ]: 17140 : n &= (n - 1);
117 : 17140 : count++;
118 : : }
119 : 38144 : }
120 : 8832 : return count;
121 : 37 : }
122 : :
123 : : const char *
124 : 2148 : spdk_cpuset_fmt(struct spdk_cpuset *set)
125 : : {
126 : 2148 : uint32_t lcore, lcore_max = 0;
127 : 11 : int val, i, n;
128 : 11 : char *ptr;
129 : : static const char *hex = "0123456789abcdef";
130 : :
131 [ + + # # ]: 2148 : assert(set != NULL);
132 : :
133 [ + + ]: 2201700 : for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
134 [ + + ]: 2199552 : if (spdk_cpuset_get_cpu(set, lcore)) {
135 : 10268 : lcore_max = lcore;
136 : 1058 : }
137 : 11264 : }
138 : :
139 [ + - ]: 2148 : ptr = set->str;
140 [ + - ]: 2148 : n = lcore_max / 8;
141 [ + - + - : 2148 : val = set->cpus[n];
+ - ]
142 : :
143 : : /* Store first number only if it is not leading zero */
144 [ + + ]: 2148 : if ((val & 0xf0) != 0) {
145 [ + - + - : 155 : *(ptr++) = hex[(val & 0xf0) >> 4];
+ - + - +
- ]
146 : 1 : }
147 [ + - + - : 2148 : *(ptr++) = hex[val & 0x0f];
+ - + - ]
148 : :
149 [ + + + + : 3549 : for (i = n - 1; i >= 0; i--) {
+ - ]
150 [ + - + - : 1401 : val = set->cpus[i];
+ - ]
151 [ + - + - : 1401 : *(ptr++) = hex[(val & 0xf0) >> 4];
+ - + - +
- ]
152 [ + - + - : 1401 : *(ptr++) = hex[val & 0x0f];
+ - + - ]
153 : 129 : }
154 [ + - ]: 2148 : *ptr = '\0';
155 : :
156 [ + - ]: 2148 : return set->str;
157 : 11 : }
158 : :
159 : : static int
160 : 697 : hex_value(uint8_t c)
161 : : {
162 : : #define V(x, y) [x] = y + 1
163 : : static const int8_t val[256] = {
164 : : V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
165 : : V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
166 : : V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
167 : : V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
168 : : };
169 : : #undef V
170 : :
171 [ + - + - : 697 : return val[c] - 1;
+ - + - ]
172 : : }
173 : :
174 : : static int
175 : 75 : parse_list(const char *mask, struct spdk_cpuset *set)
176 : : {
177 : 61 : char *end;
178 : 75 : const char *ptr = mask;
179 : 11 : uint32_t lcore;
180 : 11 : uint32_t lcore_min, lcore_max;
181 : :
182 : 75 : spdk_cpuset_zero(set);
183 : 75 : lcore_min = UINT32_MAX;
184 : :
185 [ + - ]: 75 : ptr++;
186 : 75 : end = (char *)ptr;
187 : 11 : do {
188 [ + + + - : 147 : while (isblank(*ptr)) {
+ - + - -
+ ]
189 [ # # ]: 0 : ptr++;
190 : : }
191 [ + + + + : 147 : if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
+ + + + +
- + + + -
+ + ]
192 : 30 : goto invalid_character;
193 : : }
194 : :
195 [ + - ]: 117 : errno = 0;
196 [ + + ]: 117 : lcore = strtoul(ptr, &end, 10);
197 [ + + + + ]: 117 : if (errno) {
198 : 6 : SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
199 : 6 : return -1;
200 : : }
201 : :
202 [ + + ]: 111 : if (lcore >= sizeof(set->cpus) * 8) {
203 : 6 : SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
204 : 6 : return -1;
205 : : }
206 : :
207 [ + + + - : 105 : while (isblank(*end)) {
+ - + - -
+ ]
208 [ # # ]: 0 : end++;
209 : : }
210 : :
211 [ + + + + ]: 105 : if (*end == '-') {
212 : 36 : lcore_min = lcore;
213 [ + + + + : 75 : } else if (*end == ',' || *end == ']') {
+ - + - ]
214 : 69 : lcore_max = lcore;
215 [ + + ]: 69 : if (lcore_min == UINT32_MAX) {
216 : 39 : lcore_min = lcore;
217 : 2 : }
218 [ + + ]: 69 : if (lcore_min > lcore_max) {
219 : 6 : SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
220 : : lcore_min, lcore_max);
221 : 6 : return -1;
222 : : }
223 [ + + ]: 7086 : for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
224 : 7023 : spdk_cpuset_set_cpu(set, lcore, true);
225 : 1166 : }
226 : 63 : lcore_min = UINT32_MAX;
227 : 6 : } else {
228 : 0 : goto invalid_character;
229 : : }
230 : :
231 [ + - ]: 99 : ptr = end + 1;
232 : :
233 [ + + + + ]: 99 : } while (*end != ']');
234 : :
235 : 27 : return 0;
236 : :
237 : 25 : invalid_character:
238 [ + + + + ]: 30 : if (*end == '\0') {
239 : 6 : SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
240 : 1 : } else {
241 [ - + ]: 24 : SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
242 : : }
243 : 30 : return -1;
244 : 11 : }
245 : :
246 : : static int
247 : 357 : parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
248 : : {
249 : 12 : int i, j;
250 : 12 : char c;
251 : 12 : int val;
252 : 357 : uint32_t lcore = 0;
253 : :
254 [ + + + + : 357 : if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
+ - + - +
- - + # #
# # # # ]
255 [ + - ]: 337 : mask += 2;
256 : 337 : len -= 2;
257 : 20 : }
258 : :
259 : 357 : spdk_cpuset_zero(set);
260 [ + + + - ]: 1054 : for (i = len - 1; i >= 0; i--) {
261 [ + - + - ]: 697 : c = mask[i];
262 : 697 : val = hex_value(c);
263 [ + + ]: 697 : if (val < 0) {
264 : : /* Invalid character */
265 : 0 : SPDK_ERRLOG("Invalid character in core mask '%s' (%c)\n", mask, c);
266 : 0 : return -1;
267 : : }
268 [ + + + + : 3485 : for (j = 0; j < 4 && lcore < SPDK_CPUSET_SIZE; j++, lcore++) {
+ - ]
269 [ + + + + : 2788 : if ((1 << j) & val) {
+ + ]
270 : 1048 : spdk_cpuset_set_cpu(set, lcore, true);
271 : 44 : }
272 : 256 : }
273 : 64 : }
274 : :
275 : 357 : return 0;
276 : 20 : }
277 : :
278 : : int
279 : 450 : spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
280 : : {
281 : 26 : int ret;
282 : 26 : size_t len;
283 : :
284 [ + + + + ]: 450 : if (mask == NULL || set == NULL) {
285 : 12 : return -1;
286 : : }
287 : :
288 [ + + + - : 438 : while (isblank(*mask)) {
+ - + - -
+ ]
289 [ # # ]: 0 : mask++;
290 : : }
291 : :
292 [ + + ]: 438 : len = strlen(mask);
293 [ + + + + : 438 : while (len > 0 && isblank(mask[len - 1])) {
+ - + - +
- + - -
+ ]
294 : 0 : len--;
295 : : }
296 : :
297 [ + + ]: 438 : if (len == 0) {
298 : 6 : return -1;
299 : : }
300 : :
301 [ + + + - : 432 : if (mask[0] == '[') {
+ + ]
302 : 75 : ret = parse_list(mask, set);
303 : 11 : } else {
304 : 357 : ret = parse_mask(mask, set, len);
305 : : }
306 : :
307 : 432 : return ret;
308 : 34 : }
|