1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include "it_pthread_test.h"
32
33 static int g_currThreadPri, g_currThreadPolicy;
34 static volatile int g_pthreadTestCount = 0;
35 static volatile int g_threadTestCount1 = 0;
36 static pthread_spinlock_t g_spinTestLock;
37
ThreadFunc8(void * arg)38 static void *ThreadFunc8(void *arg)
39 {
40 pthread_t pthread = pthread_self();
41 int ret;
42
43 ret = pthread_detach(pthread);
44 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
45
46 ret = pthread_spin_lock(&g_spinTestLock);
47 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
48 g_threadTestCount1++;
49 ret = pthread_spin_unlock(&g_spinTestLock);
50 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
51
52 EXIT:
53 return NULL;
54 }
55
ThreadFunc7(void * arg)56 static void *ThreadFunc7(void *arg)
57 {
58 pthread_t pthread = pthread_self();
59 int ret;
60 pthread_attr_t a = { 0 };
61 struct sched_param param = { 0 };
62 pthread_t newPthread;
63 int curThreadPri, curThreadPolicy;
64
65 ret = pthread_detach(pthread);
66 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
67
68 ret = pthread_getschedparam(pthread_self(), &curThreadPolicy, ¶m);
69 ICUNIT_GOTO_EQUAL(ret, 0, -ret, EXIT);
70
71 curThreadPri = param.sched_priority;
72
73 ret = pthread_attr_init(&a);
74 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
75 param.sched_priority = curThreadPri;
76 pthread_attr_setschedparam(&a, ¶m);
77 ret = pthread_create(&newPthread, &a, ThreadFunc8, 0);
78 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
79
80 ret = pthread_spin_lock(&g_spinTestLock);
81 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
82 g_threadTestCount1++;
83 ret = pthread_spin_unlock(&g_spinTestLock);
84 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
85
86 sleep(2); // 2, delay
87 EXIT:
88 return NULL;
89 }
90
ThreadFunc5(void * arg)91 static void *ThreadFunc5(void *arg)
92 {
93 pthread_attr_t a = { 0 };
94 struct sched_param param = { 0 };
95 int ret;
96 void *res = NULL;
97 pthread_t newPthread;
98 int curThreadPri, curThreadPolicy;
99
100 ret = pthread_detach(pthread_self());
101 ICUNIT_GOTO_EQUAL(ret, EINVAL, ret, EXIT);
102
103 ret = pthread_getschedparam(pthread_self(), &curThreadPolicy, ¶m);
104 ICUNIT_GOTO_EQUAL(ret, 0, -ret, EXIT);
105
106 curThreadPri = param.sched_priority;
107
108 ret = pthread_attr_init(&a);
109 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
110 param.sched_priority = curThreadPri + 1;
111 pthread_attr_setschedparam(&a, ¶m);
112 ret = pthread_create(&newPthread, &a, ThreadFunc7, 0);
113 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
114
115 ret = pthread_join(newPthread, &res);
116 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
117
118 ret = pthread_spin_lock(&g_spinTestLock);
119 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
120 g_threadTestCount1++;
121 ret = pthread_spin_unlock(&g_spinTestLock);
122 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
123
124 EXIT:
125 return NULL;
126 }
127
ThreadFunc6(void * arg)128 static void *ThreadFunc6(void *arg)
129 {
130 pthread_t pthread = pthread_self();
131
132 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 12, g_pthreadTestCount, EXIT); // 12, here assert the result.
133 g_pthreadTestCount++; // 13
134
135 return (void *)(uintptr_t)pthread;
136
137 EXIT:
138 return NULL;
139 }
140
ThreadFunc4(void * arg)141 static void *ThreadFunc4(void *arg)
142 {
143 pthread_t pthread = pthread_self();
144 int i = 0;
145 unsigned int ret;
146
147 ret = pthread_spin_lock(&g_spinTestLock);
148 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
149 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 9, g_pthreadTestCount, EXIT); // 9, here assert the result.
150 g_pthreadTestCount++; // 10
151 ret = pthread_spin_unlock(&g_spinTestLock);
152 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
153
154 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
155
156 while (1) {
157 pthread_testcancel();
158 if (++i == 5) { // 5, in loop 5, set cancel state.
159 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
160 }
161
162 if (i == 10) { // 10, in loop 10, cancel pthread.
163 ret = pthread_cancel(pthread);
164 }
165 }
166 return (void *)i;
167
168 EXIT:
169 return NULL;
170 }
171
ThreadFunc3(void * arg)172 static void *ThreadFunc3(void *arg)
173 {
174 pthread_t pthread = pthread_self();
175 int i = 0;
176 unsigned int ret;
177
178 ret = pthread_spin_lock(&g_spinTestLock);
179 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
180 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 6, g_pthreadTestCount, EXIT); // 6, here assert the result.
181 g_pthreadTestCount++; // 7
182 ret = pthread_spin_unlock(&g_spinTestLock);
183 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
184
185 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
186
187 while (1) {
188 pthread_testcancel();
189 if (++i == 5) { // 5, in loop 5, set cancel state.
190 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
191 }
192
193 if (i == 10) { // 10, in loop 10, cancel pthread.
194 ret = pthread_cancel(pthread);
195 }
196 }
197
198 ICUNIT_GOTO_EQUAL(i, 10, i, EXIT); // 10, here assert the result.
199 return (void *)i;
200
201 EXIT:
202 return NULL;
203 }
204
threadFunc2(void * arg)205 static void *threadFunc2(void *arg)
206 {
207 unsigned int ret;
208
209 ret = pthread_spin_lock(&g_spinTestLock);
210 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
211 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 3, g_pthreadTestCount, EXIT); // 3, here assert the result.
212 g_pthreadTestCount++;
213 ret = pthread_spin_unlock(&g_spinTestLock);
214 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
215
216 ret = pthread_join(pthread_self(), 0);
217 ICUNIT_GOTO_EQUAL(ret, EINVAL, ret, EXIT);
218
219 ret = pthread_detach(pthread_self());
220 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
221
222 EXIT:
223 return NULL;
224 }
225
threadFunc(void * arg)226 static void *threadFunc(void *arg)
227 {
228 unsigned int ret;
229 void *res = NULL;
230 pthread_attr_t a = { 0 };
231 pthread_t newPthread;
232 struct sched_param param = { 0 };
233
234 ret = pthread_spin_lock(&g_spinTestLock);
235 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
236 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 2, g_pthreadTestCount, EXIT); // 2, here assert the result.
237 g_pthreadTestCount++;
238 ret = pthread_spin_unlock(&g_spinTestLock);
239 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
240
241 ret = pthread_attr_init(&a);
242 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
243 param.sched_priority = g_currThreadPri;
244 pthread_attr_setschedparam(&a, ¶m);
245 ret = pthread_create(&newPthread, &a, threadFunc2, 0);
246 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
247
248 ret = pthread_spin_lock(&g_spinTestLock);
249 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
250 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 4, g_pthreadTestCount, EXIT); // 4, here assert the result.
251 g_pthreadTestCount++; // 5
252 ret = pthread_spin_unlock(&g_spinTestLock);
253 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
254
255 ret = pthread_attr_init(&a);
256 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
257 param.sched_priority = g_currThreadPri + 2; // 2, adjust priority.
258 pthread_attr_setschedparam(&a, ¶m);
259 ret = pthread_create(&newPthread, &a, ThreadFunc3, 0);
260 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
261
262 ret = pthread_spin_lock(&g_spinTestLock);
263 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
264 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 5, g_pthreadTestCount, EXIT); // 5, here assert the result.
265 g_pthreadTestCount++; // 6
266 ret = pthread_spin_unlock(&g_spinTestLock);
267 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
268
269 ret = pthread_join(newPthread, &res);
270 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
271
272 ret = pthread_spin_lock(&g_spinTestLock);
273 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
274 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 7, g_pthreadTestCount, EXIT); // 7, here assert the result.
275 g_pthreadTestCount++; // 8
276 ret = pthread_spin_unlock(&g_spinTestLock);
277 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
278
279 ret = pthread_attr_init(&a);
280 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
281 param.sched_priority = g_currThreadPri + 3; // 3, adjust priority.
282 pthread_attr_setschedparam(&a, ¶m);
283 ret = pthread_create(&newPthread, &a, ThreadFunc4, 0);
284 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
285
286 ret = pthread_spin_lock(&g_spinTestLock);
287 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
288 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 8, g_pthreadTestCount, EXIT); // 8, here assert the result.
289 g_pthreadTestCount++; // 9
290 ret = pthread_spin_unlock(&g_spinTestLock);
291 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
292
293 ret = pthread_join(newPthread, &res);
294 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
295
296 ret = pthread_spin_lock(&g_spinTestLock);
297 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
298 ICUNIT_GOTO_EQUAL(g_pthreadTestCount, 10, g_pthreadTestCount, EXIT); // 10, here assert the result.
299 g_pthreadTestCount++; // 11
300 ret = pthread_spin_unlock(&g_spinTestLock);
301 ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT);
302
303 EXIT:
304 return NULL;
305 }
306
PthreadTest004()307 int PthreadTest004()
308 {
309 int exitCount = 0;
310 struct sched_param param = { 0 };
311 int ret;
312 void *res = NULL;
313 pthread_attr_t a = { 0 };
314 pthread_t newPthread, newPthread1;
315 const int testCount = 5;
316 int count = 5;
317 pthread_spin_init(&g_spinTestLock, 0);
318
319 g_threadTestCount1 = 0;
320 g_pthreadTestCount = 0;
321
322 ret = pthread_getschedparam(pthread_self(), &g_currThreadPolicy, ¶m);
323 ICUNIT_ASSERT_EQUAL(ret, 0, -ret);
324
325 g_currThreadPri = param.sched_priority;
326
327 g_pthreadTestCount++;
328
329 ret = pthread_attr_init(&a);
330 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
331 param.sched_priority = g_currThreadPri + 1;
332 pthread_attr_setschedparam(&a, ¶m);
333 ret = pthread_create(&newPthread, &a, threadFunc, 0);
334 ICUNIT_ASSERT_EQUAL(ret, 0, ret);
335
336 ICUNIT_ASSERT_EQUAL(g_pthreadTestCount, 1, g_pthreadTestCount);
337 g_pthreadTestCount++;
338
339 while (count > 0) {
340 ret = pthread_create(&newPthread1, &a, ThreadFunc5, 0);
341 ICUNIT_ASSERT_EQUAL(ret, 0, ret);
342
343 ret = pthread_detach(newPthread1);
344 ICUNIT_ASSERT_EQUAL(ret, 0, ret);
345 count--;
346 }
347
348 g_threadTestCount1++;
349 ICUNIT_ASSERT_EQUAL(g_threadTestCount1, 1, g_threadTestCount1);
350
351 ret = pthread_join(newPthread, &res);
352 ICUNIT_ASSERT_EQUAL(ret, 0, ret);
353
354 while (g_threadTestCount1 != (1 + (testCount * 3))) { // 3
355 sleep(2); // 2, delay
356 printf("Wait for the concurrent thread to end \n");
357 exitCount++;
358 if (exitCount > 10) { // wait time > 10 * 2s, cancel wait.
359 break;
360 }
361 }
362
363 ICUNIT_ASSERT_EQUAL(g_pthreadTestCount, 11, g_pthreadTestCount); // 11, here assert the result.
364 g_pthreadTestCount++; // 12
365
366 param.sched_priority = g_currThreadPri - 1;
367 pthread_attr_setschedparam(&a, ¶m);
368 ret = pthread_create(&newPthread1, &a, ThreadFunc6, 0);
369 ICUNIT_ASSERT_EQUAL(ret, 0, ret);
370
371 ret = pthread_join(newPthread1, &res);
372 ICUNIT_ASSERT_EQUAL(ret, 0, ret);
373
374 ICUNIT_ASSERT_EQUAL(g_pthreadTestCount, 13, g_pthreadTestCount); // 13, here assert the result.
375 g_pthreadTestCount++; // 14
376
377 ICUNIT_ASSERT_EQUAL(g_pthreadTestCount, 14, g_pthreadTestCount); // 14, here assert the result.
378
379 pthread_spin_destroy(&g_spinTestLock);
380
381 return 0;
382 }
383
ItTestPthread004(void)384 void ItTestPthread004(void)
385 {
386 TEST_ADD_CASE("IT_POSIX_PTHREAD_004", PthreadTest004, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION);
387 }
388