1 /*- 2 * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 #include <sys/cdefs.h> 7 __FBSDID("$FreeBSD$"); 8 9 #include <sys/types.h> 10 #include <sys/stdint.h> 11 #include <sys/sysctl.h> 12 13 #include <errno.h> 14 #include <sched.h> 15 16 #include <atf-c.h> 17 18 static uint32_t maxcpuid; 19 static uint32_t maxcpus; 20 static uint32_t cpus; 21 22 static uint32_t 23 support_getcpus(void) 24 { 25 uint32_t val; 26 size_t sz = sizeof(val); 27 28 ATF_REQUIRE(sysctlbyname("kern.smp.cpus", &val, &sz, NULL, 0) == 0); 29 return (val); 30 } 31 32 static uint32_t 33 support_getmaxcpus(void) 34 { 35 uint32_t val; 36 size_t sz = sizeof(val); 37 38 ATF_REQUIRE(sysctlbyname("kern.smp.maxcpus", &val, &sz, NULL, 0) == 0); 39 return (val); 40 } 41 42 static uint32_t 43 support_getmaxcpuid(void) 44 { 45 cpuset_t *set; 46 int setsize, rv; 47 uint32_t i, id; 48 49 for (i = 1; i < maxcpus; i++) { 50 setsize = CPU_ALLOC_SIZE(i); 51 set = CPU_ALLOC(i); 52 ATF_REQUIRE(set != NULL); 53 CPU_ZERO_S(i, set); 54 rv = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 55 -1, setsize, set); 56 if (rv == 0) { 57 id = __BIT_FLS(i, set) - 1; 58 CPU_FREE(set); 59 break; 60 } 61 CPU_FREE(set); 62 } 63 ATF_REQUIRE(rv == 0); 64 return (id); 65 } 66 67 ATF_TC_WITHOUT_HEAD(test_setinvalidcpu); 68 ATF_TC_BODY(test_setinvalidcpu, tc) 69 { 70 size_t cpusetsize; 71 cpuset_t *set; 72 73 cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 74 set = CPU_ALLOC(maxcpuid + 1); 75 ATF_REQUIRE(set != NULL); 76 CPU_ZERO_S(maxcpuid + 1, set); 77 CPU_SET_S(maxcpuid + 1, maxcpuid + 1, set); 78 CPU_SET_S(maxcpuid - 1, maxcpuid + 1, set); 79 ATF_REQUIRE(sched_setaffinity(0, cpusetsize, set) == 0); 80 CPU_FREE(set); 81 82 cpusetsize = CPU_ALLOC_SIZE(maxcpus + 1); 83 set = CPU_ALLOC(maxcpus + 1); 84 ATF_REQUIRE(set != NULL); 85 CPU_ZERO_S(maxcpus + 1, set); 86 CPU_SET_S(maxcpuid + 1, maxcpus + 1, set); 87 CPU_SET_S(maxcpuid - 1, maxcpus + 1, set); 88 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 89 -1, cpusetsize, set) == -1); 90 ATF_REQUIRE_EQ(errno, EINVAL); 91 CPU_FREE(set); 92 } 93 94 ATF_TC_WITHOUT_HEAD(test_setvalidcpu); 95 ATF_TC_BODY(test_setvalidcpu, tc) 96 { 97 size_t cpusetsize; 98 cpuset_t *set; 99 int cpu; 100 101 ATF_REQUIRE(maxcpuid < maxcpus); 102 cpu = maxcpuid > 1 ? maxcpuid - 1 : 0; 103 104 cpusetsize = CPU_ALLOC_SIZE(maxcpus + 1); 105 set = CPU_ALLOC(maxcpus + 1); 106 ATF_REQUIRE(set != NULL); 107 CPU_ZERO_S(maxcpus + 1, set); 108 CPU_SET_S(cpu, maxcpus + 1, set); 109 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 110 -1, cpusetsize, set) == 0); 111 ATF_REQUIRE_EQ(cpu, sched_getcpu()); 112 CPU_FREE(set); 113 } 114 115 ATF_TC_WITHOUT_HEAD(test_setzeroset1); 116 ATF_TC_BODY(test_setzeroset1, tc) 117 { 118 size_t cpusetsize; 119 cpuset_t *set; 120 121 cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 122 set = CPU_ALLOC(maxcpuid + 1); 123 ATF_REQUIRE(set != NULL); 124 CPU_ZERO_S(maxcpuid + 1, set); 125 ATF_REQUIRE(sched_setaffinity(0, cpusetsize, set) == -1); 126 ATF_REQUIRE_EQ(errno, EINVAL); 127 CPU_FREE(set); 128 } 129 130 ATF_TC_WITHOUT_HEAD(test_setzeroset2); 131 ATF_TC_BODY(test_setzeroset2, tc) 132 { 133 size_t cpusetsize; 134 cpuset_t *set; 135 136 cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 137 set = CPU_ALLOC(maxcpuid + 1); 138 ATF_REQUIRE(set != NULL); 139 CPU_ZERO_S(maxcpuid + 1, set); 140 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 141 -1, cpusetsize, set) == -1); 142 ATF_REQUIRE_EQ(errno, EDEADLK); 143 CPU_FREE(set); 144 } 145 146 ATF_TC_WITHOUT_HEAD(test_setmaxsetsize); 147 ATF_TC_BODY(test_setmaxsetsize, tc) 148 { 149 size_t cpusetsize; 150 cpuset_t *set; 151 152 cpusetsize = CPU_ALLOC_SIZE(maxcpus * 2); 153 set = CPU_ALLOC(maxcpus * 2); 154 ATF_REQUIRE(set != NULL); 155 CPU_ZERO_S(maxcpus * 2, set); 156 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 0); 157 CPU_SET_S(0, maxcpus * 2, set); 158 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 1); 159 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 160 -1, cpusetsize, set) == 0); 161 162 CPU_ZERO_S(maxcpus * 2, set); 163 CPU_SET_S(maxcpuid, maxcpus * 2, set); 164 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 165 -1, cpusetsize, set) == 0); 166 167 CPU_ZERO_S(maxcpus * 2, set); 168 CPU_SET_S(maxcpuid + 1, maxcpus * 2, set); 169 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 170 -1, cpusetsize, set) == -1); 171 ATF_REQUIRE_EQ(errno, EINVAL); 172 CPU_FREE(set); 173 } 174 175 ATF_TC_WITHOUT_HEAD(test_setminsetsize); 176 ATF_TC_BODY(test_setminsetsize, tc) 177 { 178 size_t cpusetsize = 1; 179 int8_t set; 180 181 if (cpus <= 8) 182 return; 183 184 set = 1; 185 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 186 -1, cpusetsize, (const cpuset_t *)&set) == 0); 187 set = 0; 188 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 189 -1, cpusetsize, (const cpuset_t *)&set) == -1); 190 ATF_REQUIRE_EQ(errno, EDEADLK); 191 } 192 193 ATF_TC_WITHOUT_HEAD(test_getminsetsize); 194 ATF_TC_BODY(test_getminsetsize, tc) 195 { 196 size_t cpusetsize = 1; 197 int8_t set = 0; 198 199 if (cpus < 9) 200 return; 201 ATF_REQUIRE(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 202 -1, cpusetsize, (cpuset_t *)&set) == -1); 203 ATF_REQUIRE_EQ(errno, ERANGE); 204 } 205 206 ATF_TC_WITHOUT_HEAD(test_getsetsize); 207 ATF_TC_BODY(test_getsetsize, tc) 208 { 209 size_t cpusetsize; 210 cpuset_t *set; 211 212 cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 213 set = CPU_ALLOC(maxcpuid + 1); 214 ATF_REQUIRE(set != NULL); 215 CPU_ZERO_S(maxcpuid + 1, set); 216 ATF_REQUIRE(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 217 -1, cpusetsize, set) == 0); 218 CPU_FREE(set); 219 } 220 221 ATF_TC_WITHOUT_HEAD(test_holes); 222 ATF_TC_BODY(test_holes, tc) 223 { 224 cpuset_t *set; 225 int cpusetsize; 226 227 cpusetsize = CPU_ALLOC_SIZE(maxcpus * 2); 228 set = CPU_ALLOC(maxcpus * 2); 229 ATF_REQUIRE(set != NULL); 230 CPU_ZERO_S(maxcpus * 2, set); 231 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 0); 232 CPU_SET_S(maxcpuid, maxcpus * 2, set); 233 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 1); 234 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 235 -1, cpusetsize, set) == 0); 236 237 CPU_ZERO_S(maxcpus * 2, set); 238 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 0); 239 CPU_SET_S(maxcpuid + 1, maxcpus * 2, set); 240 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 1); 241 ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 242 -1, cpusetsize, set) == -1); 243 ATF_REQUIRE_EQ(errno, EINVAL); 244 245 ATF_REQUIRE(CPU_COUNT_S(maxcpus * 2, set) == 1); 246 ATF_REQUIRE(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 247 -1, cpusetsize, set) == 0); 248 ATF_REQUIRE(CPU_ISSET_S(maxcpuid + 1, maxcpus * 2, set) == false); 249 ATF_REQUIRE(CPU_ISSET_S(maxcpuid, maxcpus * 2, set) == true); 250 ATF_REQUIRE_EQ(maxcpuid, (uint32_t)sched_getcpu()); 251 } 252 253 ATF_TP_ADD_TCS(tp) 254 { 255 256 cpus = support_getcpus(); 257 maxcpus = support_getmaxcpus(); 258 maxcpuid = support_getmaxcpuid(); 259 260 ATF_TP_ADD_TC(tp, test_setinvalidcpu); 261 ATF_TP_ADD_TC(tp, test_setvalidcpu); 262 ATF_TP_ADD_TC(tp, test_setzeroset1); 263 ATF_TP_ADD_TC(tp, test_setzeroset2); 264 265 ATF_TP_ADD_TC(tp, test_setminsetsize); 266 ATF_TP_ADD_TC(tp, test_setmaxsetsize); 267 268 ATF_TP_ADD_TC(tp, test_getminsetsize); 269 ATF_TP_ADD_TC(tp, test_getsetsize); 270 271 ATF_TP_ADD_TC(tp, test_holes); 272 273 return (atf_no_error()); 274 } 275