xref: /dpdk/app/test/test_threads.c (revision e0a8442ccd15bafbb7eb150c35331c8e3b828c53)
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_FAST_TEST(threads_autotest, true, true, test_threads);
283