1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk/cpuset.h" 8 9 #include "spdk_internal/cunit.h" 10 11 #include "util/cpuset.c" 12 13 static int 14 cpuset_check_range(struct spdk_cpuset *core_mask, uint32_t min, uint32_t max, bool isset) 15 { 16 uint32_t core; 17 for (core = min; core <= max; core++) { 18 if (isset != spdk_cpuset_get_cpu(core_mask, core)) { 19 return -1; 20 } 21 } 22 return 0; 23 } 24 25 static void 26 test_cpuset(void) 27 { 28 uint32_t cpu; 29 struct spdk_cpuset *set = spdk_cpuset_alloc(); 30 31 SPDK_CU_ASSERT_FATAL(set != NULL); 32 CU_ASSERT(spdk_cpuset_count(set) == 0); 33 34 /* Set cpu 0 */ 35 spdk_cpuset_set_cpu(set, 0, true); 36 CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == true); 37 CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 1, false) == 0); 38 CU_ASSERT(spdk_cpuset_count(set) == 1); 39 40 /* Set last cpu (cpu 0 already set) */ 41 spdk_cpuset_set_cpu(set, SPDK_CPUSET_SIZE - 1, true); 42 CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == true); 43 CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true); 44 CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 2, false) == 0); 45 CU_ASSERT(spdk_cpuset_count(set) == 2); 46 47 /* Clear cpu 0 (last cpu already set) */ 48 spdk_cpuset_set_cpu(set, 0, false); 49 CU_ASSERT(spdk_cpuset_get_cpu(set, 0) == false); 50 CU_ASSERT(cpuset_check_range(set, 1, SPDK_CPUSET_SIZE - 2, false) == 0); 51 CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true); 52 CU_ASSERT(spdk_cpuset_count(set) == 1); 53 54 /* Set middle cpu (last cpu already set) */ 55 cpu = (SPDK_CPUSET_SIZE - 1) / 2; 56 spdk_cpuset_set_cpu(set, cpu, true); 57 CU_ASSERT(spdk_cpuset_get_cpu(set, cpu) == true); 58 CU_ASSERT(spdk_cpuset_get_cpu(set, SPDK_CPUSET_SIZE - 1) == true); 59 CU_ASSERT(cpuset_check_range(set, 1, cpu - 1, false) == 0); 60 CU_ASSERT(cpuset_check_range(set, cpu + 1, SPDK_CPUSET_SIZE - 2, false) == 0); 61 CU_ASSERT(spdk_cpuset_count(set) == 2); 62 63 /* Set all cpus */ 64 for (cpu = 0; cpu < SPDK_CPUSET_SIZE; cpu++) { 65 spdk_cpuset_set_cpu(set, cpu, true); 66 } 67 CU_ASSERT(cpuset_check_range(set, 0, SPDK_CPUSET_SIZE - 1, true) == 0); 68 CU_ASSERT(spdk_cpuset_count(set) == SPDK_CPUSET_SIZE); 69 70 /* Clear all cpus */ 71 spdk_cpuset_zero(set); 72 CU_ASSERT(cpuset_check_range(set, 0, SPDK_CPUSET_SIZE - 1, false) == 0); 73 CU_ASSERT(spdk_cpuset_count(set) == 0); 74 75 spdk_cpuset_free(set); 76 } 77 78 static void 79 test_cpuset_parse(void) 80 { 81 int rc; 82 struct spdk_cpuset *core_mask; 83 char buf[1024]; 84 85 core_mask = spdk_cpuset_alloc(); 86 SPDK_CU_ASSERT_FATAL(core_mask != NULL); 87 88 /* Only core 0 should be set */ 89 rc = spdk_cpuset_parse(core_mask, "0x1"); 90 CU_ASSERT(rc >= 0); 91 CU_ASSERT(cpuset_check_range(core_mask, 0, 0, true) == 0); 92 CU_ASSERT(cpuset_check_range(core_mask, 1, SPDK_CPUSET_SIZE - 1, false) == 0); 93 94 /* Only core 1 should be set */ 95 rc = spdk_cpuset_parse(core_mask, "[1]"); 96 CU_ASSERT(rc >= 0); 97 CU_ASSERT(cpuset_check_range(core_mask, 0, 0, false) == 0); 98 CU_ASSERT(cpuset_check_range(core_mask, 1, 1, true) == 0); 99 CU_ASSERT(cpuset_check_range(core_mask, 2, SPDK_CPUSET_SIZE - 1, false) == 0); 100 101 /* Set cores 0-10,12,128-254 */ 102 rc = spdk_cpuset_parse(core_mask, "[0-10,12,128-254]"); 103 CU_ASSERT(rc >= 0); 104 CU_ASSERT(cpuset_check_range(core_mask, 0, 10, true) == 0); 105 CU_ASSERT(cpuset_check_range(core_mask, 11, 11, false) == 0); 106 CU_ASSERT(cpuset_check_range(core_mask, 12, 12, true) == 0); 107 CU_ASSERT(cpuset_check_range(core_mask, 13, 127, false) == 0); 108 CU_ASSERT(cpuset_check_range(core_mask, 128, 254, true) == 0); 109 CU_ASSERT(cpuset_check_range(core_mask, 255, SPDK_CPUSET_SIZE - 1, false) == 0); 110 111 /* Set all cores */ 112 snprintf(buf, sizeof(buf), "[0-%d]", SPDK_CPUSET_SIZE - 1); 113 rc = spdk_cpuset_parse(core_mask, buf); 114 CU_ASSERT(rc >= 0); 115 CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0); 116 117 /* Null parameters not allowed */ 118 rc = spdk_cpuset_parse(core_mask, NULL); 119 CU_ASSERT(rc < 0); 120 121 rc = spdk_cpuset_parse(NULL, "[1]"); 122 CU_ASSERT(rc < 0); 123 124 /* Wrong formatted core lists */ 125 rc = spdk_cpuset_parse(core_mask, ""); 126 CU_ASSERT(rc < 0); 127 128 rc = spdk_cpuset_parse(core_mask, "["); 129 CU_ASSERT(rc < 0); 130 131 rc = spdk_cpuset_parse(core_mask, "[]"); 132 CU_ASSERT(rc < 0); 133 134 rc = spdk_cpuset_parse(core_mask, "[10--11]"); 135 CU_ASSERT(rc < 0); 136 137 rc = spdk_cpuset_parse(core_mask, "[11-10]"); 138 CU_ASSERT(rc < 0); 139 140 rc = spdk_cpuset_parse(core_mask, "[10-11,]"); 141 CU_ASSERT(rc < 0); 142 143 rc = spdk_cpuset_parse(core_mask, "[,10-11]"); 144 CU_ASSERT(rc < 0); 145 146 /* Out of range value */ 147 snprintf(buf, sizeof(buf), "[%d]", SPDK_CPUSET_SIZE + 1); 148 rc = spdk_cpuset_parse(core_mask, buf); 149 CU_ASSERT(rc < 0); 150 151 /* Overflow value (UINT64_MAX * 10) */ 152 rc = spdk_cpuset_parse(core_mask, "[184467440737095516150]"); 153 CU_ASSERT(rc < 0); 154 155 /* Test mask with cores 4-7 and 168-171 set. */ 156 rc = spdk_cpuset_parse(core_mask, "0xF0000000000000000000000000000000000000000F0"); 157 CU_ASSERT(rc == 0); 158 CU_ASSERT(cpuset_check_range(core_mask, 0, 3, false) == 0); 159 CU_ASSERT(cpuset_check_range(core_mask, 4, 7, true) == 0); 160 CU_ASSERT(cpuset_check_range(core_mask, 8, 167, false) == 0); 161 CU_ASSERT(cpuset_check_range(core_mask, 168, 171, true) == 0); 162 CU_ASSERT(cpuset_check_range(core_mask, 172, SPDK_CPUSET_SIZE - 1, false) == 0); 163 164 /* Test masks with commas. The commas should be ignored by cpuset, to 165 * allow using spdk_cpuset_parse() with Linux kernel sysfs strings 166 * that insert commas for readability purposes. 167 */ 168 rc = spdk_cpuset_parse(core_mask, "FF,FF0000FF,00000000"); 169 CU_ASSERT(rc == 0); 170 CU_ASSERT(cpuset_check_range(core_mask, 0, 31, false) == 0); 171 CU_ASSERT(cpuset_check_range(core_mask, 32, 39, true) == 0); 172 CU_ASSERT(cpuset_check_range(core_mask, 40, 55, false) == 0); 173 CU_ASSERT(cpuset_check_range(core_mask, 56, 71, true) == 0); 174 CU_ASSERT(cpuset_check_range(core_mask, 72, SPDK_CPUSET_SIZE - 1, false) == 0); 175 176 /* Test masks with random commas. We just ignore the commas, cpuset 177 * should not try to validate that commas are only in certain positions. 178 */ 179 rc = spdk_cpuset_parse(core_mask, ",,,,,000,,1,0,0,,,,"); 180 CU_ASSERT(rc == 0); 181 CU_ASSERT(cpuset_check_range(core_mask, 0, 7, false) == 0); 182 CU_ASSERT(cpuset_check_range(core_mask, 8, 8, true) == 0); 183 CU_ASSERT(cpuset_check_range(core_mask, 9, SPDK_CPUSET_SIZE - 1, false) == 0); 184 185 spdk_cpuset_free(core_mask); 186 } 187 188 static void 189 test_cpuset_fmt(void) 190 { 191 int i; 192 uint32_t lcore; 193 struct spdk_cpuset *core_mask = spdk_cpuset_alloc(); 194 const char *hex_mask; 195 char hex_mask_ref[SPDK_CPUSET_SIZE / 4 + 1]; 196 197 /* Clear coremask. hex_mask should be "0" */ 198 spdk_cpuset_zero(core_mask); 199 hex_mask = spdk_cpuset_fmt(core_mask); 200 SPDK_CU_ASSERT_FATAL(hex_mask != NULL); 201 CU_ASSERT(strcmp("0", hex_mask) == 0); 202 203 /* Set coremask 0x51234. Result should be "51234" */ 204 spdk_cpuset_zero(core_mask); 205 spdk_cpuset_set_cpu(core_mask, 2, true); 206 spdk_cpuset_set_cpu(core_mask, 4, true); 207 spdk_cpuset_set_cpu(core_mask, 5, true); 208 spdk_cpuset_set_cpu(core_mask, 9, true); 209 spdk_cpuset_set_cpu(core_mask, 12, true); 210 spdk_cpuset_set_cpu(core_mask, 16, true); 211 spdk_cpuset_set_cpu(core_mask, 18, true); 212 hex_mask = spdk_cpuset_fmt(core_mask); 213 SPDK_CU_ASSERT_FATAL(hex_mask != NULL); 214 CU_ASSERT(strcmp("51234", hex_mask) == 0); 215 216 /* Set all cores */ 217 spdk_cpuset_zero(core_mask); 218 CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, false) == 0); 219 220 for (lcore = 0; lcore < SPDK_CPUSET_SIZE; lcore++) { 221 spdk_cpuset_set_cpu(core_mask, lcore, true); 222 } 223 for (i = 0; i < SPDK_CPUSET_SIZE / 4; i++) { 224 hex_mask_ref[i] = 'f'; 225 } 226 hex_mask_ref[SPDK_CPUSET_SIZE / 4] = '\0'; 227 228 /* Check data before format */ 229 CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0); 230 231 hex_mask = spdk_cpuset_fmt(core_mask); 232 SPDK_CU_ASSERT_FATAL(hex_mask != NULL); 233 CU_ASSERT(strcmp(hex_mask_ref, hex_mask) == 0); 234 235 /* Check data integrity after format */ 236 CU_ASSERT(cpuset_check_range(core_mask, 0, SPDK_CPUSET_SIZE - 1, true) == 0); 237 238 spdk_cpuset_free(core_mask); 239 } 240 241 int 242 main(int argc, char **argv) 243 { 244 CU_pSuite suite = NULL; 245 unsigned int num_failures; 246 247 CU_initialize_registry(); 248 249 suite = CU_add_suite("cpuset", NULL, NULL); 250 251 CU_ADD_TEST(suite, test_cpuset); 252 CU_ADD_TEST(suite, test_cpuset_parse); 253 CU_ADD_TEST(suite, test_cpuset_fmt); 254 255 256 num_failures = spdk_ut_run_tests(argc, argv, NULL); 257 258 CU_cleanup_registry(); 259 260 return num_failures; 261 } 262