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 : 1095 : spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
23 : : {
24 [ - + ]: 1095 : assert(set1 != NULL);
25 [ - + ]: 1095 : assert(set2 != NULL);
26 [ - + - + ]: 1095 : return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
27 : : }
28 : :
29 : : void
30 : 26791 : spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
31 : : {
32 [ - + ]: 26791 : assert(dst != NULL);
33 [ - + ]: 26791 : assert(src != NULL);
34 [ - + - + ]: 26791 : memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
35 : 26791 : }
36 : :
37 : : void
38 : 3151 : spdk_cpuset_negate(struct spdk_cpuset *set)
39 : : {
40 : : unsigned int i;
41 [ - + ]: 3151 : assert(set != NULL);
42 [ + + ]: 406479 : for (i = 0; i < sizeof(set->cpus); i++) {
43 : 403328 : set->cpus[i] = ~set->cpus[i];
44 : : }
45 : 3151 : }
46 : :
47 : : void
48 : 8031 : spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
49 : : {
50 : : unsigned int i;
51 [ - + ]: 8031 : assert(dst != NULL);
52 [ - + ]: 8031 : assert(src != NULL);
53 [ + + ]: 1035999 : for (i = 0; i < sizeof(src->cpus); i++) {
54 : 1027968 : dst->cpus[i] &= src->cpus[i];
55 : : }
56 : 8031 : }
57 : :
58 : : void
59 : 1094 : spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
60 : : {
61 : : unsigned int i;
62 [ - + ]: 1094 : assert(dst != NULL);
63 [ - + ]: 1094 : assert(src != NULL);
64 [ + + ]: 141126 : for (i = 0; i < sizeof(src->cpus); i++) {
65 : 140032 : dst->cpus[i] |= src->cpus[i];
66 : : }
67 : 1094 : }
68 : :
69 : : void
70 : 7711 : spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
71 : : {
72 : : unsigned int i;
73 [ - + ]: 7711 : assert(dst != NULL);
74 [ - + ]: 7711 : assert(src != NULL);
75 [ + + ]: 994719 : for (i = 0; i < sizeof(src->cpus); i++) {
76 : 987008 : dst->cpus[i] ^= src->cpus[i];
77 : : }
78 : 7711 : }
79 : :
80 : : void
81 : 19873 : spdk_cpuset_zero(struct spdk_cpuset *set)
82 : : {
83 [ - + ]: 19873 : assert(set != NULL);
84 [ - + ]: 19873 : memset(set->cpus, 0, sizeof(set->cpus));
85 : 19873 : }
86 : :
87 : : void
88 : 63573 : spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
89 : : {
90 [ - + ]: 63573 : assert(set != NULL);
91 [ - + ]: 63573 : assert(cpu < sizeof(set->cpus) * 8);
92 [ + + ]: 63573 : if (state) {
93 [ - + ]: 63327 : set->cpus[cpu / 8] |= (1U << (cpu % 8));
94 : : } else {
95 [ - + ]: 246 : set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
96 : : }
97 : 63573 : }
98 : :
99 : : bool
100 : 28503372 : spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
101 : : {
102 [ - + ]: 28503372 : assert(set != NULL);
103 [ - + ]: 28503372 : assert(cpu < sizeof(set->cpus) * 8);
104 [ - + ]: 28503372 : return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
105 : : }
106 : :
107 : : uint32_t
108 : 8951 : spdk_cpuset_count(const struct spdk_cpuset *set)
109 : : {
110 : 8951 : uint32_t count = 0;
111 : : uint8_t n;
112 : : unsigned int i;
113 [ + + ]: 1154679 : for (i = 0; i < sizeof(set->cpus); i++) {
114 : 1145728 : n = set->cpus[i];
115 [ + + ]: 1163308 : while (n) {
116 : 17580 : n &= (n - 1);
117 : 17580 : count++;
118 : : }
119 : : }
120 : 8951 : return count;
121 : : }
122 : :
123 : : const char *
124 : 2370 : spdk_cpuset_fmt(struct spdk_cpuset *set)
125 : : {
126 : 2370 : uint32_t lcore, lcore_max = 0;
127 : : int val, i, n;
128 : : char *ptr;
129 : : static const char *hex = "0123456789abcdef";
130 : :
131 [ - + ]: 2370 : assert(set != NULL);
132 : :
133 [ + + ]: 2429250 : for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
134 [ + + ]: 2426880 : if (spdk_cpuset_get_cpu(set, lcore)) {
135 : 10623 : lcore_max = lcore;
136 : : }
137 : : }
138 : :
139 : 2370 : ptr = set->str;
140 : 2370 : n = lcore_max / 8;
141 : 2370 : val = set->cpus[n];
142 : :
143 : : /* Store first number only if it is not leading zero */
144 [ + + ]: 2370 : if ((val & 0xf0) != 0) {
145 : 174 : *(ptr++) = hex[(val & 0xf0) >> 4];
146 : : }
147 : 2370 : *(ptr++) = hex[val & 0x0f];
148 : :
149 [ + + ]: 3771 : 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 : : }
154 : 2370 : *ptr = '\0';
155 : :
156 : 2370 : return set->str;
157 : : }
158 : :
159 : : static int
160 : 735 : 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 : 735 : 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 : : uint32_t lcore;
180 : : 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 : : 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 [ + + + - ]: 69 : } else if (*end == ',' || *end == ']') {
214 : 69 : lcore_max = lcore;
215 [ + + ]: 69 : if (lcore_min == UINT32_MAX) {
216 : 39 : lcore_min = lcore;
217 : : }
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 : : }
226 : 63 : lcore_min = UINT32_MAX;
227 : : } 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 : 30 : invalid_character:
238 [ + + ]: 30 : if (*end == '\0') {
239 : 6 : SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
240 : : } else {
241 : 24 : SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
242 : : }
243 : 30 : return -1;
244 : : }
245 : :
246 : : static int
247 : 377 : parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
248 : : {
249 : : int i, j;
250 : : char c;
251 : : int val;
252 : 377 : uint32_t lcore = 0;
253 : :
254 [ + + - + : 377 : if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
- - ]
255 : 357 : mask += 2;
256 : 357 : len -= 2;
257 : : }
258 : :
259 : 377 : spdk_cpuset_zero(set);
260 [ + + ]: 1112 : for (i = len - 1; i >= 0; i--) {
261 : 735 : c = mask[i];
262 : 735 : val = hex_value(c);
263 [ - + ]: 735 : 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 [ + + + - ]: 3675 : for (j = 0; j < 4 && lcore < SPDK_CPUSET_SIZE; j++, lcore++) {
269 [ + + + + ]: 2940 : if ((1 << j) & val) {
270 : 1194 : spdk_cpuset_set_cpu(set, lcore, true);
271 : : }
272 : : }
273 : : }
274 : :
275 : 377 : return 0;
276 : : }
277 : :
278 : : int
279 : 470 : spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
280 : : {
281 : : int ret;
282 : : size_t len;
283 : :
284 [ + + + + ]: 470 : if (mask == NULL || set == NULL) {
285 : 12 : return -1;
286 : : }
287 : :
288 [ - + ]: 458 : while (isblank(*mask)) {
289 : 0 : mask++;
290 : : }
291 : :
292 [ - + ]: 458 : len = strlen(mask);
293 [ + + - + ]: 458 : while (len > 0 && isblank(mask[len - 1])) {
294 : 0 : len--;
295 : : }
296 : :
297 [ + + ]: 458 : if (len == 0) {
298 : 6 : return -1;
299 : : }
300 : :
301 [ + + ]: 452 : if (mask[0] == '[') {
302 : 75 : ret = parse_list(mask, set);
303 : : } else {
304 : 377 : ret = parse_mask(mask, set, len);
305 : : }
306 : :
307 : 452 : return ret;
308 : : }
|