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¬ifyone");
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¬ifyone");
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