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