• 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 <memory>
17 #include <vector>
18 #include <cstdarg>
19 
20 #include "ffrt_inner.h"
21 #include "cpp/task.h"
22 
23 #include "internal_inc/osal.h"
24 #include "sync/io_poller.h"
25 #include "sched/qos.h"
26 #include "dependence_manager.h"
27 #include "task_attr_private.h"
28 #include "internal_inc/config.h"
29 #include "eu/osattr_manager.h"
30 #include "dfx/log/ffrt_log_api.h"
31 #include "queue/serial_task.h"
32 #include "eu/func_manager.h"
33 
34 namespace ffrt {
35 template <int WITH_HANDLE>
submit_impl(ffrt_task_handle_t & handle,ffrt_function_header_t * f,const ffrt_deps_t * ins,const ffrt_deps_t * outs,const task_attr_private * attr)36 inline void submit_impl(ffrt_task_handle_t &handle, ffrt_function_header_t *f,
37     const ffrt_deps_t *ins, const ffrt_deps_t *outs, const task_attr_private *attr)
38 {
39     DependenceManager::Instance()->onSubmit<WITH_HANDLE>(handle, f, ins, outs, attr);
40 }
41 
42 API_ATTRIBUTE((visibility("default")))
sync_io(int fd)43 void sync_io(int fd)
44 {
45     ffrt_wait_fd(fd);
46 }
47 
48 API_ATTRIBUTE((visibility("default")))
set_trace_tag(const std::string & name)49 void set_trace_tag(const std::string& name)
50 {
51     TaskCtx* curTask = ffrt::ExecuteCtx::Cur()->task;
52     if (curTask != nullptr) {
53         curTask->SetTraceTag(name);
54     }
55 }
56 
57 API_ATTRIBUTE((visibility("default")))
clear_trace_tag()58 void clear_trace_tag()
59 {
60     TaskCtx* curTask = ffrt::ExecuteCtx::Cur()->task;
61     if (curTask != nullptr) {
62         curTask->ClearTraceTag();
63     }
64 }
65 
create_delay_deps(ffrt_task_handle_t & handle,const ffrt_deps_t * in_deps,const ffrt_deps_t * out_deps,task_attr_private * p)66 void create_delay_deps(
67     ffrt_task_handle_t &handle, const ffrt_deps_t *in_deps, const ffrt_deps_t *out_deps, task_attr_private *p)
68 {
69     // setting dependences is not supportted for delayed task
70     if (unlikely(((in_deps != nullptr) && (in_deps->len != 0)) || ((out_deps != nullptr) && (out_deps->len != 0)))) {
71         FFRT_LOGE("delayed task not support dependence, in_deps/out_deps ignored.");
72     }
73 
74     // delay task
75     uint64_t delayUs = p->delay_;
76     std::function<void()> &&func = [delayUs]() {
77         this_task::sleep_for(std::chrono::microseconds(delayUs));
78         FFRT_LOGI("submit task delay time [%d us] has ended.", delayUs);
79     };
80     ffrt_function_header_t *delay_func = create_function_wrapper(std::move(func));
81     submit_impl<1>(handle, delay_func, nullptr, nullptr, reinterpret_cast<task_attr_private *>(p));
82 }
83 } // namespace ffrt
84 
85 #ifdef __cplusplus
86 extern "C" {
87 #endif
88 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_init(ffrt_task_attr_t * attr)89 int ffrt_task_attr_init(ffrt_task_attr_t *attr)
90 {
91     if (!attr) {
92         FFRT_LOGE("attr should be a valid address");
93         return -1;
94     }
95     static_assert(sizeof(ffrt::task_attr_private) <= ffrt_task_attr_storage_size,
96         "size must be less than ffrt_task_attr_storage_size");
97 
98     new (attr)ffrt::task_attr_private();
99     return 0;
100 }
101 
102 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_destroy(ffrt_task_attr_t * attr)103 void ffrt_task_attr_destroy(ffrt_task_attr_t *attr)
104 {
105     if (!attr) {
106         FFRT_LOGE("attr should be a valid address");
107         return;
108     }
109     auto p = reinterpret_cast<ffrt::task_attr_private *>(attr);
110     p->~task_attr_private();
111 }
112 
113 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_name(ffrt_task_attr_t * attr,const char * name)114 void ffrt_task_attr_set_name(ffrt_task_attr_t *attr, const char *name)
115 {
116     if (!attr || !name) {
117         FFRT_LOGE("attr or name not valid");
118         return;
119     }
120     (reinterpret_cast<ffrt::task_attr_private *>(attr))->name_ = name;
121 }
122 
123 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_name(const ffrt_task_attr_t * attr)124 const char *ffrt_task_attr_get_name(const ffrt_task_attr_t *attr)
125 {
126     if (!attr) {
127         FFRT_LOGE("attr should be a valid address");
128         return nullptr;
129     }
130     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
131     return (reinterpret_cast<ffrt::task_attr_private *>(p))->name_.c_str();
132 }
133 
134 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_qos(ffrt_task_attr_t * attr,ffrt_qos_t qos)135 void ffrt_task_attr_set_qos(ffrt_task_attr_t *attr, ffrt_qos_t qos)
136 {
137     if (!attr) {
138         FFRT_LOGE("attr should be a valid address");
139         return;
140     }
141     ffrt::QoS _qos = ffrt::QoS(qos);
142     (reinterpret_cast<ffrt::task_attr_private *>(attr))->qos_ = _qos();
143 }
144 
145 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_qos(const ffrt_task_attr_t * attr)146 ffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t *attr)
147 {
148     if (!attr) {
149         FFRT_LOGE("attr should be a valid address");
150         return static_cast<int>(ffrt_qos_default);
151     }
152     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
153     return static_cast<ffrt_qos_t>((reinterpret_cast<ffrt::task_attr_private *>(p))->qos_);
154 }
155 
156 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_delay(ffrt_task_attr_t * attr,uint64_t delay_us)157 void ffrt_task_attr_set_delay(ffrt_task_attr_t *attr, uint64_t delay_us)
158 {
159     if (!attr) {
160         FFRT_LOGE("attr should be a valid address");
161         return;
162     }
163     (reinterpret_cast<ffrt::task_attr_private *>(attr))->delay_ = delay_us;
164 }
165 
166 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_delay(const ffrt_task_attr_t * attr)167 uint64_t ffrt_task_attr_get_delay(const ffrt_task_attr_t *attr)
168 {
169     if (!attr) {
170         FFRT_LOGE("attr should be a valid address");
171         return 0;
172     }
173     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
174     return (reinterpret_cast<ffrt::task_attr_private *>(p))->delay_;
175 }
176 
177 // submit
178 API_ATTRIBUTE((visibility("default")))
ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind)179 void *ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind)
180 {
181     if (kind == ffrt_function_kind_general) {
182         return ffrt::SimpleAllocator<ffrt::TaskCtx>::allocMem()->func_storage;
183     }
184 
185     return ffrt::SimpleAllocator<ffrt::SerialTask>::allocMem()->func_storage;
186 }
187 
188 API_ATTRIBUTE((visibility("default")))
ffrt_submit_base(ffrt_function_header_t * f,const ffrt_deps_t * in_deps,const ffrt_deps_t * out_deps,const ffrt_task_attr_t * attr)189 void ffrt_submit_base(ffrt_function_header_t *f, const ffrt_deps_t *in_deps, const ffrt_deps_t *out_deps,
190     const ffrt_task_attr_t *attr)
191 {
192     if (!f) {
193         FFRT_LOGE("function handler should not be empty");
194         return;
195     }
196     ffrt_task_handle_t handle;
197     ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr));
198     if (likely(attr == nullptr || ffrt_task_attr_get_delay(attr) == 0)) {
199         ffrt::submit_impl<0>(handle, f, in_deps, out_deps, p);
200         return;
201     }
202 
203     // task after delay
204     ffrt_task_handle_t delay_handle;
205     ffrt::create_delay_deps(delay_handle, in_deps, out_deps, p);
206     std::vector<ffrt_dependence_t> deps = {{ffrt_dependence_task, delay_handle}};
207     ffrt_deps_t delay_deps {static_cast<uint32_t>(deps.size()), deps.data()};
208     ffrt::submit_impl<0>(handle, f, &delay_deps, nullptr, p);
209     ffrt_task_handle_destroy(delay_handle);
210 }
211 
212 API_ATTRIBUTE((visibility("default")))
ffrt_submit_h_base(ffrt_function_header_t * f,const ffrt_deps_t * in_deps,const ffrt_deps_t * out_deps,const ffrt_task_attr_t * attr)213 ffrt_task_handle_t ffrt_submit_h_base(ffrt_function_header_t *f, const ffrt_deps_t *in_deps,
214     const ffrt_deps_t *out_deps, const ffrt_task_attr_t *attr)
215 {
216     if (!f) {
217         FFRT_LOGE("function handler should not be empty");
218         return nullptr;
219     }
220     ffrt_task_handle_t handle;
221     ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr));
222     if (likely(attr == nullptr || ffrt_task_attr_get_delay(attr) == 0)) {
223         ffrt::submit_impl<1>(handle, f, in_deps, out_deps, p);
224         return handle;
225     }
226 
227     // task after delay
228     ffrt_task_handle_t delay_handle;
229     ffrt::create_delay_deps(delay_handle, in_deps, out_deps, p);
230     std::vector<ffrt_dependence_t> deps = {{ffrt_dependence_task, delay_handle}};
231     ffrt_deps_t delay_deps {static_cast<uint32_t>(deps.size()), deps.data()};
232     ffrt::submit_impl<1>(handle, f, &delay_deps, nullptr, p);
233     ffrt_task_handle_destroy(delay_handle);
234     return handle;
235 }
236 
237 API_ATTRIBUTE((visibility("default")))
ffrt_task_handle_destroy(ffrt_task_handle_t handle)238 void ffrt_task_handle_destroy(ffrt_task_handle_t handle)
239 {
240     if (!handle) {
241         FFRT_LOGE("input task handle is invalid");
242         return;
243     }
244     static_cast<ffrt::TaskCtx*>(handle)->DecDeleteRef();
245 }
246 
247 // wait
248 API_ATTRIBUTE((visibility("default")))
ffrt_wait_deps(const ffrt_deps_t * deps)249 void ffrt_wait_deps(const ffrt_deps_t *deps)
250 {
251     if (!deps) {
252         FFRT_LOGE("deps should not be empty");
253         return;
254     }
255     std::vector<ffrt_dependence_t> v(deps->len);
256     for (uint64_t i = 0; i < deps->len; ++i) {
257         v[i] = deps->items[i];
258     }
259     ffrt_deps_t d = { deps->len, v.data() };
260     ffrt::DependenceManager::Instance()->onWait(&d);
261 }
262 
263 API_ATTRIBUTE((visibility("default")))
ffrt_wait()264 void ffrt_wait()
265 {
266     ffrt::DependenceManager::Instance()->onWait();
267 }
268 
269 API_ATTRIBUTE((visibility("default")))
ffrt_set_cgroup_attr(ffrt_qos_t qos,ffrt_os_sched_attr * attr)270 int ffrt_set_cgroup_attr(ffrt_qos_t qos, ffrt_os_sched_attr *attr)
271 {
272     if (!attr) {
273         FFRT_LOGE("attr should not be empty");
274         return -1;
275     }
276     ffrt::QoS _qos = ffrt::QoS(qos);
277     return ffrt::OSAttrManager::Instance()->UpdateSchedAttr(_qos, attr);
278 }
279 
280 API_ATTRIBUTE((visibility("default")))
ffrt_this_task_update_qos(int qos_)281 int ffrt_this_task_update_qos(int qos_)
282 {
283     ffrt::QoS _qos = ffrt::QoS(qos_);
284     auto curTask = ffrt::ExecuteCtx::Cur()->task;
285     if (curTask == nullptr) {
286         FFRT_LOGW("task is nullptr");
287         return 1;
288     }
289 
290     if (_qos() == curTask->qos) {
291         FFRT_LOGW("the target qos is euqal to current qos, no need update");
292         return 0;
293     }
294 
295     curTask->SetQos(_qos);
296     ffrt_yield();
297 
298     return 0;
299 }
300 
301 API_ATTRIBUTE((visibility("default")))
ffrt_this_task_get_id()302 uint64_t ffrt_this_task_get_id()
303 {
304     auto curTask = ffrt::ExecuteCtx::Cur()->task;
305     if (curTask == nullptr) {
306         return 0;
307     }
308 
309     return curTask->gid;
310 }
311 
312 API_ATTRIBUTE((visibility("default")))
ffrt_skip(ffrt_task_handle_t handle)313 int ffrt_skip(ffrt_task_handle_t handle)
314 {
315     if (!handle) {
316         FFRT_LOGE("input ffrt task handle is invalid.");
317         return -1;
318     }
319     ffrt::TaskCtx *task = static_cast<ffrt::TaskCtx*>(handle);
320     auto exp = ffrt::SkipStatus::SUBMITTED;
321     if (__atomic_compare_exchange_n(&task->skipped, &exp, ffrt::SkipStatus::SKIPPED, 0, __ATOMIC_ACQUIRE,
322         __ATOMIC_RELAXED)) {
323         return 0;
324     }
325     FFRT_LOGE("skip task [%lu] faild", task->gid);
326     return 1;
327 }
328 
329 API_ATTRIBUTE((visibility("default")))
ffrt_executor_task_submit(ffrt_executor_task_t * task,const ffrt_task_attr_t * attr)330 void ffrt_executor_task_submit(ffrt_executor_task_t *task, const ffrt_task_attr_t *attr)
331 {
332     if (!task) {
333         FFRT_LOGE("function handler should not be empty");
334         return;
335     }
336     ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr));
337     if (likely(attr == nullptr || ffrt_task_attr_get_delay(attr) == 0)) {
338         ffrt::DependenceManager::Instance()->onSubmitUV(task, p);
339         return;
340     }
341     FFRT_LOGE("uv function not supports delay");
342     return;
343 }
344 
345 API_ATTRIBUTE((visibility("default")))
ffrt_executor_task_register_func(ffrt_executor_task_func func,ffrt_executor_task_type_t type)346 void ffrt_executor_task_register_func(ffrt_executor_task_func func, ffrt_executor_task_type_t type)
347 {
348     ffrt::FuncManager* func_mg = ffrt::FuncManager::Instance();
349     func_mg->insert(type, func);
350 }
351 
352 API_ATTRIBUTE((visibility("default")))
ffrt_executor_task_cancel(ffrt_executor_task_t * task,const ffrt_qos_t qos)353 int ffrt_executor_task_cancel(ffrt_executor_task_t *task, const ffrt_qos_t qos)
354 {
355     ffrt::QoS _qos = ffrt::QoS(qos);
356 
357     ffrt::LinkedList* node = (ffrt::LinkedList *)(&task->wq);
358     ffrt::FFRTScheduler* sch = ffrt::FFRTScheduler::Instance();
359     return (int)(sch->RemoveNode(node, _qos));
360 }
361 #ifdef __cplusplus
362 }
363 #endif