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