• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }