1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Microsoft Corporation 3 */ 4 5 #include <string.h> 6 7 #include <rte_thread.h> 8 #include <rte_debug.h> 9 10 #include "test.h" 11 12 RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO); 13 14 static uint32_t thread_id_ready; 15 16 static uint32_t 17 thread_main(void *arg) 18 { 19 if (arg != NULL) 20 *(rte_thread_t *)arg = rte_thread_self(); 21 22 __atomic_store_n(&thread_id_ready, 1, __ATOMIC_RELEASE); 23 24 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 1) 25 ; 26 27 return 0; 28 } 29 30 static int 31 test_thread_create_join(void) 32 { 33 rte_thread_t thread_id; 34 rte_thread_t thread_main_id; 35 36 thread_id_ready = 0; 37 RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, &thread_main_id) == 0, 38 "Failed to create thread."); 39 40 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 41 ; 42 43 RTE_TEST_ASSERT(rte_thread_equal(thread_id, thread_main_id) != 0, 44 "Unexpected thread id."); 45 46 __atomic_store_n(&thread_id_ready, 2, __ATOMIC_RELEASE); 47 48 RTE_TEST_ASSERT(rte_thread_join(thread_id, NULL) == 0, 49 "Failed to join thread."); 50 51 return 0; 52 } 53 54 static int 55 test_thread_create_detach(void) 56 { 57 rte_thread_t thread_id; 58 rte_thread_t thread_main_id; 59 60 thread_id_ready = 0; 61 RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, 62 &thread_main_id) == 0, "Failed to create thread."); 63 64 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 65 ; 66 67 RTE_TEST_ASSERT(rte_thread_equal(thread_id, thread_main_id) != 0, 68 "Unexpected thread id."); 69 70 __atomic_store_n(&thread_id_ready, 2, __ATOMIC_RELEASE); 71 72 RTE_TEST_ASSERT(rte_thread_detach(thread_id) == 0, 73 "Failed to detach thread."); 74 75 return 0; 76 } 77 78 static int 79 test_thread_priority(void) 80 { 81 rte_thread_t thread_id; 82 enum rte_thread_priority priority; 83 84 thread_id_ready = 0; 85 RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, NULL) == 0, 86 "Failed to create thread"); 87 88 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 89 ; 90 91 priority = RTE_THREAD_PRIORITY_NORMAL; 92 RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == 0, 93 "Failed to set thread priority"); 94 RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0, 95 "Failed to get thread priority"); 96 RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL, 97 "Priority set mismatches priority get"); 98 99 priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL; 100 #ifndef RTE_EXEC_ENV_WINDOWS 101 RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == ENOTSUP, 102 "Priority set to critical should fail"); 103 RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0, 104 "Failed to get thread priority"); 105 RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL, 106 "Failed set to critical should have retained normal"); 107 #else 108 RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == 0, 109 "Priority set to critical should succeed"); 110 RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0, 111 "Failed to get thread priority"); 112 RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL, 113 "Priority set mismatches priority get"); 114 #endif 115 116 priority = RTE_THREAD_PRIORITY_NORMAL; 117 RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == 0, 118 "Failed to set thread priority"); 119 RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0, 120 "Failed to get thread priority"); 121 RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL, 122 "Priority set mismatches priority get"); 123 124 __atomic_store_n(&thread_id_ready, 2, __ATOMIC_RELEASE); 125 126 return 0; 127 } 128 129 static int 130 test_thread_affinity(void) 131 { 132 rte_thread_t thread_id; 133 rte_cpuset_t cpuset0; 134 rte_cpuset_t cpuset1; 135 136 thread_id_ready = 0; 137 RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, NULL) == 0, 138 "Failed to create thread"); 139 140 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 141 ; 142 143 RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset0) == 0, 144 "Failed to get thread affinity"); 145 RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0, 146 "Failed to get thread affinity"); 147 RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, 148 "Affinity should be stable"); 149 150 size_t i; 151 for (i = 1; i < CPU_SETSIZE; i++) 152 if (CPU_ISSET(i, &cpuset0)) { 153 CPU_ZERO(&cpuset0); 154 CPU_SET(i, &cpuset0); 155 156 break; 157 } 158 RTE_TEST_ASSERT(rte_thread_set_affinity_by_id(thread_id, &cpuset0) == 0, 159 "Failed to set thread affinity"); 160 RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0, 161 "Failed to get thread affinity"); 162 RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, 163 "Affinity should be stable"); 164 165 return 0; 166 } 167 168 static int 169 test_thread_attributes_affinity(void) 170 { 171 rte_thread_t thread_id; 172 rte_thread_attr_t attr; 173 rte_cpuset_t cpuset0; 174 rte_cpuset_t cpuset1; 175 176 RTE_TEST_ASSERT(rte_thread_attr_init(&attr) == 0, 177 "Failed to initialize thread attributes"); 178 179 CPU_ZERO(&cpuset0); 180 RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset0) == 0, 181 "Failed to get thread affinity"); 182 RTE_TEST_ASSERT(rte_thread_attr_set_affinity(&attr, &cpuset0) == 0, 183 "Failed to set thread attributes affinity"); 184 RTE_TEST_ASSERT(rte_thread_attr_get_affinity(&attr, &cpuset1) == 0, 185 "Failed to get thread attributes affinity"); 186 RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, 187 "Affinity should be stable"); 188 189 thread_id_ready = 0; 190 RTE_TEST_ASSERT(rte_thread_create(&thread_id, &attr, thread_main, NULL) == 0, 191 "Failed to create attributes affinity thread."); 192 193 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 194 ; 195 196 RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0, 197 "Failed to get attributes thread affinity"); 198 RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0, 199 "Failed to apply affinity attributes"); 200 201 __atomic_store_n(&thread_id_ready, 2, __ATOMIC_RELEASE); 202 203 return 0; 204 } 205 206 static int 207 test_thread_attributes_priority(void) 208 { 209 rte_thread_t thread_id; 210 rte_thread_attr_t attr; 211 enum rte_thread_priority priority; 212 213 RTE_TEST_ASSERT(rte_thread_attr_init(&attr) == 0, 214 "Failed to initialize thread attributes"); 215 RTE_TEST_ASSERT(rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL) == 0, 216 "Failed to set thread attributes priority"); 217 218 thread_id_ready = 0; 219 RTE_TEST_ASSERT(rte_thread_create(&thread_id, &attr, thread_main, NULL) == 0, 220 "Failed to create attributes priority thread."); 221 222 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 223 ; 224 225 RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0, 226 "Failed to get thread priority"); 227 RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL, 228 "Failed to apply priority attributes"); 229 230 __atomic_store_n(&thread_id_ready, 2, __ATOMIC_RELEASE); 231 232 return 0; 233 } 234 235 static int 236 test_thread_control_create_join(void) 237 { 238 rte_thread_t thread_id; 239 rte_thread_t thread_main_id; 240 241 thread_id_ready = 0; 242 RTE_TEST_ASSERT(rte_thread_create_control(&thread_id, "test_control_threads", 243 NULL, thread_main, &thread_main_id) == 0, 244 "Failed to create thread."); 245 246 while (__atomic_load_n(&thread_id_ready, __ATOMIC_ACQUIRE) == 0) 247 ; 248 249 RTE_TEST_ASSERT(rte_thread_equal(thread_id, thread_main_id) != 0, 250 "Unexpected thread id."); 251 252 __atomic_store_n(&thread_id_ready, 2, __ATOMIC_RELEASE); 253 254 RTE_TEST_ASSERT(rte_thread_join(thread_id, NULL) == 0, 255 "Failed to join thread."); 256 257 return 0; 258 } 259 260 static struct unit_test_suite threads_test_suite = { 261 .suite_name = "threads autotest", 262 .setup = NULL, 263 .teardown = NULL, 264 .unit_test_cases = { 265 TEST_CASE(test_thread_create_join), 266 TEST_CASE(test_thread_create_detach), 267 TEST_CASE(test_thread_affinity), 268 TEST_CASE(test_thread_priority), 269 TEST_CASE(test_thread_attributes_affinity), 270 TEST_CASE(test_thread_attributes_priority), 271 TEST_CASE(test_thread_control_create_join), 272 TEST_CASES_END() 273 } 274 }; 275 276 static int 277 test_threads(void) 278 { 279 return unit_test_suite_runner(&threads_test_suite); 280 } 281 282 REGISTER_TEST_COMMAND(threads_autotest, test_threads); 283