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 : 24 : spdk_cpuset_alloc(void)
11 : : {
12 : 24 : return (struct spdk_cpuset *)calloc(sizeof(struct spdk_cpuset), 1);
13 : : }
14 : :
15 : : void
16 : 24 : spdk_cpuset_free(struct spdk_cpuset *set)
17 : : {
18 : 24 : free(set);
19 : 24 : }
20 : :
21 : : bool
22 : 992 : spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
23 : : {
24 [ - + ]: 992 : assert(set1 != NULL);
25 [ - + ]: 992 : assert(set2 != NULL);
26 [ - + - + ]: 992 : return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
27 : : }
28 : :
29 : : void
30 : 31577 : spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
31 : : {
32 [ - + ]: 31577 : assert(dst != NULL);
33 [ - + ]: 31577 : assert(src != NULL);
34 [ - + - + ]: 31577 : memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
35 : 31577 : }
36 : :
37 : : void
38 : 2634 : spdk_cpuset_negate(struct spdk_cpuset *set)
39 : : {
40 : : unsigned int i;
41 [ - + ]: 2634 : assert(set != NULL);
42 [ + + ]: 339786 : for (i = 0; i < sizeof(set->cpus); i++) {
43 : 337152 : set->cpus[i] = ~set->cpus[i];
44 : : }
45 : 2634 : }
46 : :
47 : : void
48 : 8313 : spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
49 : : {
50 : : unsigned int i;
51 [ - + ]: 8313 : assert(dst != NULL);
52 [ - + ]: 8313 : assert(src != NULL);
53 [ + + ]: 1072377 : for (i = 0; i < sizeof(src->cpus); i++) {
54 : 1064064 : dst->cpus[i] &= src->cpus[i];
55 : : }
56 : 8313 : }
57 : :
58 : : void
59 : 991 : spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
60 : : {
61 : : unsigned int i;
62 [ - + ]: 991 : assert(dst != NULL);
63 [ - + ]: 991 : assert(src != NULL);
64 [ + + ]: 127839 : for (i = 0; i < sizeof(src->cpus); i++) {
65 : 126848 : dst->cpus[i] |= src->cpus[i];
66 : : }
67 : 991 : }
68 : :
69 : : void
70 : 8018 : spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
71 : : {
72 : : unsigned int i;
73 [ - + ]: 8018 : assert(dst != NULL);
74 [ - + ]: 8018 : assert(src != NULL);
75 [ + + ]: 1034322 : for (i = 0; i < sizeof(src->cpus); i++) {
76 : 1026304 : dst->cpus[i] ^= src->cpus[i];
77 : : }
78 : 8018 : }
79 : :
80 : : void
81 : 20620 : spdk_cpuset_zero(struct spdk_cpuset *set)
82 : : {
83 [ - + ]: 20620 : assert(set != NULL);
84 [ - + ]: 20620 : memset(set->cpus, 0, sizeof(set->cpus));
85 : 20620 : }
86 : :
87 : : void
88 : 63116 : spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
89 : : {
90 [ - + ]: 63116 : assert(set != NULL);
91 [ - + ]: 63116 : assert(cpu < sizeof(set->cpus) * 8);
92 [ + + ]: 63116 : if (state) {
93 [ - + ]: 62892 : set->cpus[cpu / 8] |= (1U << (cpu % 8));
94 : : } else {
95 [ - + ]: 224 : set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
96 : : }
97 : 63116 : }
98 : :
99 : : bool
100 : 28576293 : spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
101 : : {
102 [ - + ]: 28576293 : assert(set != NULL);
103 [ - + ]: 28576293 : assert(cpu < sizeof(set->cpus) * 8);
104 [ - + ]: 28576293 : return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
105 : : }
106 : :
107 : : uint32_t
108 : 9103 : spdk_cpuset_count(const struct spdk_cpuset *set)
109 : : {
110 : 9103 : uint32_t count = 0;
111 : : uint8_t n;
112 : : unsigned int i;
113 [ + + ]: 1174287 : for (i = 0; i < sizeof(set->cpus); i++) {
114 : 1165184 : n = set->cpus[i];
115 [ + + ]: 1180961 : while (n) {
116 : 15777 : n &= (n - 1);
117 : 15777 : count++;
118 : : }
119 : : }
120 : 9103 : return count;
121 : : }
122 : :
123 : : const char *
124 : 2265 : spdk_cpuset_fmt(struct spdk_cpuset *set)
125 : : {
126 : 2265 : uint32_t lcore, lcore_max = 0;
127 : : int val, i, n;
128 : : char *ptr;
129 : : static const char *hex = "0123456789abcdef";
130 : :
131 [ - + ]: 2265 : assert(set != NULL);
132 : :
133 [ + + ]: 2321625 : for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
134 [ + + ]: 2319360 : if (spdk_cpuset_get_cpu(set, lcore)) {
135 : 8424 : lcore_max = lcore;
136 : : }
137 : : }
138 : :
139 : 2265 : ptr = set->str;
140 : 2265 : n = lcore_max / 8;
141 : 2265 : val = set->cpus[n];
142 : :
143 : : /* Store first number only if it is not leading zero */
144 [ + + ]: 2265 : if ((val & 0xf0) != 0) {
145 : 176 : *(ptr++) = hex[(val & 0xf0) >> 4];
146 : : }
147 : 2265 : *(ptr++) = hex[val & 0x0f];
148 : :
149 [ + + ]: 3408 : for (i = n - 1; i >= 0; i--) {
150 : 1143 : val = set->cpus[i];
151 : 1143 : *(ptr++) = hex[(val & 0xf0) >> 4];
152 : 1143 : *(ptr++) = hex[val & 0x0f];
153 : : }
154 : 2265 : *ptr = '\0';
155 : :
156 : 2265 : return set->str;
157 : : }
158 : :
159 : : static int
160 : 623 : 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 : 623 : return val[c] - 1;
172 : : }
173 : :
174 : : static int
175 : 53 : parse_list(const char *mask, struct spdk_cpuset *set)
176 : : {
177 : 50 : char *end;
178 : 53 : const char *ptr = mask;
179 : : uint32_t lcore;
180 : : uint32_t lcore_min, lcore_max;
181 : :
182 : 53 : spdk_cpuset_zero(set);
183 : 53 : lcore_min = UINT32_MAX;
184 : :
185 : 53 : ptr++;
186 : 53 : end = (char *)ptr;
187 : : do {
188 [ - + ]: 107 : while (isblank(*ptr)) {
189 : 0 : ptr++;
190 : : }
191 [ + + + + : 107 : if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
+ + + + ]
192 : 20 : goto invalid_character;
193 : : }
194 : :
195 : 87 : errno = 0;
196 [ - + ]: 87 : lcore = strtoul(ptr, &end, 10);
197 [ + + ]: 87 : if (errno) {
198 : 4 : SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
199 : 4 : return -1;
200 : : }
201 : :
202 [ + + ]: 83 : if (lcore >= sizeof(set->cpus) * 8) {
203 : 4 : SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
204 : 4 : return -1;
205 : : }
206 : :
207 [ - + ]: 79 : while (isblank(*end)) {
208 : 0 : end++;
209 : : }
210 : :
211 [ + + ]: 79 : if (*end == '-') {
212 : 24 : lcore_min = lcore;
213 [ + + + - ]: 55 : } else if (*end == ',' || *end == ']') {
214 : 55 : lcore_max = lcore;
215 [ + + ]: 55 : if (lcore_min == UINT32_MAX) {
216 : 35 : lcore_min = lcore;
217 : : }
218 [ + + ]: 55 : if (lcore_min > lcore_max) {
219 : 4 : SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
220 : : lcore_min, lcore_max);
221 : 4 : return -1;
222 : : }
223 [ + + ]: 4742 : for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
224 : 4691 : spdk_cpuset_set_cpu(set, lcore, true);
225 : : }
226 : 51 : lcore_min = UINT32_MAX;
227 : : } else {
228 : 0 : goto invalid_character;
229 : : }
230 : :
231 : 75 : ptr = end + 1;
232 : :
233 [ + + ]: 75 : } while (*end != ']');
234 : :
235 : 21 : return 0;
236 : :
237 : 20 : invalid_character:
238 [ + + ]: 20 : if (*end == '\0') {
239 : 4 : SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
240 : : } else {
241 : 16 : SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
242 : : }
243 : 20 : return -1;
244 : : }
245 : :
246 : : static int
247 : 353 : parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
248 : : {
249 : : int i, j;
250 : : char c;
251 : : int val;
252 : 353 : uint32_t lcore = 0;
253 : :
254 [ + + - + : 353 : if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
- - ]
255 : 333 : mask += 2;
256 : 333 : len -= 2;
257 : : }
258 : :
259 : 353 : spdk_cpuset_zero(set);
260 [ + + ]: 976 : for (i = len - 1; i >= 0; i--) {
261 : 623 : c = mask[i];
262 : 623 : val = hex_value(c);
263 [ - + ]: 623 : 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 [ + + + - ]: 3115 : for (j = 0; j < 4 && lcore < SPDK_CPUSET_SIZE; j++, lcore++) {
269 [ + + + + ]: 2492 : if ((1 << j) & val) {
270 : 1122 : spdk_cpuset_set_cpu(set, lcore, true);
271 : : }
272 : : }
273 : : }
274 : :
275 : 353 : return 0;
276 : : }
277 : :
278 : : int
279 : 418 : spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
280 : : {
281 : : int ret;
282 : : size_t len;
283 : :
284 [ + + + + ]: 418 : if (mask == NULL || set == NULL) {
285 : 8 : return -1;
286 : : }
287 : :
288 [ - + ]: 410 : while (isblank(*mask)) {
289 : 0 : mask++;
290 : : }
291 : :
292 [ - + ]: 410 : len = strlen(mask);
293 [ + + - + ]: 410 : while (len > 0 && isblank(mask[len - 1])) {
294 : 0 : len--;
295 : : }
296 : :
297 [ + + ]: 410 : if (len == 0) {
298 : 4 : return -1;
299 : : }
300 : :
301 [ + + ]: 406 : if (mask[0] == '[') {
302 : 53 : ret = parse_list(mask, set);
303 : : } else {
304 : 353 : ret = parse_mask(mask, set, len);
305 : : }
306 : :
307 : 406 : return ret;
308 : : }
|