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 
19 #include "ffrt_inner.h"
20 #include "internal_inc/osal.h"
21 #include "sync/io_poller.h"
22 #include "qos.h"
23 #include "sched/task_scheduler.h"
24 #include "task_attr_private.h"
25 #include "internal_inc/config.h"
26 #include "eu/osattr_manager.h"
27 #include "eu/worker_thread.h"
28 #include "eu/cpu_monitor.h"
29 #include "dfx/log/ffrt_log_api.h"
30 #include "dfx/trace_record/ffrt_trace_record.h"
31 #include "dfx/watchdog/watchdog_util.h"
32 #include "eu/func_manager.h"
33 #include "util/ffrt_facade.h"
34 #include "util/slab.h"
35 #include "eu/sexecute_unit.h"
36 #include "core/task_io.h"
37 #include "sync/poller.h"
38 #include "util/spmc_queue.h"
39 #include "tm/task_factory.h"
40 #include "tm/queue_task.h"
41 
42 namespace ffrt {
submit_impl(bool has_handle, 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)43 inline void submit_impl(bool has_handle, ffrt_task_handle_t &handle, ffrt_function_header_t *f,
44     const ffrt_deps_t *ins, const ffrt_deps_t *outs, const task_attr_private *attr)
45 {
46     FFRTFacade::GetDMInstance().onSubmit(has_handle, handle, f, ins, outs, attr);
47 }
48 
49 API_ATTRIBUTE((visibility("default")))
sync_io(int fd)50 void sync_io(int fd)
51 {
52     ffrt_wait_fd(fd);
53 }
54 
55 API_ATTRIBUTE((visibility("default")))
set_trace_tag(const char* name)56 void set_trace_tag(const char* name)
57 {
58     CPUEUTask* curTask = ffrt::ExecuteCtx::Cur()->task;
59     if (curTask != nullptr) {
60         curTask->SetTraceTag(name);
61     }
62 }
63 
64 API_ATTRIBUTE((visibility("default")))
clear_trace_tag()65 void clear_trace_tag()
66 {
67     CPUEUTask* curTask = ffrt::ExecuteCtx::Cur()->task;
68     if (curTask != nullptr) {
69         curTask->ClearTraceTag();
70     }
71 }
72 
CreateDelayDeps( ffrt_task_handle_t &handle, const ffrt_deps_t *in_deps, const ffrt_deps_t *out_deps, task_attr_private *p)73 void CreateDelayDeps(
74     ffrt_task_handle_t &handle, const ffrt_deps_t *in_deps, const ffrt_deps_t *out_deps, task_attr_private *p)
75 {
76     // setting dependences is not supportted for delayed task
77     if (unlikely(((in_deps != nullptr) && (in_deps->len != 0)) || ((out_deps != nullptr) && (out_deps->len != 0)))) {
78         FFRT_LOGE("delayed task do not support dependence, in_deps/out_deps ignored.");
79     }
80 
81     // delay task
82     uint64_t delayUs = p->delay_;
83     std::function<void()> &&func = [delayUs]() {
84         this_task::sleep_for(std::chrono::microseconds(delayUs));
85         FFRT_LOGD("submit task delay time [%d us] has ended.", delayUs);
86     };
87     ffrt_function_header_t *delay_func = create_function_wrapper(std::move(func));
88     submit_impl(true, handle, delay_func, nullptr, nullptr, reinterpret_cast<task_attr_private *>(p));
89 }
90 } // namespace ffrt
91 
92 #ifdef __cplusplus
93 extern "C" {
94 #endif
95 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_init(ffrt_task_attr_t *attr)96 int ffrt_task_attr_init(ffrt_task_attr_t *attr)
97 {
98     if (unlikely(!attr)) {
99         FFRT_LOGE("attr should be a valid address");
100         return -1;
101     }
102     static_assert(sizeof(ffrt::task_attr_private) <= ffrt_task_attr_storage_size,
103         "size must be less than ffrt_task_attr_storage_size");
104 
105     new (attr)ffrt::task_attr_private();
106     return 0;
107 }
108 
109 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_destroy(ffrt_task_attr_t *attr)110 void ffrt_task_attr_destroy(ffrt_task_attr_t *attr)
111 {
112     if (unlikely(!attr)) {
113         FFRT_LOGE("attr should be a valid address");
114         return;
115     }
116     auto p = reinterpret_cast<ffrt::task_attr_private *>(attr);
117     p->~task_attr_private();
118 }
119 
120 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_name(ffrt_task_attr_t *attr, const char *name)121 void ffrt_task_attr_set_name(ffrt_task_attr_t *attr, const char *name)
122 {
123     if (unlikely(!attr || !name)) {
124         FFRT_LOGE("invalid attr or name");
125         return;
126     }
127     (reinterpret_cast<ffrt::task_attr_private *>(attr))->name_ = name;
128 }
129 
130 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_name(const ffrt_task_attr_t *attr)131 const char *ffrt_task_attr_get_name(const ffrt_task_attr_t *attr)
132 {
133     if (unlikely(!attr)) {
134         FFRT_LOGE("attr should be a valid address");
135         return nullptr;
136     }
137     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
138     return (reinterpret_cast<ffrt::task_attr_private *>(p))->name_.c_str();
139 }
140 
141 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_qos(ffrt_task_attr_t *attr, ffrt_qos_t qos)142 void ffrt_task_attr_set_qos(ffrt_task_attr_t *attr, ffrt_qos_t qos)
143 {
144     if (unlikely(!attr)) {
145         FFRT_LOGE("attr should be a valid address");
146         return;
147     }
148     if (ffrt::GetFuncQosMap() == nullptr) {
149         FFRT_LOGE("FuncQosMap has not regist");
150         return;
151     }
152     (reinterpret_cast<ffrt::task_attr_private *>(attr))->qos_ = ffrt::GetFuncQosMap()(qos);
153 }
154 
155 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_qos(const ffrt_task_attr_t *attr)156 ffrt_qos_t ffrt_task_attr_get_qos(const ffrt_task_attr_t *attr)
157 {
158     if (unlikely(!attr)) {
159         FFRT_LOGE("attr should be a valid address");
160         return static_cast<int>(ffrt_qos_default);
161     }
162     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
163     return (reinterpret_cast<ffrt::task_attr_private *>(p))->qos_;
164 }
165 
166 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_delay(ffrt_task_attr_t *attr, uint64_t delay_us)167 void ffrt_task_attr_set_delay(ffrt_task_attr_t *attr, uint64_t delay_us)
168 {
169     if (unlikely(!attr)) {
170         FFRT_LOGE("attr should be a valid address");
171         return;
172     }
173     (reinterpret_cast<ffrt::task_attr_private *>(attr))->delay_ = delay_us;
174 }
175 
176 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_delay(const ffrt_task_attr_t *attr)177 uint64_t ffrt_task_attr_get_delay(const ffrt_task_attr_t *attr)
178 {
179     if (unlikely(!attr)) {
180         FFRT_LOGE("attr should be a valid address");
181         return 0;
182     }
183     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
184     return (reinterpret_cast<ffrt::task_attr_private *>(p))->delay_;
185 }
186 
187 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_timeout(ffrt_task_attr_t *attr, uint64_t timeout_ms)188 void ffrt_task_attr_set_timeout(ffrt_task_attr_t *attr, uint64_t timeout_ms)
189 {
190     if (unlikely(!attr)) {
191         FFRT_LOGE("attr should be a valid address");
192         return;
193     }
194     (reinterpret_cast<ffrt::task_attr_private *>(attr))->timeout_ = timeout_ms;
195 }
196 
197 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_timeout(const ffrt_task_attr_t *attr)198 uint64_t ffrt_task_attr_get_timeout(const ffrt_task_attr_t *attr)
199 {
200     if (unlikely(!attr)) {
201         FFRT_LOGE("attr should be a valid address");
202         return 0;
203     }
204     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
205     return (reinterpret_cast<ffrt::task_attr_private *>(p))->timeout_;
206 }
207 
208 
209 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_notify_worker(ffrt_task_attr_t* attr, bool notify)210 void ffrt_task_attr_set_notify_worker(ffrt_task_attr_t* attr, bool notify)
211 {
212     if (unlikely(!attr)) {
213         FFRT_LOGE("attr should be a valid address");
214         return;
215     }
216     (reinterpret_cast<ffrt::task_attr_private *>(attr))->notifyWorker_ = notify;
217 }
218 
219 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority)220 void ffrt_task_attr_set_queue_priority(ffrt_task_attr_t* attr, ffrt_queue_priority_t priority)
221 {
222     if (unlikely(!attr)) {
223         FFRT_LOGE("attr should be a valid address");
224         return;
225     }
226 
227     // eventhandler inner priority is one more than the kits priority
228     int prio = static_cast<int>(priority);
229     if (prio < static_cast<int>(ffrt_queue_priority_immediate) ||
230         prio > static_cast<int>(ffrt_queue_priority_idle) + 1) {
231         FFRT_LOGE("priority should be a valid priority");
232         return;
233     }
234 
235     (reinterpret_cast<ffrt::task_attr_private *>(attr))->prio_ = priority;
236 }
237 
238 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr)239 ffrt_queue_priority_t ffrt_task_attr_get_queue_priority(const ffrt_task_attr_t* attr)
240 {
241     if (unlikely(!attr)) {
242         FFRT_LOGE("attr should be a valid address");
243         return ffrt_queue_priority_immediate;
244     }
245     ffrt_task_attr_t *p = const_cast<ffrt_task_attr_t *>(attr);
246     return static_cast<ffrt_queue_priority_t>((reinterpret_cast<ffrt::task_attr_private *>(p))->prio_);
247 }
248 
249 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_stack_size(ffrt_task_attr_t* attr, uint64_t size)250 void ffrt_task_attr_set_stack_size(ffrt_task_attr_t* attr, uint64_t size)
251 {
252     if (unlikely(!attr)) {
253         FFRT_LOGE("attr should be a valid address");
254         return;
255     }
256     (reinterpret_cast<ffrt::task_attr_private *>(attr))->stackSize_ = size;
257 }
258 
259 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_stack_size(const ffrt_task_attr_t* attr)260 uint64_t ffrt_task_attr_get_stack_size(const ffrt_task_attr_t* attr)
261 {
262     if (unlikely(!attr)) {
263         FFRT_LOGE("attr should be a valid address");
264         return 0;
265     }
266     return (reinterpret_cast<const ffrt::task_attr_private *>(attr))->stackSize_;
267 }
268 
269 // submit
270 API_ATTRIBUTE((visibility("default")))
ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind)271 void *ffrt_alloc_auto_managed_function_storage_base(ffrt_function_kind_t kind)
272 {
273     if (kind == ffrt_function_kind_general) {
274         return ffrt::TaskFactory::Alloc()->func_storage;
275     }
276     return ffrt::SimpleAllocator<ffrt::QueueTask>::AllocMem()->func_storage;
277 }
278 
279 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)280 void ffrt_submit_base(ffrt_function_header_t *f, const ffrt_deps_t *in_deps, const ffrt_deps_t *out_deps,
281     const ffrt_task_attr_t *attr)
282 {
283     if (unlikely(!f)) {
284         FFRT_LOGE("function handler should not be empty");
285         return;
286     }
287     ffrt_task_handle_t handle;
288     ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr));
289     if (likely(attr == nullptr || ffrt_task_attr_get_delay(attr) == 0)) {
290         ffrt::submit_impl(false, handle, f, in_deps, out_deps, p);
291         return;
292     }
293 
294     // task after delay
295     ffrt_task_handle_t delay_handle;
296     uint64_t timeout = p->timeout_;
297     p->timeout_ = 0;
298     ffrt::CreateDelayDeps(delay_handle, in_deps, out_deps, p);
299     p->timeout_ = timeout;
300     std::vector<ffrt_dependence_t> deps = {{ffrt_dependence_task, delay_handle}};
301     ffrt_deps_t delay_deps {static_cast<uint32_t>(deps.size()), deps.data()};
302     ffrt::submit_impl(false, handle, f, &delay_deps, nullptr, p);
303     ffrt_task_handle_destroy(delay_handle);
304 }
305 
306 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)307 ffrt_task_handle_t ffrt_submit_h_base(ffrt_function_header_t *f, const ffrt_deps_t *in_deps,
308     const ffrt_deps_t *out_deps, const ffrt_task_attr_t *attr)
309 {
310     if (unlikely(!f)) {
311         FFRT_LOGE("function handler should not be empty");
312         return nullptr;
313     }
314     ffrt_task_handle_t handle = nullptr;
315     ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr));
316     if (likely(attr == nullptr || ffrt_task_attr_get_delay(attr) == 0)) {
317         ffrt::submit_impl(true, handle, f, in_deps, out_deps, p);
318         return handle;
319     }
320 
321     // task after delay
322     ffrt_task_handle_t delay_handle = nullptr;
323     uint64_t timeout = p->timeout_;
324     p->timeout_ = 0;
325     ffrt::CreateDelayDeps(delay_handle, in_deps, out_deps, p);
326     p->timeout_ = timeout;
327     std::vector<ffrt_dependence_t> deps = {{ffrt_dependence_task, delay_handle}};
328     ffrt_deps_t delay_deps {static_cast<uint32_t>(deps.size()), deps.data()};
329     ffrt::submit_impl(true, handle, f, &delay_deps, nullptr, p);
330     ffrt_task_handle_destroy(delay_handle);
331     return handle;
332 }
333 
334 API_ATTRIBUTE((visibility("default")))
ffrt_task_handle_inc_ref(ffrt_task_handle_t handle)335 uint32_t ffrt_task_handle_inc_ref(ffrt_task_handle_t handle)
336 {
337     if (handle == nullptr) {
338         FFRT_LOGE("input task handle is invalid");
339         return -1;
340     }
341     return static_cast<ffrt::CPUEUTask*>(handle)->IncDeleteRef();
342 }
343 
344 API_ATTRIBUTE((visibility("default")))
ffrt_task_handle_dec_ref(ffrt_task_handle_t handle)345 uint32_t ffrt_task_handle_dec_ref(ffrt_task_handle_t handle)
346 {
347     if (handle == nullptr) {
348         FFRT_LOGE("input task handle is invalid");
349         return -1;
350     }
351     return static_cast<ffrt::CPUEUTask*>(handle)->DecDeleteRef();
352 }
353 
354 API_ATTRIBUTE((visibility("default")))
ffrt_task_handle_destroy(ffrt_task_handle_t handle)355 void ffrt_task_handle_destroy(ffrt_task_handle_t handle)
356 {
357     ffrt_task_handle_dec_ref(handle);
358 }
359 
360 // wait
361 API_ATTRIBUTE((visibility("default")))
ffrt_wait_deps(const ffrt_deps_t *deps)362 void ffrt_wait_deps(const ffrt_deps_t *deps)
363 {
364     if (unlikely(!deps)) {
365         FFRT_LOGE("deps should not be empty");
366         return;
367     }
368     std::vector<ffrt_dependence_t> v(deps->len);
369     for (uint64_t i = 0; i < deps->len; ++i) {
370         v[i] = deps->items[i];
371     }
372     ffrt_deps_t d = { deps->len, v.data() };
373     ffrt::FFRTFacade::GetDMInstance().onWait(&d);
374 }
375 
376 API_ATTRIBUTE((visibility("default")))
ffrt_wait()377 void ffrt_wait()
378 {
379     ffrt::FFRTFacade::GetDMInstance().onWait();
380 }
381 
382 API_ATTRIBUTE((visibility("default")))
ffrt_set_cgroup_attr(ffrt_qos_t qos, ffrt_os_sched_attr *attr)383 int ffrt_set_cgroup_attr(ffrt_qos_t qos, ffrt_os_sched_attr *attr)
384 {
385     if (unlikely(!attr)) {
386         FFRT_LOGE("attr should not be empty");
387         return -1;
388     }
389     if (ffrt::GetFuncQosMap() == nullptr) {
390         FFRT_LOGE("FuncQosMap has not regist");
391         return -1;
392     }
393     ffrt::QoS _qos = ffrt::GetFuncQosMap()(qos);
394     return ffrt::OSAttrManager::Instance()->UpdateSchedAttr(_qos, attr);
395 }
396 
397 API_ATTRIBUTE((visibility("default")))
ffrt_restore_qos_config()398 void ffrt_restore_qos_config()
399 {
400     ffrt::WorkerGroupCtl *wgCtl = ffrt::FFRTFacade::GetEUInstance().GetGroupCtl();
401     for (auto qos = ffrt::QoS::Min(); qos < ffrt::QoS::Max(); ++qos) {
402         std::unique_lock<std::shared_mutex> lck(wgCtl[qos].tgMutex);
403         for (auto& thread : wgCtl[qos].threads) {
404             ffrt::SetThreadAttr(thread.first, qos);
405         }
406     }
407 }
408 
409 API_ATTRIBUTE((visibility("default")))
ffrt_set_qos_worker_num(ffrt_worker_num_param *qosData)410 int ffrt_set_qos_worker_num(ffrt_worker_num_param *qosData)
411 {
412     ffrt::CPUMonitor *monitor = ffrt::FFRTFacade::GetEUInstance().GetCPUMonitor();
413     return monitor->QosWorkerNumSegment(qosData);
414 }
415 
416 API_ATTRIBUTE((visibility("default")))
ffrt_notify_workers(ffrt_qos_t qos, int number)417 void ffrt_notify_workers(ffrt_qos_t qos, int number)
418 {
419     if (qos < ffrt::QoS::Min() || qos >= ffrt::QoS::Max() || number <= 0) {
420         FFRT_LOGE("qos [%d] or number [%d] or is invalid.", qos, number);
421         return;
422     }
423 
424     ffrt::FFRTFacade::GetEUInstance().NotifyWorkers(qos, number);
425 }
426 
427 API_ATTRIBUTE((visibility("default")))
ffrt_set_worker_stack_size(ffrt_qos_t qos, size_t stack_size)428 ffrt_error_t ffrt_set_worker_stack_size(ffrt_qos_t qos, size_t stack_size)
429 {
430     if (qos < ffrt::QoS::Min() || qos >= ffrt::QoS::Max() || stack_size < PTHREAD_STACK_MIN) {
431         FFRT_LOGE("qos [%d] or stack size [%d] is invalid.", qos, stack_size);
432         return ffrt_error_inval;
433     }
434 
435     ffrt::WorkerGroupCtl* groupCtl = ffrt::FFRTFacade::GetEUInstance().GetGroupCtl();
436     std::unique_lock<std::shared_mutex> lck(groupCtl[qos].tgMutex);
437     if (!groupCtl[qos].threads.empty()) {
438         FFRT_LOGE("Stack size can be set only when there is no worker.");
439         return ffrt_error;
440     }
441 
442     int pageSize = getpagesize();
443     if (pageSize < 0) {
444         FFRT_LOGE("Invalid pagesize : %d", pageSize);
445         return ffrt_error;
446     }
447 
448     groupCtl[qos].workerStackSize = (stack_size - 1 + static_cast<size_t>(pageSize)) &
449         -(static_cast<size_t>(pageSize));
450 
451     return ffrt_success;
452 }
453 
454 API_ATTRIBUTE((visibility("default")))
ffrt_this_task_update_qos(ffrt_qos_t qos)455 int ffrt_this_task_update_qos(ffrt_qos_t qos)
456 {
457     if (ffrt::GetFuncQosMap() == nullptr) {
458         FFRT_LOGE("FuncQosMap has not regist");
459         return 1;
460     }
461     ffrt::QoS _qos = ffrt::GetFuncQosMap()(qos);
462     auto curTask = ffrt::ExecuteCtx::Cur()->task;
463     if (curTask == nullptr) {
464         FFRT_LOGW("task is nullptr");
465         return 1;
466     }
467 
468     FFRT_COND_DO_ERR((curTask->type != ffrt_normal_task), return 1, "update qos task type invalid");
469     if (_qos() == curTask->qos) {
470         FFRT_LOGW("the target qos is equal to current qos, no need update");
471         return 0;
472     }
473 
474     curTask->SetQos(_qos);
475     ffrt_yield();
476 
477     return 0;
478 }
479 
480 API_ATTRIBUTE((visibility("default")))
ffrt_this_task_get_qos()481 ffrt_qos_t ffrt_this_task_get_qos()
482 {
483     if (ffrt::ExecuteCtx::Cur()->task == nullptr) {
484         FFRT_LOGW("task is nullptr");
485         return static_cast<int>(ffrt_qos_default);
486     }
487     return ffrt::ExecuteCtx::Cur()->qos();
488 }
489 
490 API_ATTRIBUTE((visibility("default")))
ffrt_this_task_get_id()491 uint64_t ffrt_this_task_get_id()
492 {
493     auto curTask = ffrt::ExecuteCtx::Cur()->task;
494     if (curTask == nullptr) {
495         return 0;
496     }
497 
498     if (curTask->type == ffrt_normal_task || curTask->type == ffrt_queue_task) {
499         return curTask->gid;
500     }
501 
502     return 0;
503 }
504 
505 API_ATTRIBUTE((visibility("default")))
ffrt_this_queue_get_id()506 int64_t ffrt_this_queue_get_id()
507 {
508     auto curTask = ffrt::ExecuteCtx::Cur()->task;
509     if (curTask == nullptr || curTask->type != ffrt_queue_task) {
510         // not serial queue task
511         return -1;
512     }
513 
514     ffrt::QueueTask* task = reinterpret_cast<ffrt::QueueTask*>(curTask);
515     return task->GetQueueId();
516 }
517 
518 API_ATTRIBUTE((visibility("default")))
ffrt_skip(ffrt_task_handle_t handle)519 int ffrt_skip(ffrt_task_handle_t handle)
520 {
521     return ffrt::FFRTFacade::GetDMInstance().onSkip(handle);
522 }
523 
524 API_ATTRIBUTE((visibility("default")))
ffrt_executor_task_submit(ffrt_executor_task_t* task, const ffrt_task_attr_t* attr)525 void ffrt_executor_task_submit(ffrt_executor_task_t* task, const ffrt_task_attr_t* attr)
526 {
527     if (task == nullptr) {
528         FFRT_LOGE("function handler should not be empty");
529         return;
530     }
531     ffrt::task_attr_private* p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr));
532     if (likely(attr == nullptr || ffrt_task_attr_get_delay(attr) == 0)) {
533         ffrt::FFRTFacade::GetDMInstance().onSubmitUV(task, p);
534         return;
535     }
536     FFRT_LOGE("uv function does not support delay");
537 }
538 
539 API_ATTRIBUTE((visibility("default")))
ffrt_executor_task_register_func(ffrt_executor_task_func func, ffrt_executor_task_type_t type)540 void ffrt_executor_task_register_func(ffrt_executor_task_func func, ffrt_executor_task_type_t type)
541 {
542     ffrt::FuncManager* func_mg = ffrt::FuncManager::Instance();
543     func_mg->insert(type, func);
544 }
545 
546 API_ATTRIBUTE((visibility("default")))
ffrt_executor_task_cancel(ffrt_executor_task_t* task, const ffrt_qos_t qos)547 int ffrt_executor_task_cancel(ffrt_executor_task_t* task, const ffrt_qos_t qos)
548 {
549     if (task == nullptr) {
550         FFRT_LOGE("function handler should not be empty");
551         return 0;
552     }
553     ffrt::QoS _qos = qos;
554 
555     ffrt::LinkedList* node = reinterpret_cast<ffrt::LinkedList *>(&task->wq);
556     ffrt::FFRTScheduler* sch = ffrt::FFRTFacade::GetSchedInstance();
557     bool ret = sch->RemoveNode(node, _qos);
558     if (ret) {
559         ffrt::FFRTTraceRecord::TaskCancel<ffrt_uv_task>(qos);
560     }
561     return static_cast<int>(ret);
562 }
563 
564 API_ATTRIBUTE((visibility("default")))
ffrt_get_cur_task()565 void* ffrt_get_cur_task()
566 {
567     return ffrt::ExecuteCtx::Cur()->task;
568 }
569 
570 API_ATTRIBUTE((visibility("default")))
ffrt_get_current_coroutine_stack(void** stack_addr, size_t* size)571 bool ffrt_get_current_coroutine_stack(void** stack_addr, size_t* size)
572 {
573     if (stack_addr == nullptr || size == nullptr) {
574         return false;
575     }
576 
577     if (!ffrt::USE_COROUTINE) {
578         return false;
579     }
580     auto curTask = ffrt::ExecuteCtx::Cur()->task;
581     if (curTask != nullptr) {
582         auto co = curTask->coRoutine;
583         if (co) {
584             *size = co->stkMem.size;
585             *stack_addr = static_cast<void*>(reinterpret_cast<char*>(co) + sizeof(CoRoutine) - 8);
586             return true;
587         }
588     }
589     return false;
590 }
591 
592 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_set_local(ffrt_task_attr_t* attr, bool task_local)593 void ffrt_task_attr_set_local(ffrt_task_attr_t* attr, bool task_local)
594 {
595     if (unlikely(!attr)) {
596         FFRT_LOGE("attr should be a valid address");
597         return;
598     }
599     (reinterpret_cast<ffrt::task_attr_private *>(attr))->taskLocal_ = task_local;
600 }
601 
602 API_ATTRIBUTE((visibility("default")))
ffrt_task_attr_get_local(ffrt_task_attr_t* attr)603 bool ffrt_task_attr_get_local(ffrt_task_attr_t* attr)
604 {
605     if (unlikely(!attr)) {
606         FFRT_LOGE("attr should be a valid address");
607         return false;
608     }
609     return (reinterpret_cast<ffrt::task_attr_private *>(attr))->taskLocal_;
610 }
611 
612 API_ATTRIBUTE((visibility("default")))
ffrt_task_get_tid(void* task_handle)613 pthread_t ffrt_task_get_tid(void* task_handle)
614 {
615     if (task_handle == nullptr) {
616         FFRT_LOGE("invalid task handle");
617         return 0;
618     }
619 
620     auto task = reinterpret_cast<ffrt::CPUEUTask*>(task_handle);
621     return task->runningTid.load();
622 }
623 
624 API_ATTRIBUTE((visibility("default")))
ffrt_get_cur_cached_task_id()625 uint64_t ffrt_get_cur_cached_task_id()
626 {
627     uint64_t gid = ffrt_this_task_get_id();
628     if (gid == 0) {
629         return ffrt::ExecuteCtx::Cur()->lastGid_;
630     }
631 
632     return gid;
633 }
634 #ifdef __cplusplus
635 }
636 #endif
637