• 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 #include "tm/cpu_task.h"
16 #include <securec.h>
17 #include "dfx/trace_record/ffrt_trace_record.h"
18 #include "dm/dependence_manager.h"
19 
20 #include "internal_inc/osal.h"
21 #include "tm/task_factory.h"
22 #include "util/ffrt_facade.h"
23 #include "util/slab.h"
24 #include "eu/func_manager.h"
25 
26 namespace {
27 const int TSD_SIZE = 128;
28 }
29 
30 namespace ffrt {
SetQos(const QoS & newQos)31 void CPUEUTask::SetQos(const QoS& newQos)
32 {
33     if (newQos == qos_inherit) {
34         if (!this->IsRoot()) {
35             this->qos_ = parent->qos_;
36         } else {
37             this->qos_ = QoS();
38         }
39         FFRT_LOGD("Change task %s QoS %d", label.c_str(), this->qos_());
40     } else {
41         this->qos_ = newQos;
42     }
43 }
44 
FreeMem()45 void CPUEUTask::FreeMem()
46 {
47     BboxCheckAndFreeze();
48     // only tasks which called ffrt_poll_ctl may have cached events
49     if (pollerEnable) {
50         FFRTFacade::GetPPInstance().GetPoller(qos_).ClearCachedEvents(this);
51     }
52 #ifdef FFRT_TASK_LOCAL_ENABLE
53     TaskTsdDeconstruct(this);
54 #endif
55     TaskFactory<CPUEUTask>::Free(this);
56 }
57 
Execute()58 void CPUEUTask::Execute()
59 {
60     FFRT_LOGD("Execute task[%lu], name[%s]", gid, label.c_str());
61     FFRTTraceRecord::TaskExecute(&(this->executeTime));
62     UpdateState(TaskState::RUNNING);
63     auto f = reinterpret_cast<ffrt_function_header_t*>(func_storage);
64     auto exp = ffrt::SkipStatus::SUBMITTED;
65     if (likely(__atomic_compare_exchange_n(&skipped, &exp, ffrt::SkipStatus::EXECUTED, 0,
66         __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))) {
67         f->exec(f);
68     }
69     f->destroy(f);
70     FFRT_TASKDONE_MARKER(gid);
71     if (!USE_COROUTINE) {
72         this->UpdateState(ffrt::TaskState::EXITED);
73     } else {
74         this->coRoutine->isTaskDone = true;
75     }
76 }
77 
CPUEUTask(const task_attr_private * attr,CPUEUTask * parent,const uint64_t & id,const QoS & qos)78 CPUEUTask::CPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id,
79     const QoS &qos)
80     : parent(parent), rank(id)
81 {
82     this->qos_ = qos;
83     fq_we.task = this;
84     if (attr && !attr->name_.empty()) {
85         label = attr->name_;
86     } else if (IsRoot()) {
87         label = "root";
88     } else if ((parent != nullptr) && parent->IsRoot()) {
89         label = "t" + std::to_string(rank);
90     } else {
91         label = parent->label + "." + std::to_string(rank);
92     }
93 
94     taskLocal = false;
95     tsd = nullptr;
96     if (attr && attr->taskLocal_) {
97         tsd = (void **)malloc(TSD_SIZE * sizeof(void *));
98         if (unlikely(tsd == nullptr)) {
99             FFRT_LOGE("task local malloc tsd failed");
100             return;
101         }
102         memset_s(tsd, TSD_SIZE * sizeof(void *), 0, TSD_SIZE * sizeof(void *));
103         taskLocal = attr->taskLocal_;
104     }
105     if (attr) {
106         stack_size = std::max(attr->stackSize_, MIN_STACK_SIZE);
107     }
108 }
109 
ExecuteUVTask(TaskBase * task,QoS qos)110 void ExecuteUVTask(TaskBase* task, QoS qos)
111 {
112     ffrt_executor_task_func func = FuncManager::Instance()->getFunc(ffrt_uv_task);
113     if (func == nullptr) {
114         FFRT_LOGE("Static func is nullptr");
115         return;
116     }
117     ffrt_executor_task_t* uv_work = reinterpret_cast<ffrt_executor_task_t *>(task);
118     FFRTTraceRecord::TaskExecute<ffrt_uv_task>(qos);
119     FFRT_EXECUTOR_TASK_BEGIN(uv_work);
120     func(uv_work, qos);
121     FFRT_EXECUTOR_TASK_END();
122     FFRT_EXECUTOR_TASK_FINISH_MARKER(uv_work); // task finish marker for uv task
123     FFRTTraceRecord::TaskDone<ffrt_uv_task>(qos);
124 }
125 
ExecuteTask(TaskBase * task,QoS qos)126 void ExecuteTask(TaskBase* task, QoS qos)
127 {
128     bool isCoTask = IsCoTask(task);
129 
130     // set current task info to context
131     ExecuteCtx* ctx = ExecuteCtx::Cur();
132     if (isCoTask) {
133         ctx->task = reinterpret_cast<CPUEUTask *>(task);
134         ctx->lastGid_ = task->gid;
135     } else {
136         ctx->exec_task = task; // for ffrt_wake_coroutine
137     }
138 
139     // run Task with coroutine
140     if (USE_COROUTINE && isCoTask) {
141         while (CoStart(static_cast<CPUEUTask*>(task), GetCoEnv()) != 0) {
142             usleep(CO_CREATE_RETRY_INTERVAL);
143         }
144     } else {
145     // run task on thread
146 #ifdef FFRT_ASYNC_STACKTRACE
147         if (isCoTask) {
148             FFRTSetStackId(task->stackId);
149         }
150 #endif
151         if (task->type < ffrt_invalid_task && task->type != ffrt_uv_task) {
152             task->Execute();
153         } else {
154             ExecuteUVTask(task, qos);
155         }
156     }
157 
158     // reset task info in context
159     ctx->task = nullptr;
160     ctx->exec_task = nullptr;
161 }
162 } /* namespace ffrt */