1484543d1Sopenharmony_ci/* 2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License. 5484543d1Sopenharmony_ci * You may obtain a copy of the License at 6484543d1Sopenharmony_ci * 7484543d1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8484543d1Sopenharmony_ci * 9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and 13484543d1Sopenharmony_ci * limitations under the License. 14484543d1Sopenharmony_ci */ 15484543d1Sopenharmony_ci#include <pthread.h> 16484543d1Sopenharmony_ci#include <random> 17484543d1Sopenharmony_ci#include "core/task_io.h" 18484543d1Sopenharmony_ci#ifdef FFRT_CO_BACKTRACE_OH_ENABLE 19484543d1Sopenharmony_ci#include <dlfcn.h> 20484543d1Sopenharmony_ci#endif 21484543d1Sopenharmony_ci#include "util/slab.h" 22484543d1Sopenharmony_ci#include "util/ffrt_facade.h" 23484543d1Sopenharmony_ci#include "util/spmc_queue.h" 24484543d1Sopenharmony_ci 25484543d1Sopenharmony_ci#define ENABLE_LOCAL_QUEUE 26484543d1Sopenharmony_ci 27484543d1Sopenharmony_cinamespace { 28484543d1Sopenharmony_ciconst int INSERT_GLOBAL_QUEUE_FREQ = 5; 29484543d1Sopenharmony_ci} 30484543d1Sopenharmony_ci 31484543d1Sopenharmony_cinamespace ffrt { 32484543d1Sopenharmony_cistatic void work_finish_callable(IOTaskExecutor* task) 33484543d1Sopenharmony_ci{ 34484543d1Sopenharmony_ci task->status = ExecTaskStatus::ET_FINISH; 35484543d1Sopenharmony_ci task->work.destroy(task->work.data); 36484543d1Sopenharmony_ci delete task; 37484543d1Sopenharmony_ci} 38484543d1Sopenharmony_ci 39484543d1Sopenharmony_cistatic void ExecuteIOTask(ffrt_executor_task_t* data, ffrt_qos_t qos) 40484543d1Sopenharmony_ci{ 41484543d1Sopenharmony_ci IOTaskExecutor* task = static_cast<IOTaskExecutor*>(data); 42484543d1Sopenharmony_ci task->status = ExecTaskStatus::ET_EXECUTING; 43484543d1Sopenharmony_ci (void)qos; 44484543d1Sopenharmony_ci ffrt_coroutine_ptr_t coroutine = task->work.exec; 45484543d1Sopenharmony_ci ffrt_coroutine_ret_t ret = coroutine(task->work.data); 46484543d1Sopenharmony_ci if (ret == ffrt_coroutine_ready) { 47484543d1Sopenharmony_ci FFRT_EXECUTOR_TASK_FINISH_MARKER(task); 48484543d1Sopenharmony_ci work_finish_callable(task); 49484543d1Sopenharmony_ci return; 50484543d1Sopenharmony_ci } 51484543d1Sopenharmony_ci 52484543d1Sopenharmony_ci FFRT_EXECUTOR_TASK_BLOCK_MARKER(task); 53484543d1Sopenharmony_ci task->status = ffrt::ExecTaskStatus::ET_PENDING; 54484543d1Sopenharmony_ci#ifdef FFRT_BBOX_ENABLE 55484543d1Sopenharmony_ci TaskPendingCounterInc(); 56484543d1Sopenharmony_ci#endif 57484543d1Sopenharmony_ci} 58484543d1Sopenharmony_ci 59484543d1Sopenharmony_cistatic pthread_once_t once = PTHREAD_ONCE_INIT; 60484543d1Sopenharmony_ci 61484543d1Sopenharmony_cistatic void InitIOTaskExecutor() 62484543d1Sopenharmony_ci{ 63484543d1Sopenharmony_ci ffrt_executor_task_register_func(ExecuteIOTask, ffrt_io_task); 64484543d1Sopenharmony_ci} 65484543d1Sopenharmony_ci} /* namespace ffrt */ 66484543d1Sopenharmony_ci 67484543d1Sopenharmony_ci#ifdef __cplusplus 68484543d1Sopenharmony_ciextern "C" { 69484543d1Sopenharmony_ci#endif 70484543d1Sopenharmony_ciAPI_ATTRIBUTE((visibility("default"))) 71484543d1Sopenharmony_civoid ffrt_submit_coroutine(void* co, ffrt_coroutine_ptr_t exec, ffrt_function_t destroy, const ffrt_deps_t* in_deps, 72484543d1Sopenharmony_ci const ffrt_deps_t* out_deps, const ffrt_task_attr_t* attr) 73484543d1Sopenharmony_ci{ 74484543d1Sopenharmony_ci FFRT_COND_DO_ERR((exec == nullptr), return, "input invalid, exec == nullptr"); 75484543d1Sopenharmony_ci pthread_once(&ffrt::once, ffrt::InitIOTaskExecutor); 76484543d1Sopenharmony_ci 77484543d1Sopenharmony_ci ffrt::task_attr_private *p = reinterpret_cast<ffrt::task_attr_private *>(const_cast<ffrt_task_attr_t *>(attr)); 78484543d1Sopenharmony_ci ffrt::QoS qos = (p == nullptr ? ffrt::QoS() : ffrt::QoS(p->qos_)); 79484543d1Sopenharmony_ci 80484543d1Sopenharmony_ci (void)in_deps; 81484543d1Sopenharmony_ci (void)out_deps; 82484543d1Sopenharmony_ci ffrt::IOTaskExecutor* task = new ffrt::IOTaskExecutor(qos); 83484543d1Sopenharmony_ci task->work.exec = exec; 84484543d1Sopenharmony_ci task->work.destroy = destroy; 85484543d1Sopenharmony_ci task->work.data = co; 86484543d1Sopenharmony_ci task->status = ffrt::ExecTaskStatus::ET_READY; 87484543d1Sopenharmony_ci 88484543d1Sopenharmony_ci ffrt_executor_task_submit(dynamic_cast<ffrt_executor_task_t*>(task), attr); 89484543d1Sopenharmony_ci} 90484543d1Sopenharmony_ci 91484543d1Sopenharmony_ciAPI_ATTRIBUTE((visibility("default"))) 92484543d1Sopenharmony_civoid* ffrt_get_current_task() 93484543d1Sopenharmony_ci{ 94484543d1Sopenharmony_ci return reinterpret_cast<void*>(ffrt::ExecuteCtx::Cur()->exec_task); 95484543d1Sopenharmony_ci} 96484543d1Sopenharmony_ci 97484543d1Sopenharmony_ci// API used to schedule stackless coroutine task 98484543d1Sopenharmony_ciAPI_ATTRIBUTE((visibility("default"))) 99484543d1Sopenharmony_civoid ffrt_wake_coroutine(void* task) 100484543d1Sopenharmony_ci{ 101484543d1Sopenharmony_ci if (task == nullptr) { 102484543d1Sopenharmony_ci FFRT_LOGE("Task is nullptr."); 103484543d1Sopenharmony_ci return; 104484543d1Sopenharmony_ci } 105484543d1Sopenharmony_ci 106484543d1Sopenharmony_ci#ifdef FFRT_BBOX_ENABLE 107484543d1Sopenharmony_ci TaskWakeCounterInc(); 108484543d1Sopenharmony_ci#endif 109484543d1Sopenharmony_ci 110484543d1Sopenharmony_ci ffrt::IOTaskExecutor* wakedTask = static_cast<ffrt::IOTaskExecutor*>(task); 111484543d1Sopenharmony_ci wakedTask->status = ffrt::ExecTaskStatus::ET_READY; 112484543d1Sopenharmony_ci 113484543d1Sopenharmony_ci // in self-wakeup scenario, tasks are placed in local fifo to delay scheduling, implementing the yeild function 114484543d1Sopenharmony_ci bool selfWakeup = (ffrt::ExecuteCtx::Cur()->exec_task == task); 115484543d1Sopenharmony_ci if (!selfWakeup) { 116484543d1Sopenharmony_ci if (ffrt::ExecuteCtx::Cur()->PushTaskToPriorityStack(wakedTask)) { 117484543d1Sopenharmony_ci return; 118484543d1Sopenharmony_ci } 119484543d1Sopenharmony_ci 120484543d1Sopenharmony_ci if (rand() % INSERT_GLOBAL_QUEUE_FREQ) { 121484543d1Sopenharmony_ci if (ffrt::ExecuteCtx::Cur()->localFifo != nullptr && 122484543d1Sopenharmony_ci ffrt::ExecuteCtx::Cur()->localFifo->PushTail(task) == 0) { 123484543d1Sopenharmony_ci ffrt::FFRTFacade::GetEUInstance().NotifyLocalTaskAdded(wakedTask->qos); 124484543d1Sopenharmony_ci return; 125484543d1Sopenharmony_ci } 126484543d1Sopenharmony_ci } 127484543d1Sopenharmony_ci } 128484543d1Sopenharmony_ci 129484543d1Sopenharmony_ci ffrt::LinkedList* node = reinterpret_cast<ffrt::LinkedList *>(&wakedTask->wq); 130484543d1Sopenharmony_ci if (!ffrt::FFRTFacade::GetSchedInstance()->InsertNode(node, wakedTask->qos)) { 131484543d1Sopenharmony_ci FFRT_LOGE("Submit io task failed!"); 132484543d1Sopenharmony_ci } 133484543d1Sopenharmony_ci} 134484543d1Sopenharmony_ci#ifdef __cplusplus 135484543d1Sopenharmony_ci} 136484543d1Sopenharmony_ci#endif 137484543d1Sopenharmony_ci 138