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