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 26using 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 */ 33HWTEST_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 */ 49HWTEST_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 */ 70HWTEST_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 */ 84HWTEST_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 108pthread_mutex_t g_mtx1 = PTHREAD_MUTEX_INITIALIZER; 109pthread_cond_t g_cond1 = PTHREAD_COND_INITIALIZER; 110 111// pthread_cond_signal 112void *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 124void *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 */ 138HWTEST_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 154pthread_mutex_t g_mtx2 = PTHREAD_MUTEX_INITIALIZER; 155pthread_cond_t g_cond2 = PTHREAD_COND_INITIALIZER; 156 157// pthread_cond_signal 158void *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 169void *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 */ 183HWTEST_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 199pthread_mutex_t g_mtx3 = PTHREAD_MUTEX_INITIALIZER; 200pthread_cond_t g_cond3 = PTHREAD_COND_INITIALIZER; 201 202// pthread_cond_broadcast 203void *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 215void *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 */ 230HWTEST_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 248pthread_mutex_t g_mtx4 = PTHREAD_MUTEX_INITIALIZER; 249pthread_cond_t g_cond4 = PTHREAD_COND_INITIALIZER; 250 251// pthread_cond_signal 252void *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 263void *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 */ 285HWTEST_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 302pthread_mutex_t g_mtx5 = PTHREAD_MUTEX_INITIALIZER; 303pthread_cond_t g_cond5 = PTHREAD_COND_INITIALIZER; 304 305// pthread_cond_timedwait 306void *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 */ 330HWTEST_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 344pthread_mutex_t g_mtx6 = PTHREAD_MUTEX_INITIALIZER; 345pthread_cond_t g_cond6 = PTHREAD_COND_INITIALIZER; 346 347// pthread_cond_timedwait 348void *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 */ 368HWTEST_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}