• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"ffrt.h"
20 
21 using namespace std;
22 using namespace ffrt;
23 using namespace testing;
24 
25 class CoroutineTest : public testing::Test {
26 protected:
SetUpTestCase()27     static void SetUpTestCase()
28     {
29     }
30 
TearDownTestCase()31     static void TearDownTestCase()
32     {
33     }
34 
SetUp()35     virtual void SetUp()
36     {
37     }
38 
TeadDown()39     virtual void TeadDown()
40     {
41     }
42 };
43 
44 const int BLOCKED_COUNT = 3;
45 
46 typedef struct {
47     int count;
48 }StacklessCoroutine1;
49 
stackless_coroutine(void * co)50 ffrt_coroutine_ret_t stackless_coroutine(void *co)
51 {
52     ((StacklessCoroutine1*)(co))->count++;
53 
54     if (((StacklessCoroutine1*)(co))->count < BLOCKED_COUNT) {
55         ffrt_wake_coroutine(ffrt_task_get());
56         return ffrt_coroutine_pending;
57     } else if (((StacklessCoroutine1*)(co))->count == BLOCKED_COUNT) {
58         ffrt_wake_coroutine(ffrt_task_get());
59         return ffrt_coroutine_pending;
60     } else {
61         ffrt_wake_coroutine(ffrt_task_get());
62         return ffrt_coroutine_ready;
63     }
64     return ffrt_coroutine_pending;
65 }
66 
exec_stackless_coroutine(void * co)67 ffrt_coroutine_ret_t exec_stackless_coroutine(void *co)
68 {
69     return stackless_coroutine(co);
70 }
71 
destroy_stackless_coroutine(void * co)72 void destroy_stackless_coroutine(void *co)
73 {
74 }
75 
TEST_F(CoroutineTest,coroutine_submit_succ)76 TEST_F(CoroutineTest, coroutine_submit_succ)
77 {
78     StacklessCoroutine1 co1 = {0};
79     StacklessCoroutine1 co2 = {0};
80     ffrt_task_attr_t attr;
81     ffrt_task_attr_init(&attr);
82     ffrt_task_attr_set_name(&attr, "stackless_coroutine");
83     ffrt_task_attr_set_coroutine_type(&attr, ffrt_coroutine_stackless);
84     int coroutine_type_ = ffrt_task_attr_get_coroutine_type(&attr);
85     ffrt_submit_coroutine((void *)co1, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
86     ffrt_task_handle_t task1 = ffrt_submit_h_coroutine((void *)co2, exec_stackless_coroutine,
87         destroy_stackless_coroutine, NULL, NULL, &attr);
88     ffrt_wait();
89     ffrt_task_handle_destroy(task1);
90     EXPECT_EQ(coroutine_type_, 0);
91     EXPECT_EQ(co1.count, 4);
92     EXPECT_EQ(co2.count, 4);
93 }
94 
TEST_F(CoroutineTest,coroutine_submit_fail)95 TEST_F(CoroutineTest, coroutine_submit_fail)
96 {
97     ffrt_task_get();
98     ffrt_task_handle_destroy(nullptr);
99 
100     StacklessCoroutine1 co1 = {0};
101     StacklessCoroutine1 co2 = {0};
102     StacklessCoroutine1 co3 = {0};
103     StacklessCoroutine1 co4 = {0};
104     StacklessCoroutine1 co5 = {0};
105     ffrt_task_attr_t attr;
106     ffrt_task_attr_init(&attr);
107     ffrt_task_attr_set_name(&attr, "stackless_coroutine");
108     ffrt_task_attr_set_coroutine_type(&attr, ffrt_coroutine_stackless);
109 
110     ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
111     ffrt_task_handle_t task1 = ffrt_submit_h_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
112     ffrt_task_handle_destroy(task1);
113 
114     ffrt_submit_coroutine((void *)&co1, nullptr, nullptr, NULL, NULL, &attr);
115     ffrt_task_handle_t task2 = ffrt_submit_h_coroutine((void *)&co2, nullptr, nullptr, NULL, NULL, &attr);
116     ffrt_task_handle_destroy(task2);
117 
118     ffrt_submit_coroutine((void *)&co3, exec_stackless_coroutine, nullptr, NULL, NULL, &attr);
119     ffrt_task_handle_t task3 = ffrt_submit_h_coroutine((void *)&co4, exec_stackless_coroutine,
120         nullptr, NULL, NULL, &attr);
121     ffrt_task_handle_destroy(task3);
122 
123     ffrt_task_attr_t attr_stackfull;
124     ffrt_task_attr_init(&attr_stackfull);
125     ffrt_task_attr_set_name(&attr_stackfull, "stackfull_coroutine");
126     ffrt_task_attr_set_coroutine_type(&attr_stackfull, ffrt_coroutine_stackfull);
127     ffrt_submit_coroutine((void *)&co5, nullptr, nullptr, NULL, NULL, &attr_stackfull);
128     ffrt_task_handle_t task_stackfull = ffrt_submit_h_coroutine((void *)&co6, nullptr, nullptr,
129         NULL, NULL, &attr_stackfull);
130     ffrt_task_attr_destroy(task_stackfull);
131 }
132 
133 StacklessCoroutine1 g_col = {0};
134 struct Waker {
135     void *phandle;
136     void *handle;
137 } waker;
138 
wake_stackless_coroutine(void * arg)139 void wake_stackless_coroutine(void *arg)
140 {
141     ffrt_wake_coroutine(((Waker *)arg)->phandle);
142 }
143 
destroy_wake_of_stackless_coroutine(void * arg)144 void destroy_wake_of_stackless_coroutine(void *arg)
145 {
146     ffrt_task_handle_destroy(((Waker *)arg)->handle);
147 }
148 
maintask_stackless_coroutine(void * co)149 ffrt_coroutine_ret_t maintask_stackless_coroutine(void *co)
150 {
151     ((StacklessCoroutine1*)(co))->count++;
152 
153     if (((StacklessCoroutine1*)(co))->count < BLOCKED_COUNT) {
154         if (((StacklessCoroutine1*)(co))->count == 1) {
155             ffrt_task_attr_t attr;
156             ffrt_task_attr_init(&attr);
157             ffrt_task_attr_set_name(&attr, "stackless_coroutine");
158             ffrt_task_attr_set_coroutine_type(&attr, ffrt_coroutine_stackless);
159             ffrt_set_wake_flag(true);
160             ffrt_task_handle_t h = ffrt_submit_h_coroutine((void *)&g_col, exec_stackless_coroutine,
161                 destroy_stackless_coroutine, NULL, NULL, &attr);
162             waker.phandle = ffrt_task_get();
163             waker.handle = h;
164             ffrt_wake_by_handle(&waker, wake_stackless_coroutine, destroy_wake_of_stackless_coroutine, h);
165             ffrt_wake_coroutine(ffrt_task_get());
166             return ffrt_coroutine_pending;
167         }
168         ffrt_wake_coroutine(ffrt_task_get());
169         return ffrt_coroutine_pending;
170     } else if (((StacklessCoroutine1*)(co))->count == BLOCKED_COUNT) {
171         ffrt_wake_coroutine(ffrt_task_get());
172         return ffrt_coroutine_pending;
173     } else {
174         ffrt_wake_coroutine(ffrt_task_get());
175         return ffrt_coroutine_ready;
176     }
177     return ffrt_coroutine_pending;
178 }
179 
maintask_exec_stackless_coroutine(void * co)180 ffrt_coroutine_ret_t maintask_exec_stackless_coroutine(void *co)
181 {
182     return maintask_stackless_coroutine(co);
183 }
184 
maintask_destroy_stackless_coroutine(void * co)185 void maintask_destroy_stackless_coroutine(void *co)
186 {
187 }
188 
TEST_F(CoroutineTest,coroutine_wake_by_handle_succ)189 TEST_F(CoroutineTest, coroutine_wake_by_handle_succ)
190 {
191     StacklessCoroutine1 co1 = {0};
192     ffrt_task_attr_t maintask_attr;
193     ffrt_task_attr_init(&maintask_attrr);
194     ffrt_task_attr_set_name(&maintask_attr, "stackless_coroutine_maintask");
195     ffrt_task_attr_set_coroutine_type(&maintask_attr, ffrt_coroutine_stackless);
196     ffrt_task_handle_t maintask = ffrt_submit_h_coroutine((void *)&co1, maintask_exec_stackless_coroutine,
197         maintask_destroy_stackless_coroutine, NULL, NULL, &maintask_attr);
198     ffrt_wait();
199     ffrt_task_handle_destroy(maintask);
200     EXPECT_EQ(co1.count, 4);
201 }
202 
maintask_stackless_coroutine_fail(void * co)203 ffrt_coroutine_ret_t maintask_stackless_coroutine_fail(void *co)
204 {
205     ((StacklessCoroutine1*)(co))->count++;
206 
207     if (((StacklessCoroutine1*)(co))->count < BLOCKED_COUNT) {
208             if (((StacklessCoroutine1*)(co))->count == 1) {
209                 ffrt_task_attr_t attr;
210                 ffrt_task_attr_init(&attr);
211                 ffrt_task_attr_set_name(&attr, "stackless_coroutine");
212                 ffrt_task_attr_set_coroutine_type(&attr, ffrt_coroutine_stackless);
213                 ffrt_task_handle_t h = ffrt_submit_h_coroutine((void *)&g_col, exec_stackless_coroutine,
214                     destroy_stackless_coroutine, NULL, NULL, &attr);
215                 waker.phandle = ffrt_task_get();
216                 waker.handle = h;
217 
218                 ffrt_wake_by_handle(nullptr, nullptr, nullptr, nullptr);
219                 ffrt_wake_by_handle(&waker, nullptr, nullptr, h);
220                 ffrt_wake_by_handle(nullptr, nullptr, nullptr, nullptr);
221                 ffrt_wake_by_handle(&waker, nullptr, nullptr, h);
222                 ffrt_wake_by_handle(&waker, wake_stackless_coroutine, nullptr, h);
223                 ffrt_wake_by_handle(&waker, wake_stackless_coroutine, destroy_wake_of_stackless_coroutine, h);
224                 ffrt_wake_coroutine(ffrt_task_get());
225                 return ffrt_coroutine_pending;
226             }
227             ffrt_wake_coroutine(ffrt_task_get());
228             return ffrt_coroutine_pending;
229         } else if (((StacklessCoroutine1*)(co))->count == BLOCKED_COUNT) {
230             ffrt_wake_coroutine(ffrt_task_get());
231             return ffrt_coroutine_pending;
232         } else {
233             ffrt_wake_coroutine(ffrt_task_get());
234             return ffrt_coroutine_ready;
235         }
236         return ffrt_coroutine_pending;
237 }
238 
maintask_exec_stackless_coroutine_fail(void * co)239 ffrt_coroutine_ret_t maintask_exec_stackless_coroutine_fail(void *co)
240 {
241     return maintask_stackless_coroutine_fail(co);
242 }
243 
maintask_destroy_stackless_coroutine_fail(void * co)244 void maintask_destroy_stackless_coroutine_fail(void *co)
245 {
246 }
247 
TEST_F(CoroutineTest,coroutine_wake_by_handle_fail)248 TEST_F(CoroutineTest, coroutine_wake_by_handle_fail)
249 {
250     StacklessCoroutine1 co1 = {0};
251     ffrt_task_attr_t maintask_attr;
252     ffrt_task_attr_init(&maintask_attrr);
253     ffrt_task_attr_set_name(&maintask_attr, "stackless_coroutine_maintask");
254     ffrt_task_attr_set_coroutine_type(&maintask_attr, ffrt_coroutine_stackless);
255     ffrt_task_handle_t maintask = ffrt_submit_h_coroutine((void *)&co1, maintask_exec_stackless_coroutine_fail,
256         maintask_destroy_stackless_coroutine_fail, NULL, NULL, &maintask_attr);
257     ffrt_wait();
258     ffrt_task_handle_destroy(maintask);
259 }
260 
TEST_F(CoroutineTest,set_get_coroutine_type_fail)261 TEST_F(CoroutineTest, set_get_coroutine_type_fail)
262 {
263     ffrt_task_attr_t attr;
264     ffrt_task_attr_init(&attr);
265     ffrt_task_attr_set_name(&attr, "stackless_coroutine");
266     ffrt_task_attr_set_coroutine_type(nullptr, ffrt_coroutine_stackless);
267     ffrt_task_attr_get_coroutine_type(nullptr);
268 }