• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 
16 #include <mutex>
17 #include <future>
18 #include <chrono>
19 #include <random>
20 #include <gtest/gtest.h>
21 #include "sync/sync.h"
22 #include "ffrt_inner.h"
23 #include "dfx/log/ffrt_log_api.h"
24 #include "c/thread.h"
25 #include "c/ffrt_ipc.h"
26 #include "tm/cpu_task.h"
27 #include "../common.h"
28 
29 extern "C" int ffrt_mutexattr_init(ffrt_mutexattr_t* attr);
30 extern "C" int ffrt_mutexattr_settype(ffrt_mutexattr_t* attr, int type);
31 extern "C" int ffrt_mutexattr_gettype(ffrt_mutexattr_t* attr, int* type);
32 extern "C" int ffrt_mutexattr_destroy(ffrt_mutexattr_t* attr);
33 extern "C" int ffrt_mutex_init(ffrt_mutex_t *mutex, const ffrt_mutexattr_t* attr);
34 extern "C" int ffrt_mutex_lock(ffrt_mutex_t *mutex);
35 extern "C" int ffrt_mutex_unlock(ffrt_mutex_t *mutex);
36 extern "C" int ffrt_mutex_trylock(ffrt_mutex_t *mutex);
37 extern "C" int ffrt_mutex_destroy(ffrt_mutex_t *mutex);
38 
39 using namespace std;
40 using namespace testing;
41 #ifdef HWTEST_TESTING_EXT_ENABLE
42 using namespace testing::ext;
43 #endif
44 
45 class SyncTest : public testing::Test {
46 protected:
SetUpTestCase()47     static void SetUpTestCase()
48     {
49     }
50 
TearDownTestCase()51     static void TearDownTestCase()
52     {
53     }
54 
SetUp()55     void SetUp() override
56     {
57     }
58 
TearDown()59     void TearDown() override
60     {
61     }
62 };
63 
64 /**
65  * @tc.name: mutexattr_nullptr_fail
66  * @tc.desc: Test function of mutexattr when the input is nullptr;
67  * @tc.type: FUNC
68  */
69 HWTEST_F(SyncTest, mutexattr_nullptr_fail, TestSize.Level0)
70 {
71     int ret = ffrt_mutexattr_init(nullptr);
72     EXPECT_EQ(ret, ffrt_error_inval);
73     ret = ffrt_mutexattr_settype(nullptr, 0);
74     EXPECT_EQ(ret, ffrt_error_inval);
75     ret = ffrt_mutexattr_gettype(nullptr, nullptr);
76     EXPECT_EQ(ret, ffrt_error_inval);
77     ret = ffrt_mutexattr_destroy(nullptr);
78     EXPECT_EQ(ret, ffrt_error_inval);
79     ffrt_mutexattr_t attr;
80     int type = ffrt_mutex_default;
81     ffrt_mutexattr_init(&attr);
82     ret = ffrt_mutexattr_settype(&attr, ffrt_mutex_normal);
83     ret = ffrt_mutexattr_settype(&attr, ffrt_mutex_default);
84     ret = ffrt_mutexattr_settype(&attr, -1);
85     EXPECT_EQ(ret, ffrt_error_inval);
86     ret = ffrt_mutexattr_gettype(&attr, nullptr);
87     EXPECT_EQ(ret, ffrt_error_inval);
88     ret = ffrt_mutexattr_gettype(&attr, &type);
89     EXPECT_EQ(ret, ffrt_success);
90     ffrt_mutexattr_destroy(&attr);
91 }
92 
93 /**
94  * @tc.name: mutex_nullptr_fail
95  * @tc.desc: Test function of mutex when the input is nullptr;
96  * @tc.type: FUNC
97  */
98 HWTEST_F(SyncTest, mutex_nullptr_fail, TestSize.Level0)
99 {
100     int ret = ffrt_mutex_init(nullptr, nullptr);
101     EXPECT_EQ(ret, ffrt_error_inval);
102     ret = ffrt_mutex_lock(nullptr);
103     EXPECT_EQ(ret, ffrt_error_inval);
104     ret = ffrt_mutex_unlock(nullptr);
105     EXPECT_EQ(ret, ffrt_error_inval);
106     ret = ffrt_mutex_trylock(nullptr);
107     EXPECT_EQ(ret, ffrt_error_inval);
108     ffrt_mutex_destroy(nullptr);
109 }
110 
111 /**
112  * @tc.name: mutex_try_lock
113  * @tc.desc: Test function of mutex:try_lock
114  * @tc.type: FUNC
115  */
116 HWTEST_F(SyncTest, mutex_try_lock, TestSize.Level0)
117 {
118     int val = -1;
119     ffrt::mutex lock;
120     lock.lock();
121     val = lock.try_lock();
122     EXPECT_EQ(val, 0);
123     lock.unlock();
124     val = lock.try_lock();
125     EXPECT_EQ(val, 1);
126     lock.unlock();
127     lock.unlock();
128 }
129 
130 /**
131  * @tc.name: recursive_mutex_try_lock
132  * @tc.desc: Test function of recursive mutex:try_lock
133  * @tc.type: FUNC
134  */
135 HWTEST_F(SyncTest, recursive_mutex_try_lock, TestSize.Level0)
136 {
137     int val = -1;
138     ffrt::recursive_mutex lock;
139     lock.lock();
140     val = lock.try_lock();
141     EXPECT_EQ(val, 1);
142     lock.unlock();
143     val = lock.try_lock();
144     EXPECT_EQ(val, 1);
145     lock.unlock();
146     lock.unlock();
147 }
148 
149 /**
150  * @tc.name: shared_mutex_try_lock
151  * @tc.desc: Test function of shared mutex:try_lock
152  * @tc.type: FUNC
153  */
154 HWTEST_F(SyncTest, shared_mutex_try_lock, TestSize.Level0)
155 {
156     ffrt::shared_mutex lock;
157     lock.lock_shared();
158     EXPECT_TRUE(lock.try_lock_shared());
159     EXPECT_FALSE(lock.try_lock());
160     lock.unlock_shared();
161     lock.unlock_shared();
162 
163     lock.lock();
164     EXPECT_FALSE(lock.try_lock_shared());
165     EXPECT_FALSE(lock.try_lock());
166     lock.unlock();
167 
168     EXPECT_TRUE(lock.try_lock());
169     lock.unlock();
170 }
171 
172 /**
173  * @tc.name: mutex_lock_with_BlockThread
174  * @tc.desc: Test function of mutex:lock in Thread mode
175  * @tc.type: FUNC
176  */
177 HWTEST_F(SyncTest, mutex_lock_with_BlockThread, TestSize.Level0)
178 {
179     int x = 0;
180     ffrt::mutex lock;
__anon0ee75e610102() 181     ffrt::submit([&]() {
182         ffrt_this_task_set_legacy_mode(true);
183         ffrt::this_task::sleep_for(10ms);
184         lock.lock();
185         ffrt::submit([&]() {
186             EXPECT_EQ(x, 1);
187             }, {&x}, {});
188         ffrt::submit([&]() {
189             x++;
190             EXPECT_EQ(x, 2);
191             }, {&x}, {&x});
192         ffrt::submit([&]() {
193             EXPECT_EQ(x, 2);
194             }, {&x}, {});
195         ffrt::wait();
196         lock.unlock();
197         ffrt_this_task_set_legacy_mode(false);
198         }, {}, {}, ffrt::task_attr().name("t2"));
199 
__anon0ee75e610d02() 200     ffrt::submit([&]() {
201         ffrt_this_task_set_legacy_mode(true);
202         lock.lock();
203         ffrt::submit([&]() {
204             EXPECT_EQ(x, 0);
205             }, {&x}, {});
206         ffrt::submit([&]() {
207             x++;
208             EXPECT_EQ(x, 1);
209             }, {&x}, {&x});
210         ffrt::submit([&]() {
211             EXPECT_EQ(x, 1);
212             }, {&x}, {});
213         ffrt::wait();
214         lock.unlock();
215         ffrt_this_task_set_legacy_mode(false);
216         }, {}, {}, ffrt::task_attr().name("t1"));
217     ffrt::wait();
218 }
219 
220 /**
221  * @tc.name: set_legacy_mode_within_nested_task
222  * @tc.desc: Test function of mutex:lock in Thread mode
223  * @tc.type: FUNC
224  */
225 HWTEST_F(SyncTest, set_legacy_mode_within_nested_task, TestSize.Level0)
226 {
227     int x = 0;
__anon0ee75e611902() 228     ffrt::submit([&]() {
229         ffrt_this_task_set_legacy_mode(true);
230         ffrt_this_task_set_legacy_mode(true);
231         ffrt::CPUEUTask* ctx = static_cast<ffrt::CPUEUTask*>(ffrt::ExecuteCtx::Cur()->task);
232         EXPECT_EQ(ctx->Block() == ffrt::BlockType::BLOCK_THREAD, true);
233         EXPECT_EQ(ctx->GetBlockType() == ffrt::BlockType::BLOCK_THREAD, true);
234         ctx->Wake();
235         ffrt::submit([&]() {
236             ffrt_this_task_set_legacy_mode(true);
237             ffrt::CPUEUTask* ctx = static_cast<ffrt::CPUEUTask*>(ffrt::ExecuteCtx::Cur()->task);
238             EXPECT_EQ(ctx->Block() == ffrt::BlockType::BLOCK_THREAD, true);
239             EXPECT_EQ(ctx->GetBlockType() == ffrt::BlockType::BLOCK_THREAD, true);
240             x++;
241             EXPECT_EQ(x, 1);
242             ffrt_this_task_set_legacy_mode(false);
243             ffrt_this_task_set_legacy_mode(false);
244             ctx = static_cast<ffrt::CPUEUTask*>(ffrt::ExecuteCtx::Cur()->task);
245             int legacycount = ctx->legacyCountNum;
246             EXPECT_EQ(legacycount, -1);
247             }, {}, {});
248         ffrt::wait();
249         ffrt_this_task_set_legacy_mode(false);
250         ffrt_this_task_set_legacy_mode(false);
251         ctx = static_cast<ffrt::CPUEUTask*>(ffrt::ExecuteCtx::Cur()->task);
252         int legacycount = ctx->legacyCountNum;
253         EXPECT_EQ(legacycount, 0);
254         auto expectedBlockType = ffrt::USE_COROUTINE? ffrt::BlockType::BLOCK_COROUTINE : ffrt::BlockType::BLOCK_THREAD;
255         EXPECT_EQ(ctx->Block(), expectedBlockType);
256         EXPECT_EQ(ctx->GetBlockType(), expectedBlockType);
257         }, {}, {});
258     ffrt::wait();
259     EXPECT_EQ(x, 1);
260 }
261 
262 HWTEST_F(SyncTest, class_data_align, TestSize.Level0)
263 {
264     struct memTest {
265         bool isFlag; // Construct an unaligned address
266         ffrt::mutex mtx;
267         ffrt::task_attr taskAttr;
268         ffrt::task_handle taskHandle;
269         ffrt::condition_variable cv;
270         ffrt::thread t;
271     };
272     memTest m;
273     {
274         ffrt::mutex* mtxAddr = &m.mtx;
275         uintptr_t addr_int = reinterpret_cast<uintptr_t>(mtxAddr);
276         EXPECT_EQ((addr_int % 4), 0);
277 
278         ffrt::task_attr* attrAddr = &m.taskAttr;
279         addr_int = reinterpret_cast<uintptr_t>(attrAddr);
280         EXPECT_EQ((addr_int % 4), 0);
281 
282         ffrt::task_handle* handleAddr = &m.taskHandle;
283         addr_int = reinterpret_cast<uintptr_t>(handleAddr);
284         EXPECT_EQ((addr_int % 4), 0);
285 
286         ffrt::condition_variable* cvAddr = &m.cv;
287         addr_int = reinterpret_cast<uintptr_t>(cvAddr);
288         EXPECT_EQ((addr_int % 4), 0);
289 
290         ffrt::thread* tAddr = &m.t;
291         addr_int = reinterpret_cast<uintptr_t>(tAddr);
292         EXPECT_EQ((addr_int % 4), 0);
293     }
294 }
295 
296 HWTEST_F(SyncTest, lock_stress, TestSize.Level0)
297 {
298     // trigger lazy init
__anon0ee75e612002() 299     ffrt::submit([&]() {}, {}, {});
300     ffrt::wait();
301 
302     const int N = 10;
303     const int M = 1000;
304     const int J = 10000;
305     ffrt::mutex lock;
306     // std::mutex lock;
307     int acc = 0;
308     for (int i = 0; i < N; ++i) {
309         ffrt::submit(
__anon0ee75e612202() 310             [&]() {
311                 for (int j = 0; j < M; ++j) {
312                     lock.lock();
313                     acc++;
314                     lock.unlock();
315                 }
316             },
__anon0ee75e612402() 317             {}, {});
318     }
319 
320     for (int j = 0; j < J; ++j) {
321         lock.lock();
322         acc++;
323         lock.unlock();
324     }
325 
326     ffrt::wait();
327     EXPECT_EQ(acc, (M * N + J));
328 }
329 
330 HWTEST_F(SyncTest, lock_stress_c_api, TestSize.Level0)
331 {
332     // trigger lazy init
__anon0ee75e612502() 333     ffrt::submit([&]() {}, {}, {});
334     ffrt::wait();
335 
336     const int N = 10;
337     const int M = 1000;
338     const int J = 10000;
339     ffrt::mutex* lock = new ffrt::mutex;
340     int acc = 0;
341     for (int i = 0; i < N; ++i) {
342         ffrt::submit(
__anon0ee75e612802() 343             [&]() {
344                 for (int j = 0; j < M; ++j) {
345                     lock->lock();
346                     acc++;
347                     lock->unlock();
348                 }
349             },
__anon0ee75e612a02() 350             {}, {});
351     }
352 
353     for (int j = 0; j < J; ++j) {
354         lock->lock();
355         acc++;
356         lock->unlock();
357     }
358 
359     ffrt::wait();
360     EXPECT_EQ(acc, (M * N + J));
361     delete lock;
362 }
363 
364 /**
365  * @tc.name: recursive_lock_stress
366  * @tc.desc: Test C++ function of recursive mutex:lock in stress mode
367  * @tc.type: FUNC
368  */
369 HWTEST_F(SyncTest, recursive_lock_stress, TestSize.Level0)
370 {
371     // trigger lazy init
__anon0ee75e612d02() 372     ffrt::submit([&]() {}, {}, {});
373     ffrt::wait();
374 
375     const int N = 10;
376     const int M = 1000;
377     const int J = 10000;
378     ffrt::recursive_mutex lock;
379     // std::mutex lock;
380     int acc = 0;
381     for (int i = 0; i < N; ++i) {
382         ffrt::submit(
__anon0ee75e612e02() 383             [&]() {
384                 for (int j = 0; j < M; ++j) {
385                     lock.lock();
386                     acc++;
387                     lock.unlock();
388                 }
389             },
__anon0ee75e613002() 390             {}, {});
391     }
392 
393     for (int j = 0; j < J; ++j) {
394         lock.lock();
395         acc++;
396         lock.unlock();
397     }
398 
399     ffrt::wait();
400     EXPECT_EQ(acc, (M * N + J));
401 }
402 
403 /**
404  * @tc.name: recursive_lock_stress
405  * @tc.desc: Test C function of recursive mutex:lock in stress mode
406  * @tc.type: FUNC
407  */
408 HWTEST_F(SyncTest, recursive_lock_stress_c_api, TestSize.Level0)
409 {
410     // trigger lazy init
__anon0ee75e613202() 411     ffrt::submit([&]() {}, {}, {});
412     ffrt::wait();
413 
414     const int N = 10;
415     const int M = 1000;
416     const int J = 10000;
417     ffrt::recursive_mutex* lock = new ffrt::recursive_mutex;
418     int acc = 0;
419     for (int i = 0; i < N; ++i) {
420         ffrt::submit(
__anon0ee75e613402() 421             [&]() {
422                 for (int j = 0; j < M; ++j) {
423                     lock->lock();
424                     acc++;
425                     lock->unlock();
426                 }
427             },
__anon0ee75e613602() 428             {}, {});
429     }
430 
431     for (int j = 0; j < J; ++j) {
432         lock->lock();
433         acc++;
434         lock->unlock();
435     }
436 
437     ffrt::wait();
438     EXPECT_EQ(acc, (M * N + J));
439     delete lock;
440 }
441 
WaitforInThreadMode(std::function<void (std::atomic<bool> & ready)> waitFunc,std::function<void ()> notifyFunc)442 void WaitforInThreadMode(std::function<void(std::atomic<bool>& ready)> waitFunc, std::function<void()> notifyFunc)
443 {
444     std::atomic<bool> ready(false);
445     std::thread th1([&waitFunc, &ready] {
446         waitFunc(ready);
447     });
448     while (!ready.load()) {
449         std::this_thread::yield();
450     }
451     std::thread th2(notifyFunc);
452     th1.join();
453     th2.join();
454 }
455 
WaitforInCoroutineMode(std::function<void (std::atomic<bool> & ready)> waitFunc,std::function<void ()> notifyFunc)456 void WaitforInCoroutineMode(std::function<void(std::atomic<bool>& ready)> waitFunc, std::function<void()> notifyFunc)
457 {
458     std::atomic<bool> ready(false);
459     ffrt::submit([&waitFunc, &ready]() {
460         waitFunc(ready);
461     });
462     while (!ready.load()) {
463         std::this_thread::yield();
464     }
465     ffrt::submit(notifyFunc);
466     ffrt::wait();
467 }
468 
469 HWTEST_F(SyncTest, conditionTestWaitfor, TestSize.Level0)
470 {
471     ffrt::mutex lock_;
472     ffrt::condition_variable cond;
473     std::atomic_bool flag {false};
__anon0ee75e613902(std::atomic<bool>& ready) 474     auto waitFunc = [&lock_, &cond, &flag] (std::atomic<bool>& ready) {
475         std::unique_lock lck(lock_);
476         bool ret = cond.wait_for(lck, std::chrono::nanoseconds::min(), [&flag] { return flag.load(); });
477         EXPECT_FALSE(ret);
478 
479         auto start = std::chrono::high_resolution_clock::now();
480         ret = cond.wait_for(lck, 100ms, [&flag] { return flag.load(); });
481         auto end = std::chrono::high_resolution_clock::now();
482         auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
483         EXPECT_GE(elapsed, 100);
484 
485         ready.store(true);
486 
487         ret = cond.wait_for(lck, std::chrono::nanoseconds::max(), [&] { return flag.load(); });
488         EXPECT_TRUE(ret);
489         EXPECT_TRUE(flag.load());
490     };
__anon0ee75e613d02() 491     auto notifyFunc = [&lock_, &cond, &flag] () {
492         std::unique_lock lck(lock_);
493         flag.store(true);
494         cond.notify_all();
495     };
496 
497     // Running test in Thread Mode
498     WaitforInThreadMode(waitFunc, notifyFunc);
499     flag.store(false);
500     // Running test in Coroutine Mode
501     WaitforInCoroutineMode(waitFunc, notifyFunc);
502 }
503 
504 HWTEST_F(SyncTest, conditionTestDataRace, TestSize.Level0)
505 {
506     std::atomic_bool exit {false};
507     ffrt::mutex mtx;
508     ffrt::condition_variable cv;
509     std::atomic_bool start {false};
510 
__anon0ee75e613e02null511     ffrt::thread th {[&] {
512         while (!exit) {
513             if (start) {
514                 cv.notify_one();
515                 ffrt::this_task::sleep_for(1us);
516             }
517         }
518     }};
519 
520     start = true;
521     for (int i = 0; i < 2000; ++i) {
522         std::unique_lock lk(mtx);
523         cv.wait_for(lk, 1us);
524     }
525     exit = true;
526     th.join();
527     exit = false;
528     start = true;
__anon0ee75e613f02null529     ffrt::thread th1 {[&] {
530         for (int i = 0; i < 2000; ++i) {
531             std::unique_lock lk(mtx);
532             cv.wait_for(lk, 1us);
533         }
534         exit = true;
535     }};
536 
537     while (!exit) {
538         if (start) {
539             cv.notify_one();
540             ffrt::this_task::sleep_for(1us);
541         }
542     }
543 
544     th1.join();
545 }
546 
547 HWTEST_F(SyncTest, sharedMutexTestInit, TestSize.Level0)
548 {
549     // init when attr is not nullptr,
550     int x = 0;
551     ffrt::shared_mutex smut;
552     ffrt_rwlockattr_t attr;
553 
554     attr.storage = 1;
555     x = ffrt_rwlock_init(&smut, &attr);
556     EXPECT_EQ(x, ffrt_error_inval);
557     x = ffrt_rwlock_init(nullptr, &attr);
558     EXPECT_EQ(x, ffrt_error_inval);
559 }
560 
561 /*
562  * 测试用例名称:sharedMutexTest
563  * 测试用例描述:legacy任务调用shared_mutex加解锁接口
564  * 预置条件    :无
565  * 操作步骤    :1、初始化shared_mutex
566                  2、提交任务
567                  3、调用shared_mutex加解锁接口
568                  4、设置legacy模式后,调用shared_mutex加解锁接口
569  * 预期结果    :任务按预期执行
570  */
571 HWTEST_F(SyncTest, mutexTest, TestSize.Level0)
572 {
573     ffrt::mutex mut;
574 
575     int taskCount = 10;
576 
__anon0ee75e614002() 577     auto block = [&]() {
578         mut.lock();
579         usleep(10000);
580         mut.unlock();
581         ffrt_this_task_set_legacy_mode(true);
582         mut.lock();
583         usleep(10000);
584         mut.unlock();
585     };
586 
587     for (int i = 0; i < taskCount; i++) {
588         ffrt::submit(block);
589     }
590 
591     ffrt::wait();
592 }
593 
594 /*
595  * 测试用例名称:sharedMutexTest
596  * 测试用例描述:legacy任务调用shared_mutex加解锁接口
597  * 预置条件    :无
598  * 操作步骤    :1、初始化shared_mutex
599                  2、提交任务
600                  3、调用shared_mutex加解锁接口
601                  4、设置legacy模式后,调用shared_mutex加解锁接口
602  * 预期结果    :任务按预期执行
603  */
604 HWTEST_F(SyncTest, sharedMutexTest, TestSize.Level0)
605 {
606     ffrt::shared_mutex smut;
607 
608     int taskCount = 10;
609 
__anon0ee75e614102() 610     auto block = [&]() {
611         smut.lock();
612         usleep(10000);
613         smut.unlock();
614         ffrt_this_task_set_legacy_mode(true);
615         smut.lock();
616         usleep(10000);
617         smut.unlock();
618     };
619 
620     for (int i = 0; i < taskCount; i++) {
621         ffrt::submit(block);
622     }
623 
624     ffrt::wait();
625 }
626 
NotifyOneTest(ffrt::mutex & mtx,ffrt::condition_variable & cv)627 static void NotifyOneTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)
628 {
629     FFRT_LOGE("[RUN ] notifyone");
630     int value = 0;
631     bool flag {false};
632     ffrt::submit(
633         [&]() {
634             std::unique_lock lk(mtx);
635             cv.wait(lk, [&] { return flag; });
636             EXPECT_TRUE(lk.owns_lock());
637             value = 123;
638         },
639         {}, {});
640 
641     EXPECT_EQ(value, 0);
642 
643     ffrt::submit(
644         [&]() {
645             {
646                 std::unique_lock lk(mtx);
647                 flag = true;
648             }
649             cv.notify_one();
650         },
651         {}, {});
652 
653     ffrt::wait();
654 
655     EXPECT_EQ(value, 123);
656 }
657 
WaitUntilTimeoutTest(ffrt::mutex & mtx,ffrt::condition_variable & cv)658 static void WaitUntilTimeoutTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)
659 {
660     constexpr auto eps = 3ms;
661 
662     FFRT_LOGE("[RUN ] WaitUntil timeout&notifyone");
663     int value = 0;
664     ffrt::submit(
665         [&]() {
666             std::unique_lock lk(mtx);
667             EXPECT_EQ(static_cast<int>(cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms)),
668                 static_cast<int>(ffrt::cv_status::timeout));
669             EXPECT_TRUE(lk.owns_lock());
670             value = 123;
671         },
672         {}, {});
673 
674     EXPECT_EQ(value, 0);
675 
676     ffrt::submit(
677         [&]() {
678             ffrt::this_task::sleep_for(30ms + eps);
679             cv.notify_one();
680         },
681         {}, {});
682 
683     ffrt::wait();
684 
685     EXPECT_EQ(value, 123);
686 }
687 
WaitUtilFlagTest_1(ffrt::mutex & mtx,ffrt::condition_variable & cv)688 static void WaitUtilFlagTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)
689 {
690     constexpr auto eps = 3ms;
691 
692     FFRT_LOGE("[RUN ] WaitUntil flag&notifyone");
693     int value = 0;
694     bool flag {false};
695 
696     ffrt::submit(
697         [&]() {
698             std::unique_lock lk(mtx);
699             EXPECT_TRUE(!cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms, [&] { return flag; }));
700             value = 123;
701         },
702         {}, {});
703 
704     EXPECT_EQ(value, 0);
705 
706     ffrt::submit(
707         [&]() {
708             ffrt::this_task::sleep_for(30ms + eps);
709             cv.notify_one();
710         },
711         {}, {});
712 
713     ffrt::wait();
714 
715     EXPECT_EQ(value, 123);
716 }
717 
WaitUtilFlagTest_2(ffrt::mutex & mtx,ffrt::condition_variable & cv)718 static void WaitUtilFlagTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)
719 {
720     int value = 0;
721     bool flag {false};
722 
723     ffrt::submit(
724         [&]() {
725             std::unique_lock lk(mtx);
726             EXPECT_TRUE(cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms, [&] { return flag; }));
727             value = 123;
728         },
729         {}, {});
730 
731     EXPECT_EQ(value, 0);
732 
733     ffrt::submit(
734         [&]() {
735             std::unique_lock lk(mtx);
736             flag = true;
737             cv.notify_one();
738         },
739         {}, {});
740 
741     ffrt::wait();
742 
743     EXPECT_EQ(value, 123);
744 }
745 
WaitForTest_1(ffrt::mutex & mtx,ffrt::condition_variable & cv)746 static void WaitForTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)
747 {
748     constexpr auto eps = 3ms;
749 
750     int value = 0;
751     ffrt::submit(
752         [&]() {
753             std::unique_lock lk(mtx);
754             EXPECT_EQ(static_cast<int>(cv.wait_for(lk, 30ms)), static_cast<int>(ffrt::cv_status::timeout));
755             EXPECT_TRUE(lk.owns_lock());
756             value = 123;
757         },
758         {}, {});
759 
760     EXPECT_EQ(value, 0);
761 
762     ffrt::submit(
763         [&]() {
764             ffrt::this_task::sleep_for(30ms + eps);
765             cv.notify_one();
766         },
767         {}, {});
768 
769     ffrt::wait();
770 
771     EXPECT_EQ(value, 123);
772 }
773 
WaitForTest_2(ffrt::mutex & mtx,ffrt::condition_variable & cv)774 static void WaitForTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)
775 {
776     int value = 0;
777     ffrt::submit(
778         [&]() {
779             std::unique_lock lk(mtx);
780             ffrt::submit(
781                 [&]() {
782                     std::unique_lock lk(mtx);
783                     cv.notify_one();
784                 },
785                 {}, {});
786             EXPECT_EQ(static_cast<int>(cv.wait_for(lk, 30ms)), static_cast<int>(ffrt::cv_status::no_timeout));
787             EXPECT_EQ(value, 0);
788             EXPECT_TRUE(lk.owns_lock());
789             value = 123;
790         },
791         {}, {});
792 
793     ffrt::wait();
794 
795     EXPECT_EQ(value, 123);
796 }
797 
WaitForTest_3(ffrt::mutex & mtx,ffrt::condition_variable & cv)798 static void WaitForTest_3(ffrt::mutex& mtx, ffrt::condition_variable& cv)
799 {
800     constexpr auto eps = 3ms;
801 
802     int value = 0;
803     bool flag {false};
804 
805     ffrt::submit(
806         [&]() {
807             std::unique_lock lk(mtx);
808             EXPECT_TRUE(!cv.wait_for(lk, 30ms, [&] { return flag; }));
809             value = 123;
810         },
811         {}, {});
812 
813     EXPECT_EQ(value, 0);
814 
815     ffrt::submit(
816         [&]() {
817             ffrt::this_task::sleep_for(30ms + eps);
818             cv.notify_one();
819         },
820         {}, {});
821 
822     ffrt::wait();
823 
824     EXPECT_EQ(value, 123);
825 }
826 
WaitForTest_4(ffrt::mutex & mtx,ffrt::condition_variable & cv)827 static void WaitForTest_4(ffrt::mutex& mtx, ffrt::condition_variable& cv)
828 {
829     int value = 0;
830     bool flag {false};
831 
832     ffrt::submit(
833         [&]() {
834             std::unique_lock lk(mtx);
835             EXPECT_TRUE(cv.wait_for(lk, 30ms, [&] { return flag; }));
836             value = 123;
837         },
838         {}, {});
839 
840     EXPECT_EQ(value, 0);
841 
842     ffrt::submit(
843         [&]() {
844             std::unique_lock lk(mtx);
845             flag = true;
846             cv.notify_one();
847         },
848         {}, {});
849 
850     ffrt::wait();
851 
852     EXPECT_EQ(value, 123);
853 }
854 
LockTest(ffrt::shared_mutex & smtx)855 static void LockTest(ffrt::shared_mutex& smtx)
856 {
857     int x = 0;
858     const int N = 100;
859     const int R = 200;
860 
861     ffrt::submit(
862         [&]() {
863             for (int i = 0; i < N; i++) {
864                 smtx.lock();
865                 x++;
866                 smtx.unlock();
867             }
868         },
869         {}, {});
870 
871     for (int j = 0; j < N; ++j) {
872         smtx.lock();
873         x++;
874         smtx.unlock();
875     }
876 
877     ffrt::wait();
878     EXPECT_EQ(x, R);
879 }
880 
TryLockTest(ffrt::shared_mutex & smtx)881 static void TryLockTest(ffrt::shared_mutex& smtx)
882 {
883     int x = 0;
884     const int N = 100;
885     ffrt::submit(
886         [&]() {
887             smtx.lock();
888             ffrt::this_task::sleep_for(20ms);
889             smtx.unlock();
890         },
891         {}, {});
892 
893     ffrt::this_task::sleep_for(2ms);
894 
895     bool ret = smtx.try_lock();
896     EXPECT_EQ(ret, false);
897     if (ret) {
898         smtx.unlock();
899     }
900     ffrt::wait();
901 
902     ret = smtx.try_lock();
903     EXPECT_EQ(ret, true);
904     if (ret) {
905         smtx.unlock();
906     }
907 }
908 
LockSharedTest(ffrt::shared_mutex & smtx)909 static void LockSharedTest(ffrt::shared_mutex& smtx)
910 {
911     int x = 0;
912     const int N = 100;
913 
914     ffrt::submit(
915         [&]() {
916             smtx.lock_shared();
917             ffrt::this_task::sleep_for(20ms);
918             x = N;
919             smtx.unlock_shared();
920         },
921         {}, {});
922     ffrt::this_task::sleep_for(2ms);
923 
924     smtx.lock_shared();
925     EXPECT_EQ(x, 0);
926     smtx.unlock_shared();
927 
928     smtx.lock();
929     EXPECT_EQ(x, N);
930     smtx.unlock();
931 
932     ffrt::wait();
933 
934     smtx.lock_shared();
935     EXPECT_EQ(x, N);
936     smtx.unlock_shared();
937 }
938 
TryLockSharedTest(ffrt::shared_mutex & smtx)939 static void TryLockSharedTest(ffrt::shared_mutex& smtx)
940 {
941     int x = 0;
942     const int N = 100;
943 
944     ffrt::submit(
945         [&]() {
946             smtx.lock_shared();
947             ffrt::this_task::sleep_for(20ms);
948             x = N;
949             smtx.unlock_shared();
950         },
951         {}, {});
952     ffrt::this_task::sleep_for(2ms);
953 
954     bool ret = smtx.try_lock_shared();
955     EXPECT_EQ(ret, true);
956     EXPECT_EQ(x, 0);
957     if (ret) {
958         smtx.unlock_shared();
959     }
960     ffrt::wait();
961 
962     ret = smtx.try_lock_shared();
963     EXPECT_EQ(ret, true);
964     EXPECT_EQ(x, N);
965     if (ret) {
966         smtx.unlock_shared();
967     }
968 
969     ffrt::submit(
970         [&]() {
971             smtx.lock();
972             ffrt::this_task::sleep_for(20ms);
973             x = 0;
974             smtx.unlock();
975         },
976         {}, {});
977     ffrt::this_task::sleep_for(2ms);
978 
979     ret = smtx.try_lock_shared();
980     EXPECT_EQ(ret, false);
981     EXPECT_EQ(x, N);
982     if (ret) {
983         smtx.unlock_shared();
984     }
985     ffrt::wait();
986 
987     ret = smtx.try_lock_shared();
988     EXPECT_EQ(ret, true);
989     EXPECT_EQ(x, 0);
990     if (ret) {
991         smtx.unlock_shared();
992     }
993 }
994 
995 HWTEST_F(SyncTest, thread1, TestSize.Level0)
996 {
__anon0ee75e618602(int a, const int& b) 997     auto ThreadFunc1 = [](int a, const int& b) {
998         FFRT_LOGW("a = %d, b = %d", a, b);
999         return 0;
1000     };
1001 
__anon0ee75e618702(const char* a, const char* b) 1002     auto ThreadFunc2 = [](const char* a, const char* b) {
1003         FFRT_LOGW("%s %s", a, b);
1004         return 0;
1005     };
1006 
1007     {
1008         int value = 0;
__anon0ee75e618802null1009         std::thread th0 {[&value, &ThreadFunc1, &ThreadFunc2] {
1010             std::thread th1 {ThreadFunc1, 10, 20};
1011             std::thread th2 {ThreadFunc2, "hello", "ffrt"};
1012             th1.join();
1013             th2.join();
1014 
1015             value = 123;
1016             FFRT_LOGW("value = %d", value);
1017         }};
1018         th0.join();
1019         assert(!th0.joinable());
1020         EXPECT_EQ(value, 123);
1021     }
1022     {
1023         int value = 0;
__anon0ee75e618902null1024         ffrt::thread th0 {[&value, &ThreadFunc1, &ThreadFunc2] {
1025             ffrt::thread th1 {ThreadFunc1, 10, 20};
1026             ffrt::thread th2 {ThreadFunc2, "hello", "ffrt"};
1027             th1.join();
1028             th2.join();
1029 
1030             value = 123;
1031             FFRT_LOGW("value = %d", value);
1032         }};
1033         th0.join();
1034         assert(!th0.joinable());
1035         EXPECT_EQ(value, 123);
1036     }
1037 }
1038 
f1(int n)1039 void f1(int n)
1040 {
1041     for (int i = 0; i < 5; ++i) {
1042         std::cout << "Thread 1 executing\n";
1043         ++n;
1044         std::this_thread::sleep_for(std::chrono::milliseconds(10));
1045     }
1046 }
1047 
f2(int & n)1048 void f2(int& n)
1049 {
1050     for (int i = 0; i < 5; ++i) {
1051         std::cout << "Thread 2 executing\n";
1052         ++n;
1053         std::this_thread::sleep_for(std::chrono::milliseconds(10));
1054     }
1055 }
1056 
1057 class foo {
1058 public:
bar()1059     void bar()
1060     {
1061         for (int i = 0; i < 5; ++i) {
1062             std::cout << "Thread 3 executing\n";
1063             ++n;
1064             std::this_thread::sleep_for(std::chrono::milliseconds(10));
1065         }
1066     }
1067     int n = 0;
1068 };
1069 
1070 class baz {
1071 public:
operator ()()1072     void operator()()
1073     {
1074         for (int i = 0; i < 5; ++i) {
1075             std::cout << "Thread 4 executing\n";
1076             ++n;
1077             std::this_thread::sleep_for(std::chrono::milliseconds(10));
1078         }
1079     }
1080     int n = 0;
1081 };
1082 
1083 HWTEST_F(SyncTest, thread2, TestSize.Level0)
1084 {
1085     {
1086         int n = 0;
1087         foo f;
1088         baz b;
1089         {
1090             std::thread t2(f1, n + 1);
1091             t2.detach(); // test detach
1092         }
1093         std::thread t1; // t1 is not a thread
1094         std::thread t2(f1, n + 1); // pass by value
1095         std::thread t3(f2, std::ref(n)); // pass by reference
1096         std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
1097         std::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
1098         std::thread t6(b); // t6 runs baz::operator() on a copy of object b
1099         EXPECT_EQ(t1.joinable(), false);
1100         EXPECT_EQ(t2.joinable(), true);
1101         t2.join();
1102         EXPECT_EQ(t2.joinable(), false);
1103         t4.join();
1104         t5.join();
1105         t6.join();
1106         EXPECT_EQ(n, 5);
1107         EXPECT_EQ(f.n, 5);
1108         EXPECT_EQ(b.n, 0);
1109     }
1110     FFRT_LOGW("ffrt version");
1111     {
1112         int n = 0;
1113         foo f;
1114         baz b;
1115         {
1116             ffrt::thread t2(f1, n + 1);
1117             t2.detach(); // test detach
1118         }
1119         ffrt::thread t1; // t1 is not a thread
1120         ffrt::thread t2(f1, n + 1); // pass by value
1121         ffrt::thread t3(f2, std::ref(n)); // pass by reference
1122         ffrt::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
1123         ffrt::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
1124         ffrt::thread t6(b); // t6 runs baz::operator() on a copy of object b
1125         EXPECT_EQ(t1.joinable(), false);
1126         EXPECT_EQ(t2.joinable(), true);
1127         t2.join();
1128         EXPECT_EQ(t2.joinable(), false);
1129         EXPECT_EQ(t3.joinable(), false);
1130         EXPECT_EQ(t4.joinable(), true);
1131         t4.join();
1132         EXPECT_EQ(t4.joinable(), false);
1133         t5.join();
1134         t6.join();
1135         EXPECT_EQ(n, 5);
1136         EXPECT_EQ(f.n, 5);
1137         EXPECT_EQ(b.n, 0);
1138     }
1139 }
1140 
1141 HWTEST_F(SyncTest, thread_with_qos, TestSize.Level0)
1142 {
1143     int a = 0;
__anon0ee75e618a02null1144     auto task = [&] {
1145         a++;
1146     };
1147     ffrt::thread(static_cast<int>(ffrt::qos_user_initiated), task).join();
1148     EXPECT_EQ(1, a);
1149 }
1150 
1151 HWTEST_F(SyncTest, thread_with_name, TestSize.Level0)
1152 {
1153     int a = 0;
__anon0ee75e618b02null1154     auto task = [&] {
1155         a++;
1156     };
1157     std::string name = "thread_test";
1158     ffrt::thread(name.c_str(), static_cast<int>(ffrt::qos_user_initiated), task).join();
1159     EXPECT_EQ(1, a);
1160 }
1161 
1162 struct F {
1163     template<typename T, typename U>
operator ()F1164     void operator()(T, U, int& a)
1165     {
1166         using std::is_same;
1167         using std::reference_wrapper;
1168         static_assert(is_same<T, reference_wrapper<int>>::value, "");
1169         static_assert(is_same<U, reference_wrapper<const int>>::value, "");
1170         a++;
1171     }
1172 };
1173 
1174 HWTEST_F(SyncTest, thread_with_ref_check, TestSize.Level0)
1175 {
1176     int a = 0;
1177     ffrt::thread t(F{}, std::ref(a), std::cref(a), std::ref(a));
1178     t.join();
1179     EXPECT_EQ(1, a);
1180 }
1181 
1182 struct A {
1183     A() = default;
1184     explicit A(const A&) = default;
1185 };
1186 
func(const A &)1187 void func(const A&) { }
1188 
1189 HWTEST_F(SyncTest, thread_with_ref, TestSize.Level0)
1190 {
1191     ffrt::thread t(func, A{});
1192     t.join();
1193 }
1194 
1195 HWTEST_F(SyncTest, future_wait, TestSize.Level1)
1196 {
__anon0ee75e618c02null1197     ffrt::packaged_task<int()> task([] { return 7; });
1198     ffrt::future<int> f1 = task.get_future();
1199     ffrt::thread t(std::move(task));
1200 
__anon0ee75e618d02null1201     ffrt::future<int> f2 = ffrt::async([] { return 8; });
1202 
1203     ffrt::promise<int> p;
1204     ffrt::future<int> f3 = p.get_future();
__anon0ee75e618e02null1205     ffrt::thread([&p] { p.set_value(9); }).detach();
1206 
1207     std::cout << "Waiting..." << std::flush;
1208     EXPECT_TRUE(f1.valid());
1209     EXPECT_TRUE(f2.valid());
1210     f1.wait();
1211     f2.wait();
1212     f3.wait();
1213     std::cout << "Done!\nResults are: "
1214               << f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
1215     t.join();
1216 }
1217 
1218 HWTEST_F(SyncTest, future_wait_void, TestSize.Level1)
1219 {
1220     vector<int> result(3, 0);
__anon0ee75e618f02null1221     ffrt::packaged_task<void()> task([&] { result[0] = 1; });
1222     ffrt::future<void> f1 = task.get_future();
1223     ffrt::thread t(std::move(task));
1224     ffrt::thread t1;
1225     t1 = std::move(t);
1226 
__anon0ee75e619002null1227     ffrt::future<void> f2 = ffrt::async([&] { result[1] = 2; });
1228 
1229     ffrt::promise<void> p;
1230     ffrt::future<void> f3 = p.get_future();
1231     ffrt::promise<void> p1;
1232     ffrt::future<void> f4;
1233     p1 = std::move(p);
1234     f4 = std::move(f3);
__anon0ee75e619102null1235     ffrt::thread([&] { result[2] = 3; p1.set_value(); }).detach();
1236 
1237     EXPECT_TRUE(f1.valid());
1238     EXPECT_TRUE(f2.valid());
1239     EXPECT_TRUE(f4.valid());
1240     f1.wait();
1241     f2.wait();
1242     f4.wait();
1243     f1.get();
1244     EXPECT_EQ(result[0], 1);
1245     EXPECT_EQ(result[1], 2);
1246     EXPECT_EQ(result[2], 3);
1247     t1.join();
1248 }
1249 
1250 /*
1251 * 测试用例名称:ffrt_sleep_test
1252 * 测试用例描述:测试ffrt_usleep接口
1253 * 预置条件    :无
1254 * 操作步骤    :1.提交两个普通任务,一个设置为legacy任务
1255                 2.分别调用ffrt_usleep接口
1256 * 预期结果    :任务调用成功
1257 */
1258 HWTEST_F(SyncTest, ffrt_sleep_test, TestSize.Level0)
1259 {
__anon0ee75e619202() 1260     ffrt::submit([]() {
1261         ffrt_this_task_set_legacy_mode(true);
1262         ffrt::this_task::sleep_for(30ms);
1263     });
1264 
__anon0ee75e619302() 1265     ffrt::submit([]() {
1266         ffrt::this_task::sleep_for(30ms);
1267     });
1268 
1269     ffrt::wait();
1270 }
1271 
1272 /*
1273 * 测试用例名称:ffrt_yield_test
1274 * 测试用例描述:测试ffrt_yield接口
1275 * 预置条件    :无
1276 * 操作步骤    :1.提交两个普通任务,一个设置为legacy任务
1277                 2.分别调用ffrt_yield接口
1278 * 预期结果    :任务调用成功
1279 */
1280 HWTEST_F(SyncTest, ffrt_yield_test, TestSize.Level0)
1281 {
__anon0ee75e619402() 1282     ffrt::submit([]() {
1283         ffrt_this_task_set_legacy_mode(true);
1284         ffrt::this_task::yield();
1285     });
1286 
__anon0ee75e619502() 1287     ffrt::submit([]() {
1288         ffrt::this_task::yield();
1289     });
1290 
1291     ffrt::wait();
1292 }
1293 
1294 HWTEST_F(SyncTest, rwlock_api_test, TestSize.Level0)
1295 {
1296     int x = 0;
1297     x = ffrt_rwlock_wrlock(nullptr);
1298     EXPECT_EQ(x, ffrt_error_inval);
1299     x = ffrt_rwlock_trywrlock(nullptr);
1300     EXPECT_EQ(x, ffrt_error_inval);
1301     x = ffrt_rwlock_rdlock(nullptr);
1302     EXPECT_EQ(x, ffrt_error_inval);
1303     x = ffrt_rwlock_tryrdlock(nullptr);
1304     EXPECT_EQ(x, ffrt_error_inval);
1305     x = ffrt_rwlock_unlock(nullptr);
1306     EXPECT_EQ(x, ffrt_error_inval);
1307     x = ffrt_rwlock_destroy(nullptr);
1308     EXPECT_EQ(x, ffrt_error_inval);
1309 }
1310