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 <thread>
17 #include <chrono>
18 #include <gtest/gtest.h>
19 #include <sys/eventfd.h>
20 #include <sys/epoll.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <cstdint>
24 #include "c/executor_task.h"
25 #include "ffrt_inner.h"
26 #include "eu/cpu_monitor.h"
27 #include "eu/cpu_worker.h"
28 #include "eu/co_routine.h"
29 #include "eu/scpuworker_manager.h"
30 #include "sched/scheduler.h"
31 #include "../common.h"
32 #include "tm/scpu_task.h"
33
34 using namespace std;
35 using namespace ffrt;
36 using namespace testing;
37 #ifdef HWTEST_TESTING_EXT_ENABLE
38 using namespace testing::ext;
39 #endif
40 #ifdef APP_USE_ARM
41 #define SIZEOF_BYTES sizeof(uint32_t)
42 #else
43 #define SIZEOF_BYTES sizeof(uint64_t)
44 #endif
45 class CoroutineTest : 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 constexpr int BLOCKED_COUNT = 3;
64
65 typedef struct {
66 int count;
67 std::mutex lock;
68 } StacklessCoroutine1;
69
stackless_coroutine(void * co)70 ffrt_coroutine_ret_t stackless_coroutine(void* co)
71 {
72 StacklessCoroutine1* stacklesscoroutine = reinterpret_cast<StacklessCoroutine1*>(co);
73 std::lock_guard lg(stacklesscoroutine->lock);
74 printf("stacklesscoroutine %d\n", stacklesscoroutine->count);
75 stacklesscoroutine->count++;
76 if (stacklesscoroutine->count < BLOCKED_COUNT) {
77 ffrt_wake_coroutine(ffrt_get_current_task());
78 return ffrt_coroutine_pending;
79 } else if (stacklesscoroutine->count == BLOCKED_COUNT) {
80 ffrt_wake_coroutine(ffrt_get_current_task());
81 return ffrt_coroutine_pending;
82 } else {
83 return ffrt_coroutine_ready;
84 }
85 return ffrt_coroutine_pending;
86 }
87
exec_stackless_coroutine(void * co)88 ffrt_coroutine_ret_t exec_stackless_coroutine(void *co)
89 {
90 return stackless_coroutine(co);
91 }
92
destroy_stackless_coroutine(void * co)93 void destroy_stackless_coroutine(void *co)
94 {
95 }
96
97 HWTEST_F(CoroutineTest, coroutine_submit_succ, TestSize.Level1)
98 {
99 // coroutine_submit_004
100 StacklessCoroutine1 co1 = {0};
101 StacklessCoroutine1 co2 = {0};
102 ffrt_task_attr_t attr;
103 ffrt_task_attr_init(&attr);
104 ffrt_submit_coroutine((void *)&co1, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
105 ffrt_submit_coroutine((void *)&co2, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
106 // ffrt_poller_wakeup_001
107 ffrt_poller_wakeup(ffrt_qos_default);
108 usleep(100000);
109 EXPECT_EQ(co1.count, 4);
110 EXPECT_EQ(co2.count, 4);
111
112 ffrt_wake_coroutine(nullptr);
113 }
114
115 HWTEST_F(CoroutineTest, coroutine_submit_fail, TestSize.Level1)
116 {
117 // get_task_001
118 EXPECT_EQ(ffrt_get_current_task(), nullptr);
119
120 ffrt_task_attr_t attr;
121 ffrt_task_attr_init(&attr);
122
123 // coroutine_submit_001
124 ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
125 ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
126 }
127
128 struct TestData {
129 int fd;
130 uint64_t expected;
131 };
132
testCallBack(void * token,uint32_t event)133 static void testCallBack(void* token, uint32_t event)
134 {
135 struct TestData* testData = reinterpret_cast<TestData*>(token);
136 uint64_t value = 0;
137 ssize_t n = read(testData->fd, &value, sizeof(uint64_t));
138 EXPECT_EQ(n, sizeof(value));
139 EXPECT_EQ(value, testData->expected);
140 printf("cb done\n");
141 }
142
143 HWTEST_F(CoroutineTest, ffrt_epoll_ctl_add_del, TestSize.Level1)
144 {
145 uint64_t expected = 0xabacadae;
146 int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
147
__anoncbec3f170202() 148 ffrt::submit([&]() {
149 ssize_t n = write(testFd, &expected, sizeof(uint64_t));
150 EXPECT_EQ(sizeof(n), SIZEOF_BYTES);
151 }, {}, {});
152
153 struct TestData testData {.fd = testFd, .expected = expected};
154 // poller_register_001
155 ffrt_epoll_ctl(ffrt_qos_default, EPOLL_CTL_ADD, testFd, EPOLLIN, reinterpret_cast<void*>(&testData), testCallBack);
156
157 usleep(100);
158
159 // poller_deregister_001
160 ffrt_epoll_ctl(ffrt_qos_default, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr);
161 close(testFd);
162 }