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