1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <stdio.h>
16 #include <string.h>
17 #include <limits.h>
18 #include <pthread.h>
19 #include <gtest/gtest.h>
20 #include "utils.h"
21 #include "log.h"
22 #include "KernelConstants.h"
23 #include "FutexTest.h"
24 #include "mt_utils.h"
25
26 using namespace testing::ext;
27
28 /**
29 * @tc.number SUB_KERNEL_PTHREAD_COND_INIT_0100
30 * @tc.name pthread_cond_init initializes condition variables
31 * @tc.desc [C- SOFTWARE -0200]
32 */
33 HWTEST_F(FutexTest, testPthreadCondInit, Function | MediumTest | Level2)
34 {
35 pthread_condattr_t condattr;
36 EXPECT_EQ(pthread_condattr_init(&condattr), 0);
37 pthread_cond_t cond1;
38 EXPECT_EQ(pthread_cond_init(&cond1, &condattr), 0);
39
40 pthread_cond_t cond2;
41 EXPECT_EQ(pthread_cond_init(&cond2, nullptr), 0);
42 }
43
44 /**
45 * @tc.number SUB_KERNEL_PTHREAD_COND_DESTROY_0100
46 * @tc.name pthread_cond_destroy destroy condition variables
47 * @tc.desc [C- SOFTWARE -0200]
48 */
49 HWTEST_F(FutexTest, testPthreadCondDestroy, Function | MediumTest | Level3)
50 {
51 pthread_condattr_t condattr;
52 EXPECT_EQ(pthread_condattr_init(&condattr), 0);
53 pthread_cond_t cond1;
54 EXPECT_EQ(pthread_cond_init(&cond1, &condattr), 0);
55 EXPECT_EQ(pthread_cond_destroy(&cond1), 0);
56
57 pthread_cond_t cond2;
58 EXPECT_EQ(pthread_cond_init(&cond2, nullptr), 0);
59 EXPECT_EQ(pthread_cond_destroy(&cond2), 0);
60
61 pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
62 EXPECT_EQ(pthread_cond_destroy(&cond3), 0);
63 }
64
65 /**
66 * @tc.number SUB_KERNEL_PTHREAD_CONDATTR_INIT_0100
67 * @tc.name Init and destroy operations
68 * @tc.desc [C- SOFTWARE -0200]
69 */
70 HWTEST_F(FutexTest, testPthreadCondattrInit, Function | MediumTest | Level2)
71 {
72 pthread_condattr_t condattr;
73
74 EXPECT_EQ(pthread_condattr_init(&condattr), 0) << "> return errno";
75 EXPECT_EQ(pthread_condattr_destroy(&condattr), 0) << "> return errno";
76 EXPECT_EQ(pthread_condattr_init(&condattr), 0) << "> return errno";
77 }
78
79 /**
80 * @tc.number SUB_KERNEL_PTHREAD_CONDATTR_SETCLOCK_0100
81 * @tc.name Set and get the clock selection variable properties of the condition variable properties
82 * @tc.desc [C- SOFTWARE -0200]
83 */
84 HWTEST_F(FutexTest, testPthreadCondattrSetclock, Function | MediumTest | Level3)
85 {
86 clockid_t clk;
87 const int invalidClock = -100;
88 pthread_condattr_t condattr;
89 EXPECT_EQ(pthread_condattr_init(&condattr), 0);
90
91 // default
92 EXPECT_EQ(pthread_condattr_getclock(&condattr, &clk), 0) << "> return errno";
93 EXPECT_EQ(clk, DEF_PROCESS_CONDATTR_CLOCK);
94
95 EXPECT_EQ(pthread_condattr_setclock(&condattr, CLOCK_REALTIME), 0) << "> return errno";
96 EXPECT_EQ(pthread_condattr_getclock(&condattr, &clk), 0) << "> return errno";
97 EXPECT_EQ(clk, CLOCK_REALTIME);
98
99 struct timespec ts = {0};
100 EXPECT_EQ(clock_getres(CLOCK_MONOTONIC, &ts), 0) << "> return errno";
101 EXPECT_EQ(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC), 0) << "> return errno";
102 EXPECT_EQ(pthread_condattr_getclock(&condattr, &clk), 0) << "> return errno";
103 EXPECT_EQ(clk, CLOCK_MONOTONIC);
104
105 EXPECT_EQ(pthread_condattr_setclock(&condattr, invalidClock), EINVAL) << "> return errno";
106 }
107
108 pthread_mutex_t g_mtx1 = PTHREAD_MUTEX_INITIALIZER;
109 pthread_cond_t g_cond1 = PTHREAD_COND_INITIALIZER;
110
111 // pthread_cond_signal
ThreadPthreadCondSignalBefore1(void * arg)112 void *ThreadPthreadCondSignalBefore1(void *arg)
113 {
114 Msleep(20);
115 EXPECT_EQ(pthread_mutex_lock(&g_mtx1), 0);
116 LOG("step = %lx", CheckStep(2));
117 EXPECT_EQ(pthread_cond_signal(&g_cond1), 0);
118 LOG("step = %lx", CheckStep(3));
119 EXPECT_EQ(pthread_mutex_unlock(&g_mtx1), 0);
120 return arg;
121 }
122
123 // pthread_cond_wait
ThreadPthreadCondSignalBefore2(void * arg)124 void *ThreadPthreadCondSignalBefore2(void *arg)
125 {
126 EXPECT_EQ(pthread_mutex_lock(&g_mtx1), 0);
127 EXPECT_EQ(pthread_cond_wait(&g_cond1, &g_mtx1), 0);
128 LOG("step = %lx", CheckStep(4));
129 EXPECT_EQ(pthread_mutex_unlock(&g_mtx1), 0);
130 return arg;
131 }
132
133 /**
134 * @tc.number SUB_KERNEL_PTHREAD_COND_SIGNAL_0100
135 * @tc.name Use pthread_cond_signal to release the conditional semaphore, pthread_cond_signal front
136 * @tc.desc [C- SOFTWARE -0200]
137 */
138 HWTEST_F(FutexTest, testPthreadCondSignalBefore, Function | MediumTest | Level3)
139 {
140 pthread_t tid[2];
141 LOG("step = %lx", CheckStep(1));
142
143 ASSERT_EQ(pthread_create(&tid[0], nullptr, ThreadPthreadCondSignalBefore1, nullptr), 0) << "> return errno";
144 ASSERT_EQ(pthread_create(&tid[1], nullptr, ThreadPthreadCondSignalBefore2, nullptr), 0) << "> return errno";
145
146 Msleep(100);
147 pthread_join(tid[0], nullptr);
148 pthread_join(tid[1], nullptr);
149 EXPECT_EQ(pthread_cond_destroy(&g_cond1), 0);
150 EXPECT_EQ(pthread_mutex_destroy(&g_mtx1), 0);
151 EXPECT_EQ(CheckStep(5), (uint64_t)0x12345);
152 }
153
154 pthread_mutex_t g_mtx2 = PTHREAD_MUTEX_INITIALIZER;
155 pthread_cond_t g_cond2 = PTHREAD_COND_INITIALIZER;
156
157 // pthread_cond_signal
ThreadTestCondSignalWaitAfter1(void * arg)158 void *ThreadTestCondSignalWaitAfter1(void *arg)
159 {
160 Msleep(20);
161 EXPECT_EQ(pthread_mutex_lock(&g_mtx2), 0);
162 LOG("step = %lx", CheckStep(2));
163 EXPECT_EQ(pthread_mutex_unlock(&g_mtx2), 0);
164 EXPECT_EQ(pthread_cond_signal(&g_cond2), 0);
165 return arg;
166 }
167
168 // pthread_cond_wait
ThreadTestCondSignalWaitAfter2(void * arg)169 void *ThreadTestCondSignalWaitAfter2(void *arg)
170 {
171 EXPECT_EQ(pthread_mutex_lock(&g_mtx2), 0);
172 EXPECT_EQ(pthread_cond_wait(&g_cond2, &g_mtx2), 0);
173 LOG("step = %lx", CheckStep(3));
174 EXPECT_EQ(pthread_mutex_unlock(&g_mtx2), 0);
175 return arg;
176 }
177
178 /**
179 * @tc.number SUB_KERNEL_PTHREAD_COND_SIGNAL_0200
180 * @tc.name Use pthread_cond_signal to release the conditional semaphore, pthread_cond_signal in the back
181 * @tc.desc [C- SOFTWARE -0200]
182 */
183 HWTEST_F(FutexTest, testPthreadCondSignalAfter, Function | MediumTest | Level3)
184 {
185 pthread_t tid[2];
186 LOG("step = %lx", CheckStep(1));
187
188 ASSERT_EQ(pthread_create(&tid[0], nullptr, ThreadTestCondSignalWaitAfter1, nullptr), 0) << "> return errno";
189 ASSERT_EQ(pthread_create(&tid[1], nullptr, ThreadTestCondSignalWaitAfter2, nullptr), 0) << "> return errno";
190
191 Msleep(100);
192 pthread_join(tid[0], nullptr);
193 pthread_join(tid[1], nullptr);
194 EXPECT_EQ(pthread_cond_destroy(&g_cond2), 0);
195 EXPECT_EQ(pthread_mutex_destroy(&g_mtx2), 0);
196 EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
197 }
198
199 pthread_mutex_t g_mtx3 = PTHREAD_MUTEX_INITIALIZER;
200 pthread_cond_t g_cond3 = PTHREAD_COND_INITIALIZER;
201
202 // pthread_cond_broadcast
ThreadPthreadCondBroadcast1(void * arg)203 void *ThreadPthreadCondBroadcast1(void *arg)
204 {
205 int *testIntP = (int *)arg;
206 Msleep(20);
207 EXPECT_EQ(pthread_mutex_lock(&g_mtx3), 0);
208 *testIntP = 10;
209 EXPECT_EQ(pthread_cond_broadcast(&g_cond3), 0);
210 EXPECT_EQ(pthread_mutex_unlock(&g_mtx3), 0);
211 return arg;
212 }
213
214 // pthread_cond_wait
ThreadPthreadCondBroadcast2(void * arg)215 void *ThreadPthreadCondBroadcast2(void *arg)
216 {
217 int *testIntP = (int *)arg;
218 EXPECT_EQ(pthread_mutex_lock(&g_mtx3), 0);
219 EXPECT_EQ(pthread_cond_wait(&g_cond3, &g_mtx3), 0);
220 (*testIntP)++;
221 EXPECT_EQ(pthread_mutex_unlock(&g_mtx3), 0);
222 return arg;
223 }
224
225 /**
226 * @tc.number SUB_KERNEL_PTHREAD_COND_BROADCAST_0100
227 * @tc.name Use pthread_cond_broadcast to release conditional semaphore
228 * @tc.desc [C- SOFTWARE -0200]
229 */
230 HWTEST_F(FutexTest, testPthreadCondBroadcast, Function | MediumTest | Level3)
231 {
232 pthread_t tid[3];
233 int testInt = 0;
234
235 ASSERT_EQ(pthread_create(&tid[0], nullptr, ThreadPthreadCondBroadcast1, (void*)&testInt), 0) << "> return errno";
236 ASSERT_EQ(pthread_create(&tid[1], nullptr, ThreadPthreadCondBroadcast2, (void*)&testInt), 0) << "> return errno";
237 ASSERT_EQ(pthread_create(&tid[2], nullptr, ThreadPthreadCondBroadcast2, (void*)&testInt), 0) << "> return errno";
238
239 Msleep(100);
240 pthread_join(tid[0], nullptr);
241 pthread_join(tid[1], nullptr);
242 pthread_join(tid[2], nullptr);
243 EXPECT_EQ(pthread_cond_destroy(&g_cond3), 0);
244 EXPECT_EQ(pthread_mutex_destroy(&g_mtx3), 0);
245 EXPECT_EQ(testInt, 12);
246 }
247
248 pthread_mutex_t g_mtx4 = PTHREAD_MUTEX_INITIALIZER;
249 pthread_cond_t g_cond4 = PTHREAD_COND_INITIALIZER;
250
251 // pthread_cond_signal
ThreadPthreadCondTimedwait1(void * arg)252 void *ThreadPthreadCondTimedwait1(void *arg)
253 {
254 Msleep(50);
255 EXPECT_EQ(pthread_mutex_lock(&g_mtx4), 0);
256 LOG("step = %lx", CheckStep(2));
257 EXPECT_EQ(pthread_mutex_unlock(&g_mtx4), 0);
258 EXPECT_EQ(pthread_cond_signal(&g_cond4), 0);
259 return arg;
260 }
261
262 // pthread_cond_timedwait
ThreadPthreadCondTimedwait2(void * arg)263 void *ThreadPthreadCondTimedwait2(void *arg)
264 {
265 const unsigned int nsecPerSec = 1000000000;
266 const unsigned int nsecPer100Ms = 100000000;
267 struct timespec ts = {0};
268 EXPECT_EQ(pthread_mutex_lock(&g_mtx4), 0);
269
270 clock_gettime(CLOCK_REALTIME, &ts);
271 ts.tv_sec = ts.tv_sec + (ts.tv_nsec + nsecPer100Ms) / nsecPerSec;
272 ts.tv_nsec = (ts.tv_nsec + nsecPer100Ms) % nsecPerSec;
273
274 EXPECT_EQ(pthread_cond_timedwait(&g_cond4, &g_mtx4, &ts), 0);
275 LOG("step = %lx", CheckStep(3));
276 EXPECT_EQ(pthread_mutex_unlock(&g_mtx4), 0);
277 return arg;
278 }
279
280 /**
281 * @tc.number SUB_KERNEL_PTHREAD_COND_TIMEDWAIT_0100
282 * @tc.name Use pthread_cond_timedwait to get conditional semaphore
283 * @tc.desc [C- SOFTWARE -0200]
284 */
285 HWTEST_F(FutexTest, testPthreadCondTimedwait, Function | MediumTest | Level3)
286 {
287 pthread_t tid1;
288 pthread_t tid2;
289 LOG("step = %lx", CheckStep(1));
290
291 ASSERT_EQ(pthread_create(&tid1, nullptr, ThreadPthreadCondTimedwait1, nullptr), 0) << "> return errno";
292 ASSERT_EQ(pthread_create(&tid2, nullptr, ThreadPthreadCondTimedwait2, nullptr), 0) << "> return errno";
293
294 Msleep(100);
295 pthread_join(tid1, nullptr);
296 pthread_join(tid2, nullptr);
297 EXPECT_EQ(pthread_cond_destroy(&g_cond4), 0);
298 EXPECT_EQ(pthread_mutex_destroy(&g_mtx4), 0);
299 EXPECT_EQ(CheckStep(4), (uint64_t)0x1234);
300 }
301
302 pthread_mutex_t g_mtx5 = PTHREAD_MUTEX_INITIALIZER;
303 pthread_cond_t g_cond5 = PTHREAD_COND_INITIALIZER;
304
305 // pthread_cond_timedwait
ThreadPthreadCondTimedwaitOut(void * arg)306 void *ThreadPthreadCondTimedwaitOut(void *arg)
307 {
308 struct timespec ts = {0};
309 struct timespec tsNow = {0};
310 EXPECT_EQ(pthread_mutex_lock(&g_mtx5), 0);
311
312 GetDelayedTime(&ts, 100);
313 EXPECT_EQ(pthread_cond_timedwait(&g_cond5, &g_mtx5, &ts), ETIMEDOUT) << "> return should errno";
314 LOG("step = %lx", CheckStep(2));
315 clock_gettime(CLOCK_REALTIME, &tsNow);
316
317 int timeDiff = GetTimeDiff(tsNow, ts); // calculate time different
318 EXPECT_GE(timeDiff, 0);
319 EXPECT_LE(timeDiff, 20);
320
321 EXPECT_EQ(pthread_mutex_unlock(&g_mtx5), 0);
322 return arg;
323 }
324
325 /**
326 * @tc.number SUB_KERNEL_PTHREAD_COND_TIMEDWAIT_0200
327 * @tc.name Use pthread_cond_timedwait to time out time measurement
328 * @tc.desc [C- SOFTWARE -0200]
329 */
330 HWTEST_F(FutexTest, testPthreadCondTimedwaitOut, Function | MediumTest | Level3)
331 {
332 pthread_t tid;
333 LOG("step = %lx", CheckStep(1));
334
335 ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCondTimedwaitOut, nullptr), 0) << "> return errno";
336
337 Msleep(200);
338 pthread_join(tid, nullptr);
339 EXPECT_EQ(pthread_cond_destroy(&g_cond5), 0);
340 EXPECT_EQ(pthread_mutex_destroy(&g_mtx5), 0);
341 EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
342 }
343
344 pthread_mutex_t g_mtx6 = PTHREAD_MUTEX_INITIALIZER;
345 pthread_cond_t g_cond6 = PTHREAD_COND_INITIALIZER;
346
347 // pthread_cond_timedwait
ThreadPthreadCondTimedwaitEinval(void * arg)348 void *ThreadPthreadCondTimedwaitEinval(void *arg)
349 {
350 const long einvalNsec = 1000000000;
351 struct timespec ts = {0};
352 EXPECT_EQ(pthread_mutex_lock(&g_mtx6), 0);
353
354 ts.tv_sec = 1;
355 ts.tv_nsec = einvalNsec;
356 EXPECT_EQ(pthread_cond_timedwait(&g_cond6, &g_mtx6, &ts), EINVAL) << "> return should errno";
357 CheckStep(2);
358
359 EXPECT_EQ(pthread_mutex_unlock(&g_mtx6), 0);
360 return arg;
361 }
362
363 /**
364 * @tc.number SUB_KERNEL_PTHREAD_COND_TIMEDWAIT_0300
365 * @tc.name test pthread_cond_timedwait EINVAL
366 * @tc.desc [C- SOFTWARE -0200]
367 */
368 HWTEST_F(FutexTest, testPthreadCondTimedwaitEinval, Function | MediumTest | Level3)
369 {
370 pthread_t tid;
371 CheckStep(1);
372
373 ASSERT_EQ(pthread_create(&tid, nullptr, ThreadPthreadCondTimedwaitEinval, nullptr), 0) << "> return errno";
374
375 Msleep(200);
376 pthread_join(tid, nullptr);
377 EXPECT_EQ(pthread_cond_destroy(&g_cond6), 0);
378 EXPECT_EQ(pthread_mutex_destroy(&g_mtx6), 0);
379 EXPECT_EQ(CheckStep(3), (uint64_t)0x123);
380 }