xref: /dpdk/app/test/test_threads.c (revision b6a7e6852e9ab82ae0e05e2d2a0b83abca17de3b)
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
thread_main(void * arg)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
test_thread_create_join(void)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
test_thread_create_detach(void)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
test_thread_priority(void)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
test_thread_affinity(void)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
test_thread_attributes_affinity(void)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
test_thread_attributes_priority(void)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
test_thread_control_create_join(void)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
test_threads(void)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