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