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     virtual void SetUp()
56     {
57     }
58 
TearDown()59     virtual void TearDown()
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  */
HWTEST_F(SyncTest, mutexattr_nullptr_fail, TestSize.Level1)69 HWTEST_F(SyncTest, mutexattr_nullptr_fail, TestSize.Level1)
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 }
80 
81 /**
82  * @tc.name: mutex_nullptr_fail
83  * @tc.desc: Test function of mutex when the input is nullptr;
84  * @tc.type: FUNC
85  */
HWTEST_F(SyncTest, mutex_nullptr_fail, TestSize.Level1)86 HWTEST_F(SyncTest, mutex_nullptr_fail, TestSize.Level1)
87 {
88     int ret = ffrt_mutex_init(nullptr, nullptr);
89     EXPECT_EQ(ret, ffrt_error_inval);
90     ret = ffrt_mutex_lock(nullptr);
91     EXPECT_EQ(ret, ffrt_error_inval);
92     ret = ffrt_mutex_unlock(nullptr);
93     EXPECT_EQ(ret, ffrt_error_inval);
94     ret = ffrt_mutex_trylock(nullptr);
95     EXPECT_EQ(ret, ffrt_error_inval);
96     ffrt_mutex_destroy(nullptr);
97 }
98 
99 /**
100  * @tc.name: mutex_try_lock
101  * @tc.desc: Test function of mutex:try_lock
102  * @tc.type: FUNC
103  */
HWTEST_F(SyncTest, mutex_try_lock, TestSize.Level1)104 HWTEST_F(SyncTest, mutex_try_lock, TestSize.Level1)
105 {
106     int val = -1;
107     ffrt::mutex lock;
108     lock.lock();
109     val = lock.try_lock();
110     EXPECT_EQ(val, 0);
111     lock.unlock();
112     val = lock.try_lock();
113     EXPECT_EQ(val, 1);
114     lock.unlock();
115     lock.unlock();
116 }
117 
118 /**
119  * @tc.name: recursive_mutex_try_lock
120  * @tc.desc: Test function of recursive mutex:try_lock
121  * @tc.type: FUNC
122  */
HWTEST_F(SyncTest, recursive_mutex_try_lock, TestSize.Level1)123 HWTEST_F(SyncTest, recursive_mutex_try_lock, TestSize.Level1)
124 {
125     int val = -1;
126     ffrt::recursive_mutex lock;
127     lock.lock();
128     val = lock.try_lock();
129     EXPECT_EQ(val, 1);
130     lock.unlock();
131     val = lock.try_lock();
132     EXPECT_EQ(val, 1);
133     lock.unlock();
134     lock.unlock();
135 }
136 
137 /**
138  * @tc.name: mutex_lock_with_BlockThread
139  * @tc.desc: Test function of mutex:lock in Thread mode
140  * @tc.type: FUNC
141  */
HWTEST_F(SyncTest, mutex_lock_with_BlockThread, TestSize.Level1)142 HWTEST_F(SyncTest, mutex_lock_with_BlockThread, TestSize.Level1)
143 {
144     int x = 0;
145     ffrt::mutex lock;
146     ffrt::submit([&]() {
147         ffrt::this_task::sleep_for(10ms);
148         ffrt_this_task_set_legacy_mode(true);
149         lock.lock();
150         ffrt::submit([&]() {
151             EXPECT_EQ(x, 1);
152             }, {&x}, {});
153         ffrt::submit([&]() {
154             x++;
155             EXPECT_EQ(x, 2);
156             }, {&x}, {&x});
157         ffrt::submit([&]() {
158             EXPECT_EQ(x, 2);
159             }, {&x}, {});
160         ffrt::wait();
161         lock.unlock();
162         ffrt_this_task_set_legacy_mode(false);
163         }, {}, {}, ffrt::task_attr().name("t2"));
164 
165     ffrt::submit([&]() {
166         ffrt_this_task_set_legacy_mode(true);
167         lock.lock();
168         ffrt::submit([&]() {
169             EXPECT_EQ(x, 0);
170             }, {&x}, {});
171         ffrt::submit([&]() {
172             x++;
173             EXPECT_EQ(x, 1);
174             }, {&x}, {&x});
175         ffrt::submit([&]() {
176             EXPECT_EQ(x, 1);
177             }, {&x}, {});
178         ffrt::wait();
179         lock.unlock();
180         ffrt_this_task_set_legacy_mode(false);
181         }, {}, {}, ffrt::task_attr().name("t1"));
182     ffrt::wait();
183 }
184 
185 /**
186  * @tc.name: shared_mutex_lock_with_BlockThread
187  * @tc.desc: Test function of shared mutex:lock in Thread mode
188  * @tc.type: FUNC
189  */
HWTEST_F(SyncTest, shared_mutex_lock_with_BlockThread, TestSize.Level1)190 HWTEST_F(SyncTest, shared_mutex_lock_with_BlockThread, TestSize.Level1)
191 {
192     int x = 0;
193     const int N = 10;
194     ffrt::shared_mutex lock;
195     for (int i = 0; i < N; ++i) {
196         ffrt::submit([&]() {
197             ffrt_this_task_set_legacy_mode(true);
198             lock.lock();
199             ffrt::this_task::sleep_for(10ms);
200             x++;
201             lock.unlock();
202             ffrt_this_task_set_legacy_mode(false);
203             }, {}, {}, ffrt::task_attr().name("t1"));
204     }
205     ffrt::submit([&]() {
206         ffrt_this_task_set_legacy_mode(true);
207         lock.lock();
208         printf("x is %d", x);
209         lock.unlock();
210         ffrt_this_task_set_legacy_mode(false);
211         }, {}, {}, ffrt::task_attr().name("t2"));
212 
213     ffrt::wait();
214 }
215 
216 /**
217  * @tc.name: set_legacy_mode_within_nested_task
218  * @tc.desc: Test function of mutex:lock in Thread mode
219  * @tc.type: FUNC
220  */
HWTEST_F(SyncTest, set_legacy_mode_within_nested_task, TestSize.Level1)221 HWTEST_F(SyncTest, set_legacy_mode_within_nested_task, TestSize.Level1)
222 {
223     int x = 0;
224     ffrt::submit([&]() {
225         ffrt_this_task_set_legacy_mode(true);
226         ffrt_this_task_set_legacy_mode(true);
227         ffrt::CPUEUTask* ctx = ffrt::ExecuteCtx::Cur()->task;
228         bool result = ffrt::LegacyMode(ctx);
229         EXPECT_EQ(result, 1);
230         ffrt::submit([&]() {
231             ffrt_this_task_set_legacy_mode(true);
232             ffrt::CPUEUTask* ctx = ffrt::ExecuteCtx::Cur()->task;
233             bool result = ffrt::LegacyMode(ctx);
234             EXPECT_EQ(result, 1);
235             x++;
236             EXPECT_EQ(x, 1);
237             ffrt_this_task_set_legacy_mode(false);
238             ffrt_this_task_set_legacy_mode(false);
239             ctx = ffrt::ExecuteCtx::Cur()->task;
240             int legacycount = ctx->legacyCountNum;
241             EXPECT_EQ(legacycount, -1);
242             }, {}, {});
243         ffrt::wait();
244         ffrt_this_task_set_legacy_mode(false);
245         ffrt_this_task_set_legacy_mode(false);
246         ctx = ffrt::ExecuteCtx::Cur()->task;
247         int legacycount = ctx->legacyCountNum;
248         EXPECT_EQ(legacycount, 0);
249         }, {}, {});
250     ffrt::wait();
251     EXPECT_EQ(x, 1);
252 }
253 
HWTEST_F(SyncTest, class_data_align, TestSize.Level1)254 HWTEST_F(SyncTest, class_data_align, TestSize.Level1)
255 {
256     struct memTest {
257         bool isFlag; // Construct an unaligned address
258         ffrt::mutex mtx;
259         ffrt::task_attr taskAttr;
260         ffrt::task_handle taskHandle;
261         ffrt::condition_variable cv;
262         ffrt::thread t;
263     };
264     memTest m;
265     {
266         ffrt::mutex* mtxAddr = &m.mtx;
267         uintptr_t addr_int = reinterpret_cast<uintptr_t>(mtxAddr);
268         EXPECT_EQ((addr_int % 4), 0);
269 
270         ffrt::task_attr* attrAddr = &m.taskAttr;
271         addr_int = reinterpret_cast<uintptr_t>(attrAddr);
272         EXPECT_EQ((addr_int % 4), 0);
273 
274         ffrt::task_handle* handleAddr = &m.taskHandle;
275         addr_int = reinterpret_cast<uintptr_t>(handleAddr);
276         EXPECT_EQ((addr_int % 4), 0);
277 
278         ffrt::condition_variable* cvAddr = &m.cv;
279         addr_int = reinterpret_cast<uintptr_t>(cvAddr);
280         EXPECT_EQ((addr_int % 4), 0);
281 
282         ffrt::thread* tAddr = &m.t;
283         addr_int = reinterpret_cast<uintptr_t>(tAddr);
284         EXPECT_EQ((addr_int % 4), 0);
285     }
286 }
287 
HWTEST_F(SyncTest, lock_stress, TestSize.Level1)288 HWTEST_F(SyncTest, lock_stress, TestSize.Level1)
289 {
290     // trigger lazy init
291     ffrt::submit([&]() {}, {}, {});
292     ffrt::wait();
293 
294     const int N = 10;
295     const int M = 1000;
296     const int J = 10000;
297     ffrt::mutex lock;
298     // std::mutex lock;
299     int acc = 0;
300     for (int i = 0; i < N; ++i) {
301         ffrt::submit(
302             [&]() {
303                 for (int j = 0; j < M; ++j) {
304                     lock.lock();
305                     acc++;
306                     lock.unlock();
307                 }
308             },
309             {}, {});
310     }
311 
312     for (int j = 0; j < J; ++j) {
313         lock.lock();
314         acc++;
315         lock.unlock();
316     }
317 
318     ffrt::wait();
319     EXPECT_EQ(acc, (M * N + J));
320 }
321 
HWTEST_F(SyncTest, lock_stress_c_api, TestSize.Level1)322 HWTEST_F(SyncTest, lock_stress_c_api, TestSize.Level1)
323 {
324     // trigger lazy init
325     ffrt::submit([&]() {}, {}, {});
326     ffrt::wait();
327 
328     const int N = 10;
329     const int M = 1000;
330     const int J = 10000;
331     ffrt::mutex* lock = new ffrt::mutex;
332     int acc = 0;
333     for (int i = 0; i < N; ++i) {
334         ffrt::submit(
335             [&]() {
336                 for (int j = 0; j < M; ++j) {
337                     lock->lock();
338                     acc++;
339                     lock->unlock();
340                 }
341             },
342             {}, {});
343     }
344 
345     for (int j = 0; j < J; ++j) {
346         lock->lock();
347         acc++;
348         lock->unlock();
349     }
350 
351     ffrt::wait();
352     EXPECT_EQ(acc, (M * N + J));
353     delete lock;
354 }
355 
356 /**
357  * @tc.name: recursive_lock_stress
358  * @tc.desc: Test C++ function of recursive mutex:lock in stress mode
359  * @tc.type: FUNC
360  */
HWTEST_F(SyncTest, recursive_lock_stress, TestSize.Level1)361 HWTEST_F(SyncTest, recursive_lock_stress, TestSize.Level1)
362 {
363     // trigger lazy init
364     ffrt::submit([&]() {}, {}, {});
365     ffrt::wait();
366 
367     const int N = 10;
368     const int M = 1000;
369     const int J = 10000;
370     ffrt::recursive_mutex lock;
371     // std::mutex lock;
372     int acc = 0;
373     for (int i = 0; i < N; ++i) {
374         ffrt::submit(
375             [&]() {
376                 for (int j = 0; j < M; ++j) {
377                     lock.lock();
378                     acc++;
379                     lock.unlock();
380                 }
381             },
382             {}, {});
383     }
384 
385     for (int j = 0; j < J; ++j) {
386         lock.lock();
387         acc++;
388         lock.unlock();
389     }
390 
391     ffrt::wait();
392     EXPECT_EQ(acc, (M * N + J));
393 }
394 
395 /**
396  * @tc.name: recursive_lock_stress
397  * @tc.desc: Test C function of recursive mutex:lock in stress mode
398  * @tc.type: FUNC
399  */
HWTEST_F(SyncTest, recursive_lock_stress_c_api, TestSize.Level1)400 HWTEST_F(SyncTest, recursive_lock_stress_c_api, TestSize.Level1)
401 {
402     // trigger lazy init
403     ffrt::submit([&]() {}, {}, {});
404     ffrt::wait();
405 
406     const int N = 10;
407     const int M = 1000;
408     const int J = 10000;
409     ffrt::recursive_mutex* lock = new ffrt::recursive_mutex;
410     int acc = 0;
411     for (int i = 0; i < N; ++i) {
412         ffrt::submit(
413             [&]() {
414                 for (int j = 0; j < M; ++j) {
415                     lock->lock();
416                     acc++;
417                     lock->unlock();
418                 }
419             },
420             {}, {});
421     }
422 
423     for (int j = 0; j < J; ++j) {
424         lock->lock();
425         acc++;
426         lock->unlock();
427     }
428 
429     ffrt::wait();
430     EXPECT_EQ(acc, (M * N + J));
431     delete lock;
432 }
433 
HWTEST_F(SyncTest, conditionTestNotifyOne, TestSize.Level1)434 HWTEST_F(SyncTest, conditionTestNotifyOne, TestSize.Level1)
435 {
436     ffrt::condition_variable cond;
437     int a = 0;
438     ffrt::mutex lock_;
439 
440     ffrt::submit(
441         [&]() {
442             std::unique_lock lck(lock_);
443             cond.wait(lck, [&] { return a == 1; });
444         },
445         {}, {});
446 
447     ffrt::submit(
448         [&]() {
449             std::unique_lock lck(lock_);
450             a = 1;
451             cond.notify_one();
452         },
453         {}, {});
454     ffrt::wait();
455 }
456 
HWTEST_F(SyncTest, conditionTestNotifyAll, TestSize.Level1)457 HWTEST_F(SyncTest, conditionTestNotifyAll, TestSize.Level1)
458 {
459     ffrt::condition_variable cond;
460     int a = 0;
461     ffrt::mutex lock_;
462 
463     ffrt::submit(
464         [&]() {
465             std::unique_lock lck(lock_);
466             cond.wait(lck, [&] { return a == 1; });
467         },
468         {}, {});
469     ffrt::submit(
470         [&]() {
471             std::unique_lock lck(lock_);
472             cond.wait(lck, [&] { return a == 1; });
473         },
474         {}, {});
475     ffrt::submit(
476         [&]() {
477             std::unique_lock lck(lock_);
478             cond.wait(lck, [&] { return a == 1; });
479         },
480         {}, {});
481 
482     ffrt::submit(
483         [&]() {
484             std::unique_lock lck(lock_);
485             a = 1;
486             cond.notify_all();
487         },
488         {}, {});
489     ffrt::wait();
490 }
491 
HWTEST_F(SyncTest, conditionTestWaitfor, TestSize.Level1)492 HWTEST_F(SyncTest, conditionTestWaitfor, TestSize.Level1)
493 {
494     ffrt::condition_variable cond;
495     std::atomic_int a = 0;
496     ffrt::mutex lock_;
497 
498     ffrt::submit(
499         [&]() {
500             std::unique_lock lck(lock_);
501             cond.wait_for(lck, 100ms, [&] { return a == 1; });
502             EXPECT_EQ(a, 2);
503         },
504         {}, {});
505     ffrt::submit(
506         [&]() {
507             std::unique_lock lck(lock_);
508             cond.wait_for(lck, 150ms, [&] { return a == 2; });
509             EXPECT_EQ(a, 2);
510         },
511         {}, {});
512     ffrt::submit(
513         [&]() {
514             std::unique_lock lck(lock_);
515             a = 2;
516             cond.notify_all();
517         },
518         {}, {});
519     ffrt::wait();
520 }
521 
HWTEST_F(SyncTest, conditionTestDataRace, TestSize.Level1)522 HWTEST_F(SyncTest, conditionTestDataRace, TestSize.Level1)
523 {
524     std::atomic_bool exit {false};
525     ffrt::mutex mtx;
526     ffrt::condition_variable cv;
527     std::atomic_bool start {false};
528 
529     ffrt::thread th {[&] {
530         while (!exit) {
531             if (start) {
532                 cv.notify_one();
533                 ffrt::this_task::sleep_for(1us);
534             }
535         }
536     }};
537 
538     start = true;
539     for (int i = 0; i < 2000; ++i) {
540         std::unique_lock lk(mtx);
541         cv.wait_for(lk, 1us);
542     }
543     exit = true;
544     th.join();
545     exit = false;
546     start = true;
547     ffrt::thread th1 {[&] {
548         for (int i = 0; i < 2000; ++i) {
549             std::unique_lock lk(mtx);
550             cv.wait_for(lk, 1us);
551         }
552         exit = true;
553     }};
554 
555     while (!exit) {
556         if (start) {
557             cv.notify_one();
558             ffrt::this_task::sleep_for(1us);
559         }
560     }
561 
562     th1.join();
563 }
564 
NotifyOneTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)565 static void NotifyOneTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)
566 {
567     FFRT_LOGE("[RUN ] notifyone");
568     int value = 0;
569     bool flag {false};
570     ffrt::submit(
571         [&]() {
572             std::unique_lock lk(mtx);
573             cv.wait(lk, [&] { return flag; });
574             EXPECT_TRUE(lk.owns_lock());
575             value = 123;
576         },
577         {}, {});
578 
579     EXPECT_EQ(value, 0);
580 
581     ffrt::submit(
582         [&]() {
583             {
584                 std::unique_lock lk(mtx);
585                 flag = true;
586             }
587             cv.notify_one();
588         },
589         {}, {});
590 
591     ffrt::wait();
592 
593     EXPECT_EQ(value, 123);
594 }
595 
WaitUntilTimeoutTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)596 static void WaitUntilTimeoutTest(ffrt::mutex& mtx, ffrt::condition_variable& cv)
597 {
598     constexpr auto eps = 3ms;
599 
600     FFRT_LOGE("[RUN ] WaitUntil timeout&notifyone");
601     int value = 0;
602     ffrt::submit(
603         [&]() {
604             std::unique_lock lk(mtx);
605             EXPECT_EQ(static_cast<int>(cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms)),
606                 static_cast<int>(ffrt::cv_status::timeout));
607             EXPECT_TRUE(lk.owns_lock());
608             value = 123;
609         },
610         {}, {});
611 
612     EXPECT_EQ(value, 0);
613 
614     ffrt::submit(
615         [&]() {
616             ffrt::this_task::sleep_for(30ms + eps);
617             cv.notify_one();
618         },
619         {}, {});
620 
621     ffrt::wait();
622 
623     EXPECT_EQ(value, 123);
624 }
625 
WaitUtilFlagTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)626 static void WaitUtilFlagTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)
627 {
628     constexpr auto eps = 3ms;
629 
630     FFRT_LOGE("[RUN ] WaitUntil flag&notifyone");
631     int value = 0;
632     bool flag {false};
633 
634     ffrt::submit(
635         [&]() {
636             std::unique_lock lk(mtx);
637             EXPECT_TRUE(!cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms, [&] { return flag; }));
638             value = 123;
639         },
640         {}, {});
641 
642     EXPECT_EQ(value, 0);
643 
644     ffrt::submit(
645         [&]() {
646             ffrt::this_task::sleep_for(30ms + eps);
647             cv.notify_one();
648         },
649         {}, {});
650 
651     ffrt::wait();
652 
653     EXPECT_EQ(value, 123);
654 }
655 
WaitUtilFlagTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)656 static void WaitUtilFlagTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)
657 {
658     int value = 0;
659     bool flag {false};
660 
661     ffrt::submit(
662         [&]() {
663             std::unique_lock lk(mtx);
664             EXPECT_TRUE(cv.wait_until(lk, std::chrono::steady_clock::now() + 30ms, [&] { return flag; }));
665             value = 123;
666         },
667         {}, {});
668 
669     EXPECT_EQ(value, 0);
670 
671     ffrt::submit(
672         [&]() {
673             std::unique_lock lk(mtx);
674             flag = true;
675             cv.notify_one();
676         },
677         {}, {});
678 
679     ffrt::wait();
680 
681     EXPECT_EQ(value, 123);
682 }
683 
WaitForTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)684 static void WaitForTest_1(ffrt::mutex& mtx, ffrt::condition_variable& cv)
685 {
686     constexpr auto eps = 3ms;
687 
688     int value = 0;
689     ffrt::submit(
690         [&]() {
691             std::unique_lock lk(mtx);
692             EXPECT_EQ(static_cast<int>(cv.wait_for(lk, 30ms)), static_cast<int>(ffrt::cv_status::timeout));
693             EXPECT_TRUE(lk.owns_lock());
694             value = 123;
695         },
696         {}, {});
697 
698     EXPECT_EQ(value, 0);
699 
700     ffrt::submit(
701         [&]() {
702             ffrt::this_task::sleep_for(30ms + eps);
703             cv.notify_one();
704         },
705         {}, {});
706 
707     ffrt::wait();
708 
709     EXPECT_EQ(value, 123);
710 }
711 
WaitForTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)712 static void WaitForTest_2(ffrt::mutex& mtx, ffrt::condition_variable& cv)
713 {
714     int value = 0;
715     ffrt::submit(
716         [&]() {
717             std::unique_lock lk(mtx);
718             ffrt::submit(
719                 [&]() {
720                     std::unique_lock lk(mtx);
721                     cv.notify_one();
722                 },
723                 {}, {});
724             EXPECT_EQ(static_cast<int>(cv.wait_for(lk, 30ms)), static_cast<int>(ffrt::cv_status::no_timeout));
725             EXPECT_EQ(value, 0);
726             EXPECT_TRUE(lk.owns_lock());
727             value = 123;
728         },
729         {}, {});
730 
731     ffrt::wait();
732 
733     EXPECT_EQ(value, 123);
734 }
735 
WaitForTest_3(ffrt::mutex& mtx, ffrt::condition_variable& cv)736 static void WaitForTest_3(ffrt::mutex& mtx, ffrt::condition_variable& cv)
737 {
738     constexpr auto eps = 3ms;
739 
740     int value = 0;
741     bool flag {false};
742 
743     ffrt::submit(
744         [&]() {
745             std::unique_lock lk(mtx);
746             EXPECT_TRUE(!cv.wait_for(lk, 30ms, [&] { return flag; }));
747             value = 123;
748         },
749         {}, {});
750 
751     EXPECT_EQ(value, 0);
752 
753     ffrt::submit(
754         [&]() {
755             ffrt::this_task::sleep_for(30ms + eps);
756             cv.notify_one();
757         },
758         {}, {});
759 
760     ffrt::wait();
761 
762     EXPECT_EQ(value, 123);
763 }
764 
WaitForTest_4(ffrt::mutex& mtx, ffrt::condition_variable& cv)765 static void WaitForTest_4(ffrt::mutex& mtx, ffrt::condition_variable& cv)
766 {
767     int value = 0;
768     bool flag {false};
769 
770     ffrt::submit(
771         [&]() {
772             std::unique_lock lk(mtx);
773             EXPECT_TRUE(cv.wait_for(lk, 30ms, [&] { return flag; }));
774             value = 123;
775         },
776         {}, {});
777 
778     EXPECT_EQ(value, 0);
779 
780     ffrt::submit(
781         [&]() {
782             std::unique_lock lk(mtx);
783             flag = true;
784             cv.notify_one();
785         },
786         {}, {});
787 
788     ffrt::wait();
789 
790     EXPECT_EQ(value, 123);
791 }
792 
HWTEST_F(SyncTest, conditionTest, TestSize.Level1)793 HWTEST_F(SyncTest, conditionTest, TestSize.Level1)
794 {
795     ffrt::mutex mtx;
796     ffrt::condition_variable cv;
797 
798     NotifyOneTest(mtx, cv);
799     WaitUntilTimeoutTest(mtx, cv);
800     WaitUtilFlagTest_1(mtx, cv);
801     WaitUtilFlagTest_2(mtx, cv);
802     WaitForTest_1(mtx, cv);
803     WaitForTest_2(mtx, cv);
804     WaitForTest_3(mtx, cv);
805     WaitForTest_4(mtx, cv);
806 }
807 
LockTest(ffrt::shared_mutex& smtx)808 static void LockTest(ffrt::shared_mutex& smtx)
809 {
810     int x = 0;
811     const int N = 100;
812     const int R = 200;
813 
814     ffrt::submit(
815         [&]() {
816             for (int i = 0; i < N; i++) {
817                 smtx.lock();
818                 x++;
819                 smtx.unlock();
820             }
821         },
822         {}, {});
823 
824     for (int j = 0; j < N; ++j) {
825         smtx.lock();
826         x++;
827         smtx.unlock();
828     }
829 
830     ffrt::wait();
831     EXPECT_EQ(x, R);
832 }
833 
TryLockTest(ffrt::shared_mutex& smtx)834 static void TryLockTest(ffrt::shared_mutex& smtx)
835 {
836     int x = 0;
837     const int N = 100;
838     ffrt::submit(
839         [&]() {
840             smtx.lock();
841             ffrt::this_task::sleep_for(20ms);
842             smtx.unlock();
843         },
844         {}, {});
845 
846     ffrt::this_task::sleep_for(2ms);
847 
848     bool ret = smtx.try_lock();
849     EXPECT_EQ(ret, false);
850     if (ret) {
851         smtx.unlock();
852     }
853     ffrt::wait();
854 
855     ret = smtx.try_lock();
856     EXPECT_EQ(ret, true);
857     if (ret) {
858         smtx.unlock();
859     }
860 }
861 
LockSharedTest(ffrt::shared_mutex& smtx)862 static void LockSharedTest(ffrt::shared_mutex& smtx)
863 {
864     int x = 0;
865     const int N = 100;
866 
867     ffrt::submit(
868         [&]() {
869             smtx.lock_shared();
870             ffrt::this_task::sleep_for(20ms);
871             x = N;
872             smtx.unlock_shared();
873         },
874         {}, {});
875     ffrt::this_task::sleep_for(2ms);
876 
877     smtx.lock_shared();
878     EXPECT_EQ(x, 0);
879     smtx.unlock_shared();
880 
881     smtx.lock();
882     EXPECT_EQ(x, N);
883     smtx.unlock();
884 
885     ffrt::wait();
886 
887     smtx.lock_shared();
888     EXPECT_EQ(x, N);
889     smtx.unlock_shared();
890 }
891 
TryLockSharedTest(ffrt::shared_mutex& smtx)892 static void TryLockSharedTest(ffrt::shared_mutex& smtx)
893 {
894     int x = 0;
895     const int N = 100;
896 
897     ffrt::submit(
898         [&]() {
899             smtx.lock_shared();
900             ffrt::this_task::sleep_for(20ms);
901             x = N;
902             smtx.unlock_shared();
903         },
904         {}, {});
905     ffrt::this_task::sleep_for(2ms);
906 
907     bool ret = smtx.try_lock_shared();
908     EXPECT_EQ(ret, true);
909     EXPECT_EQ(x, 0);
910     if (ret) {
911         smtx.unlock_shared();
912     }
913     ffrt::wait();
914 
915     ret = smtx.try_lock_shared();
916     EXPECT_EQ(ret, true);
917     EXPECT_EQ(x, N);
918     if (ret) {
919         smtx.unlock_shared();
920     }
921 
922     ffrt::submit(
923         [&]() {
924             smtx.lock();
925             ffrt::this_task::sleep_for(20ms);
926             x = 0;
927             smtx.unlock();
928         },
929         {}, {});
930     ffrt::this_task::sleep_for(2ms);
931 
932     ret = smtx.try_lock_shared();
933     EXPECT_EQ(ret, false);
934     EXPECT_EQ(x, N);
935     if (ret) {
936         smtx.unlock_shared();
937     }
938     ffrt::wait();
939 
940     ret = smtx.try_lock_shared();
941     EXPECT_EQ(ret, true);
942     EXPECT_EQ(x, 0);
943     if (ret) {
944         smtx.unlock_shared();
945     }
946 }
947 
HWTEST_F(SyncTest, sharedMutexTest, TestSize.Level1)948 HWTEST_F(SyncTest, sharedMutexTest, TestSize.Level1)
949 {
950     ffrt::shared_mutex smtx;
951     LockTest(smtx);
952     TryLockTest(smtx);
953     LockSharedTest(smtx);
954     TryLockSharedTest(smtx);
955 }
956 
HWTEST_F(SyncTest, thread1, TestSize.Level1)957 HWTEST_F(SyncTest, thread1, TestSize.Level1)
958 {
959     auto ThreadFunc1 = [](int a, const int& b) {
960         FFRT_LOGW("a = %d, b = %d", a, b);
961         return 0;
962     };
963 
964     auto ThreadFunc2 = [](const char* a, const char* b) {
965         FFRT_LOGW("%s %s", a, b);
966         return 0;
967     };
968 
969     {
970         int value = 0;
971         std::thread th0 {[&value, &ThreadFunc1, &ThreadFunc2] {
972             std::thread th1 {ThreadFunc1, 10, 20};
973             std::thread th2 {ThreadFunc2, "hello", "ffrt"};
974             th1.join();
975             th2.join();
976 
977             value = 123;
978             FFRT_LOGW("value = %d", value);
979         }};
980         th0.join();
981         assert(!th0.joinable());
982         EXPECT_EQ(value, 123);
983     }
984     {
985         int value = 0;
986         ffrt::thread th0 {[&value, &ThreadFunc1, &ThreadFunc2] {
987             ffrt::thread th1 {ThreadFunc1, 10, 20};
988             ffrt::thread th2 {ThreadFunc2, "hello", "ffrt"};
989             th1.join();
990             th2.join();
991 
992             value = 123;
993             FFRT_LOGW("value = %d", value);
994         }};
995         th0.join();
996         assert(!th0.joinable());
997         EXPECT_EQ(value, 123);
998     }
999 }
1000 
f1(int n)1001 void f1(int n)
1002 {
1003     for (int i = 0; i < 5; ++i) {
1004         std::cout << "Thread 1 executing\n";
1005         ++n;
1006         std::this_thread::sleep_for(std::chrono::milliseconds(10));
1007     }
1008 }
1009 
f2(int& n)1010 void f2(int& n)
1011 {
1012     for (int i = 0; i < 5; ++i) {
1013         std::cout << "Thread 2 executing\n";
1014         ++n;
1015         std::this_thread::sleep_for(std::chrono::milliseconds(10));
1016     }
1017 }
1018 
1019 class foo {
1020 public:
bar()1021     void bar()
1022     {
1023         for (int i = 0; i < 5; ++i) {
1024             std::cout << "Thread 3 executing\n";
1025             ++n;
1026             std::this_thread::sleep_for(std::chrono::milliseconds(10));
1027         }
1028     }
1029     int n = 0;
1030 };
1031 
1032 class baz {
1033 public:
operator ()()1034     void operator()()
1035     {
1036         for (int i = 0; i < 5; ++i) {
1037             std::cout << "Thread 4 executing\n";
1038             ++n;
1039             std::this_thread::sleep_for(std::chrono::milliseconds(10));
1040         }
1041     }
1042     int n = 0;
1043 };
1044 
HWTEST_F(SyncTest, thread2, TestSize.Level1)1045 HWTEST_F(SyncTest, thread2, TestSize.Level1)
1046 {
1047     {
1048         int n = 0;
1049         foo f;
1050         baz b;
1051         {
1052             std::thread t2(f1, n + 1);
1053             t2.detach(); // test detach
1054         }
1055         std::thread t1; // t1 is not a thread
1056         std::thread t2(f1, n + 1); // pass by value
1057         std::thread t3(f2, std::ref(n)); // pass by reference
1058         std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
1059         std::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
1060         std::thread t6(b); // t6 runs baz::operator() on a copy of object b
1061         EXPECT_EQ(t1.joinable(), false);
1062         EXPECT_EQ(t2.joinable(), true);
1063         t2.join();
1064         EXPECT_EQ(t2.joinable(), false);
1065         t4.join();
1066         t5.join();
1067         t6.join();
1068         EXPECT_EQ(n, 5);
1069         EXPECT_EQ(f.n, 5);
1070         EXPECT_EQ(b.n, 0);
1071     }
1072     FFRT_LOGW("ffrt version");
1073     {
1074         int n = 0;
1075         foo f;
1076         baz b;
1077         {
1078             ffrt::thread t2(f1, n + 1);
1079             t2.detach(); // test detach
1080         }
1081         ffrt::thread t1; // t1 is not a thread
1082         ffrt::thread t2(f1, n + 1); // pass by value
1083         ffrt::thread t3(f2, std::ref(n)); // pass by reference
1084         ffrt::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
1085         ffrt::thread t5(&foo::bar, &f); // t5 runs foo::bar() on object f
1086         ffrt::thread t6(b); // t6 runs baz::operator() on a copy of object b
1087         EXPECT_EQ(t1.joinable(), false);
1088         EXPECT_EQ(t2.joinable(), true);
1089         t2.join();
1090         EXPECT_EQ(t2.joinable(), false);
1091         EXPECT_EQ(t3.joinable(), false);
1092         EXPECT_EQ(t4.joinable(), true);
1093         t4.join();
1094         EXPECT_EQ(t4.joinable(), false);
1095         t5.join();
1096         t6.join();
1097         EXPECT_EQ(n, 5);
1098         EXPECT_EQ(f.n, 5);
1099         EXPECT_EQ(b.n, 0);
1100     }
1101 }
1102 
HWTEST_F(SyncTest, thread_with_qos, TestSize.Level1)1103 HWTEST_F(SyncTest, thread_with_qos, TestSize.Level1)
1104 {
1105     int a = 0;
1106     auto task = [&] {
1107         a++;
1108     };
1109     ffrt::thread(static_cast<int>(ffrt::qos_user_initiated), task).join();
1110     EXPECT_EQ(1, a);
1111 }
1112 
HWTEST_F(SyncTest, thread_with_name, TestSize.Level1)1113 HWTEST_F(SyncTest, thread_with_name, TestSize.Level1)
1114 {
1115     int a = 0;
1116     auto task = [&] {
1117         a++;
1118     };
1119     std::string name = "thread_test";
1120     ffrt::thread(name.c_str(), static_cast<int>(ffrt::qos_user_initiated), task).join();
1121     EXPECT_EQ(1, a);
1122 }
1123 
1124 struct F {
1125     template<typename T, typename U>
operator ()F1126     void operator()(T, U, int& a)
1127     {
1128         using std::is_same;
1129         using std::reference_wrapper;
1130         static_assert(is_same<T, reference_wrapper<int>>::value, "");
1131         static_assert(is_same<U, reference_wrapper<const int>>::value, "");
1132         a++;
1133     }
1134 };
1135 
HWTEST_F(SyncTest, thread_with_ref_check, TestSize.Level1)1136 HWTEST_F(SyncTest, thread_with_ref_check, TestSize.Level1)
1137 {
1138     int a = 0;
1139     ffrt::thread t(F{}, std::ref(a), std::cref(a), std::ref(a));
1140     t.join();
1141     EXPECT_EQ(1, a);
1142 }
1143 
1144 struct A {
1145     A() = default;
1146     explicit A(const A&) = default;
1147 };
1148 
func(const A&)1149 void func(const A&) { }
1150 
HWTEST_F(SyncTest, thread_with_ref, TestSize.Level1)1151 HWTEST_F(SyncTest, thread_with_ref, TestSize.Level1)
1152 {
1153     ffrt::thread t(func, A{});
1154     t.join();
1155 }
1156 
HWTEST_F(SyncTest, future_wait, TestSize.Level1)1157 HWTEST_F(SyncTest, future_wait, TestSize.Level1)
1158 {
1159     ffrt::packaged_task<int()> task([] { return 7; });
1160     ffrt::future<int> f1 = task.get_future();
1161     ffrt::thread t(std::move(task));
1162 
1163     ffrt::future<int> f2 = ffrt::async([] { return 8; });
1164 
1165     ffrt::promise<int> p;
1166     ffrt::future<int> f3 = p.get_future();
1167     ffrt::thread([&p] { p.set_value(9); }).detach();
1168 
1169     std::cout << "Waiting..." << std::flush;
1170     f1.wait();
1171     f2.wait();
1172     f3.wait();
1173     std::cout << "Done!\nResults are: "
1174               << f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
1175     t.join();
1176 }
1177