104e53de9STyler Retzlaff /* SPDX-License-Identifier: BSD-3-Clause
204e53de9STyler Retzlaff * Copyright (C) 2022 Microsoft Corporation
304e53de9STyler Retzlaff */
404e53de9STyler Retzlaff
504e53de9STyler Retzlaff #include <string.h>
604e53de9STyler Retzlaff
704e53de9STyler Retzlaff #include <rte_thread.h>
804e53de9STyler Retzlaff #include <rte_debug.h>
9*b6a7e685STyler Retzlaff #include <rte_stdatomic.h>
1004e53de9STyler Retzlaff
1104e53de9STyler Retzlaff #include "test.h"
1204e53de9STyler Retzlaff
1304e53de9STyler Retzlaff RTE_LOG_REGISTER(threads_logtype_test, test.threads, INFO);
1404e53de9STyler Retzlaff
15*b6a7e685STyler Retzlaff static RTE_ATOMIC(uint32_t) thread_id_ready;
1604e53de9STyler Retzlaff
17e1d35c15STyler Retzlaff static uint32_t
thread_main(void * arg)1804e53de9STyler Retzlaff thread_main(void *arg)
1904e53de9STyler Retzlaff {
20e1d35c15STyler Retzlaff if (arg != NULL)
2104e53de9STyler Retzlaff *(rte_thread_t *)arg = rte_thread_self();
22e1d35c15STyler Retzlaff
23*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 1, rte_memory_order_release);
2404e53de9STyler Retzlaff
25*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 1)
261f16100dSTyler Retzlaff ;
271f16100dSTyler Retzlaff
28e1d35c15STyler Retzlaff return 0;
29e1d35c15STyler Retzlaff }
30e1d35c15STyler Retzlaff
31e1d35c15STyler Retzlaff static int
test_thread_create_join(void)32e1d35c15STyler Retzlaff test_thread_create_join(void)
33e1d35c15STyler Retzlaff {
34e1d35c15STyler Retzlaff rte_thread_t thread_id;
35e1d35c15STyler Retzlaff rte_thread_t thread_main_id;
36e1d35c15STyler Retzlaff
37e1d35c15STyler Retzlaff thread_id_ready = 0;
38e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, &thread_main_id) == 0,
39e1d35c15STyler Retzlaff "Failed to create thread.");
40e1d35c15STyler Retzlaff
41*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
42e1d35c15STyler Retzlaff ;
43e1d35c15STyler Retzlaff
44e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_equal(thread_id, thread_main_id) != 0,
45e1d35c15STyler Retzlaff "Unexpected thread id.");
46e1d35c15STyler Retzlaff
47*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 2, rte_memory_order_release);
48e1d35c15STyler Retzlaff
49e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_join(thread_id, NULL) == 0,
50e1d35c15STyler Retzlaff "Failed to join thread.");
51e1d35c15STyler Retzlaff
52e1d35c15STyler Retzlaff return 0;
53e1d35c15STyler Retzlaff }
54e1d35c15STyler Retzlaff
55e1d35c15STyler Retzlaff static int
test_thread_create_detach(void)56e1d35c15STyler Retzlaff test_thread_create_detach(void)
57e1d35c15STyler Retzlaff {
58e1d35c15STyler Retzlaff rte_thread_t thread_id;
59e1d35c15STyler Retzlaff rte_thread_t thread_main_id;
60e1d35c15STyler Retzlaff
61e1d35c15STyler Retzlaff thread_id_ready = 0;
62e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main,
63e1d35c15STyler Retzlaff &thread_main_id) == 0, "Failed to create thread.");
64e1d35c15STyler Retzlaff
65*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
66e1d35c15STyler Retzlaff ;
67e1d35c15STyler Retzlaff
68e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_equal(thread_id, thread_main_id) != 0,
69e1d35c15STyler Retzlaff "Unexpected thread id.");
70e1d35c15STyler Retzlaff
71*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 2, rte_memory_order_release);
72e1d35c15STyler Retzlaff
73e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_detach(thread_id) == 0,
74e1d35c15STyler Retzlaff "Failed to detach thread.");
75e1d35c15STyler Retzlaff
76e1d35c15STyler Retzlaff return 0;
7704e53de9STyler Retzlaff }
7804e53de9STyler Retzlaff
7904e53de9STyler Retzlaff static int
test_thread_priority(void)801f16100dSTyler Retzlaff test_thread_priority(void)
811f16100dSTyler Retzlaff {
821f16100dSTyler Retzlaff rte_thread_t thread_id;
831f16100dSTyler Retzlaff enum rte_thread_priority priority;
841f16100dSTyler Retzlaff
851f16100dSTyler Retzlaff thread_id_ready = 0;
86e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, NULL) == 0,
871f16100dSTyler Retzlaff "Failed to create thread");
881f16100dSTyler Retzlaff
89*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
901f16100dSTyler Retzlaff ;
911f16100dSTyler Retzlaff
921f16100dSTyler Retzlaff priority = RTE_THREAD_PRIORITY_NORMAL;
931f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == 0,
941f16100dSTyler Retzlaff "Failed to set thread priority");
951f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0,
961f16100dSTyler Retzlaff "Failed to get thread priority");
971f16100dSTyler Retzlaff RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL,
981f16100dSTyler Retzlaff "Priority set mismatches priority get");
991f16100dSTyler Retzlaff
1001f16100dSTyler Retzlaff priority = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
1011f16100dSTyler Retzlaff #ifndef RTE_EXEC_ENV_WINDOWS
1021f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == ENOTSUP,
1031f16100dSTyler Retzlaff "Priority set to critical should fail");
1041f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0,
1051f16100dSTyler Retzlaff "Failed to get thread priority");
1061f16100dSTyler Retzlaff RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL,
1071f16100dSTyler Retzlaff "Failed set to critical should have retained normal");
1081f16100dSTyler Retzlaff #else
1091f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == 0,
1101f16100dSTyler Retzlaff "Priority set to critical should succeed");
1111f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0,
1121f16100dSTyler Retzlaff "Failed to get thread priority");
1131f16100dSTyler Retzlaff RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL,
1141f16100dSTyler Retzlaff "Priority set mismatches priority get");
1151f16100dSTyler Retzlaff #endif
1161f16100dSTyler Retzlaff
1171f16100dSTyler Retzlaff priority = RTE_THREAD_PRIORITY_NORMAL;
1181f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_set_priority(thread_id, priority) == 0,
1191f16100dSTyler Retzlaff "Failed to set thread priority");
1201f16100dSTyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0,
1211f16100dSTyler Retzlaff "Failed to get thread priority");
1221f16100dSTyler Retzlaff RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL,
1231f16100dSTyler Retzlaff "Priority set mismatches priority get");
1241f16100dSTyler Retzlaff
125*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 2, rte_memory_order_release);
1261f16100dSTyler Retzlaff
1271f16100dSTyler Retzlaff return 0;
1281f16100dSTyler Retzlaff }
1291f16100dSTyler Retzlaff
1301f16100dSTyler Retzlaff static int
test_thread_affinity(void)13104e53de9STyler Retzlaff test_thread_affinity(void)
13204e53de9STyler Retzlaff {
13304e53de9STyler Retzlaff rte_thread_t thread_id;
13404e53de9STyler Retzlaff rte_cpuset_t cpuset0;
13504e53de9STyler Retzlaff rte_cpuset_t cpuset1;
13604e53de9STyler Retzlaff
1371f16100dSTyler Retzlaff thread_id_ready = 0;
138e1d35c15STyler Retzlaff RTE_TEST_ASSERT(rte_thread_create(&thread_id, NULL, thread_main, NULL) == 0,
13904e53de9STyler Retzlaff "Failed to create thread");
14004e53de9STyler Retzlaff
141*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
14204e53de9STyler Retzlaff ;
14304e53de9STyler Retzlaff
14404e53de9STyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset0) == 0,
14504e53de9STyler Retzlaff "Failed to get thread affinity");
14604e53de9STyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0,
14704e53de9STyler Retzlaff "Failed to get thread affinity");
14804e53de9STyler Retzlaff RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0,
14904e53de9STyler Retzlaff "Affinity should be stable");
15004e53de9STyler Retzlaff
15104e53de9STyler Retzlaff size_t i;
15204e53de9STyler Retzlaff for (i = 1; i < CPU_SETSIZE; i++)
15304e53de9STyler Retzlaff if (CPU_ISSET(i, &cpuset0)) {
15404e53de9STyler Retzlaff CPU_ZERO(&cpuset0);
15504e53de9STyler Retzlaff CPU_SET(i, &cpuset0);
15604e53de9STyler Retzlaff
15704e53de9STyler Retzlaff break;
15804e53de9STyler Retzlaff }
15904e53de9STyler Retzlaff RTE_TEST_ASSERT(rte_thread_set_affinity_by_id(thread_id, &cpuset0) == 0,
16004e53de9STyler Retzlaff "Failed to set thread affinity");
16104e53de9STyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0,
16204e53de9STyler Retzlaff "Failed to get thread affinity");
16304e53de9STyler Retzlaff RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0,
16404e53de9STyler Retzlaff "Affinity should be stable");
16504e53de9STyler Retzlaff
16604e53de9STyler Retzlaff return 0;
16704e53de9STyler Retzlaff }
16804e53de9STyler Retzlaff
1694cba3e11STyler Retzlaff static int
test_thread_attributes_affinity(void)1704cba3e11STyler Retzlaff test_thread_attributes_affinity(void)
1714cba3e11STyler Retzlaff {
1724cba3e11STyler Retzlaff rte_thread_t thread_id;
1734cba3e11STyler Retzlaff rte_thread_attr_t attr;
1744cba3e11STyler Retzlaff rte_cpuset_t cpuset0;
1754cba3e11STyler Retzlaff rte_cpuset_t cpuset1;
1764cba3e11STyler Retzlaff
1774cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_attr_init(&attr) == 0,
1784cba3e11STyler Retzlaff "Failed to initialize thread attributes");
1794cba3e11STyler Retzlaff
1804cba3e11STyler Retzlaff CPU_ZERO(&cpuset0);
1814cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset0) == 0,
1824cba3e11STyler Retzlaff "Failed to get thread affinity");
1834cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_attr_set_affinity(&attr, &cpuset0) == 0,
1844cba3e11STyler Retzlaff "Failed to set thread attributes affinity");
1854cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_attr_get_affinity(&attr, &cpuset1) == 0,
1864cba3e11STyler Retzlaff "Failed to get thread attributes affinity");
1874cba3e11STyler Retzlaff RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0,
1884cba3e11STyler Retzlaff "Affinity should be stable");
1894cba3e11STyler Retzlaff
1904cba3e11STyler Retzlaff thread_id_ready = 0;
1914cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_create(&thread_id, &attr, thread_main, NULL) == 0,
1924cba3e11STyler Retzlaff "Failed to create attributes affinity thread.");
1934cba3e11STyler Retzlaff
194*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
1954cba3e11STyler Retzlaff ;
1964cba3e11STyler Retzlaff
1974cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_affinity_by_id(thread_id, &cpuset1) == 0,
1984cba3e11STyler Retzlaff "Failed to get attributes thread affinity");
1994cba3e11STyler Retzlaff RTE_TEST_ASSERT(memcmp(&cpuset0, &cpuset1, sizeof(rte_cpuset_t)) == 0,
2004cba3e11STyler Retzlaff "Failed to apply affinity attributes");
2014cba3e11STyler Retzlaff
202*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 2, rte_memory_order_release);
2034cba3e11STyler Retzlaff
2044cba3e11STyler Retzlaff return 0;
2054cba3e11STyler Retzlaff }
2064cba3e11STyler Retzlaff
2074cba3e11STyler Retzlaff static int
test_thread_attributes_priority(void)2084cba3e11STyler Retzlaff test_thread_attributes_priority(void)
2094cba3e11STyler Retzlaff {
2104cba3e11STyler Retzlaff rte_thread_t thread_id;
2114cba3e11STyler Retzlaff rte_thread_attr_t attr;
2124cba3e11STyler Retzlaff enum rte_thread_priority priority;
2134cba3e11STyler Retzlaff
2144cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_attr_init(&attr) == 0,
2154cba3e11STyler Retzlaff "Failed to initialize thread attributes");
2164cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_attr_set_priority(&attr, RTE_THREAD_PRIORITY_NORMAL) == 0,
2174cba3e11STyler Retzlaff "Failed to set thread attributes priority");
2184cba3e11STyler Retzlaff
2194cba3e11STyler Retzlaff thread_id_ready = 0;
2204cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_create(&thread_id, &attr, thread_main, NULL) == 0,
2214cba3e11STyler Retzlaff "Failed to create attributes priority thread.");
2224cba3e11STyler Retzlaff
223*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
2244cba3e11STyler Retzlaff ;
2254cba3e11STyler Retzlaff
2264cba3e11STyler Retzlaff RTE_TEST_ASSERT(rte_thread_get_priority(thread_id, &priority) == 0,
2274cba3e11STyler Retzlaff "Failed to get thread priority");
2284cba3e11STyler Retzlaff RTE_TEST_ASSERT(priority == RTE_THREAD_PRIORITY_NORMAL,
2294cba3e11STyler Retzlaff "Failed to apply priority attributes");
2304cba3e11STyler Retzlaff
231*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 2, rte_memory_order_release);
2324cba3e11STyler Retzlaff
2334cba3e11STyler Retzlaff return 0;
2344cba3e11STyler Retzlaff }
2354cba3e11STyler Retzlaff
236878b7468STyler Retzlaff static int
test_thread_control_create_join(void)237878b7468STyler Retzlaff test_thread_control_create_join(void)
238878b7468STyler Retzlaff {
239878b7468STyler Retzlaff rte_thread_t thread_id;
240878b7468STyler Retzlaff rte_thread_t thread_main_id;
241878b7468STyler Retzlaff
242878b7468STyler Retzlaff thread_id_ready = 0;
24362774b78SThomas Monjalon RTE_TEST_ASSERT(rte_thread_create_control(&thread_id, "dpdk-test-thcc",
24470d19787SThomas Monjalon thread_main, &thread_main_id) == 0,
245878b7468STyler Retzlaff "Failed to create thread.");
246878b7468STyler Retzlaff
247*b6a7e685STyler Retzlaff while (rte_atomic_load_explicit(&thread_id_ready, rte_memory_order_acquire) == 0)
248878b7468STyler Retzlaff ;
249878b7468STyler Retzlaff
250878b7468STyler Retzlaff RTE_TEST_ASSERT(rte_thread_equal(thread_id, thread_main_id) != 0,
251878b7468STyler Retzlaff "Unexpected thread id.");
252878b7468STyler Retzlaff
253*b6a7e685STyler Retzlaff rte_atomic_store_explicit(&thread_id_ready, 2, rte_memory_order_release);
254878b7468STyler Retzlaff
255878b7468STyler Retzlaff RTE_TEST_ASSERT(rte_thread_join(thread_id, NULL) == 0,
256878b7468STyler Retzlaff "Failed to join thread.");
257878b7468STyler Retzlaff
258878b7468STyler Retzlaff return 0;
259878b7468STyler Retzlaff }
260878b7468STyler Retzlaff
26104e53de9STyler Retzlaff static struct unit_test_suite threads_test_suite = {
26204e53de9STyler Retzlaff .suite_name = "threads autotest",
26304e53de9STyler Retzlaff .setup = NULL,
26404e53de9STyler Retzlaff .teardown = NULL,
26504e53de9STyler Retzlaff .unit_test_cases = {
266e1d35c15STyler Retzlaff TEST_CASE(test_thread_create_join),
267e1d35c15STyler Retzlaff TEST_CASE(test_thread_create_detach),
26804e53de9STyler Retzlaff TEST_CASE(test_thread_affinity),
2691f16100dSTyler Retzlaff TEST_CASE(test_thread_priority),
2704cba3e11STyler Retzlaff TEST_CASE(test_thread_attributes_affinity),
2714cba3e11STyler Retzlaff TEST_CASE(test_thread_attributes_priority),
272878b7468STyler Retzlaff TEST_CASE(test_thread_control_create_join),
27304e53de9STyler Retzlaff TEST_CASES_END()
27404e53de9STyler Retzlaff }
27504e53de9STyler Retzlaff };
27604e53de9STyler Retzlaff
27704e53de9STyler Retzlaff static int
test_threads(void)27804e53de9STyler Retzlaff test_threads(void)
27904e53de9STyler Retzlaff {
28004e53de9STyler Retzlaff return unit_test_suite_runner(&threads_test_suite);
28104e53de9STyler Retzlaff }
28204e53de9STyler Retzlaff
283e0a8442cSBruce Richardson REGISTER_FAST_TEST(threads_autotest, true, true, test_threads);
284