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