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