xref: /dpdk/app/test/test_threads.c (revision b6a7e6852e9ab82ae0e05e2d2a0b83abca17de3b)
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