• 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 #include "cpp/task_ext.h"
26 #include "util/ref_function_header.h"
27 
28 namespace {
29 const int TSD_SIZE = 128;
30 }
31 
32 namespace ffrt {
SetQos(const QoS & newQos)33 void CPUEUTask::SetQos(const QoS& newQos)
34 {
35     if (newQos == qos_inherit) {
36         if (!IsRoot()) {
37             qos_ = parent->qos_;
38         } else {
39             qos_ = QoS();
40         }
41     } else {
42         qos_ = newQos;
43     }
44     FFRT_LOGD("Change task %s QoS %d", label.c_str(), qos_());
45 }
46 
Prepare()47 void CPUEUTask::Prepare()
48 {
49     this->SetStatus(TaskStatus::SUBMITTED);
50     FFRTTraceRecord::TaskSubmit<ffrt_normal_task>(qos_, &createTime, &fromTid);
51 }
52 
Ready()53 void CPUEUTask::Ready()
54 {
55     int qos = qos_();
56     bool notifyWorker = notifyWorker_;
57     this->SetStatus(TaskStatus::READY);
58     bool isRisingEdge = FFRTFacade::GetSchedInstance()->GetScheduler(qos_).PushTaskGlobal(this, false);
59     FFRTTraceRecord::TaskEnqueue<ffrt_normal_task>(qos);
60     if (notifyWorker) {
61         FFRTFacade::GetEUInstance().NotifyTask<TaskNotifyType::TASK_ADDED_RTQ>(qos, false, isRisingEdge);
62     }
63 }
64 
FreeMem()65 void CPUEUTask::FreeMem()
66 {
67     BboxCheckAndFreeze();
68     // only tasks which called ffrt_poll_ctl may have cached events
69     if (pollerEnable) {
70         FFRTFacade::GetPPInstance().ClearCachedEvents(this);
71     }
72 #ifdef FFRT_TASK_LOCAL_ENABLE
73     TaskTsdDeconstruct(this);
74 #endif
75     auto f = reinterpret_cast<ffrt_function_header_t*>(func_storage);
76     if ((f->reserve[0] & MASK_FOR_HCS_TASK) != MASK_FOR_HCS_TASK) {
77         TaskFactory<CPUEUTask>::Free(this);
78         return;
79     }
80     FFRT_LOGD("hcs task deconstruct dec ref gid:%llu, create time:%llu", gid, createTime);
81     this->~CPUEUTask();
82     // hcs task dec ref
83     reinterpret_cast<RefFunctionHeader*>(f->reserve[0] & (~MASK_FOR_HCS_TASK))->DecDeleteRef();
84 }
85 
Execute()86 void CPUEUTask::Execute()
87 {
88     FFRT_LOGD("Execute task[%lu], name[%s]", gid, label.c_str());
89     FFRTTraceRecord::TaskExecute(&executeTime);
90     auto f = reinterpret_cast<ffrt_function_header_t*>(func_storage);
91     auto exp = ffrt::SkipStatus::SUBMITTED;
92     if (likely(__atomic_compare_exchange_n(&skipped, &exp, ffrt::SkipStatus::EXECUTED, 0,
93         __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))) {
94         SetStatus(TaskStatus::EXECUTING);
95         f->exec(f);
96     }
97     if ((f->reserve[0] & MASK_FOR_HCS_TASK) != MASK_FOR_HCS_TASK) {
98         if (f->destroy) {
99             f->destroy(f);
100         }
101     }
102     FFRT_TASKDONE_MARKER(gid);
103     // skipped task can not be marked as finish
104     if (curStatus == TaskStatus::EXECUTING) {
105         SetStatus(TaskStatus::FINISH);
106     }
107     if (!USE_COROUTINE) {
108         FFRTFacade::GetDMInstance().onTaskDone(this);
109     } else {
110         /*
111             if we call onTaskDone inside coroutine, the memory of task may be recycled.
112             1. recycled memory of task can be used by another submit
113             2. task->coRoutine will be recycled and can be used by another task
114             In this scenario, CoStart will crash.
115             Because it needs to use this task and it's coRoutine to perform some action after it finished.
116         */
117         coRoutine->isTaskDone = true;
118         UnbindCoRoutione();
119     }
120 }
121 
CPUEUTask(const task_attr_private * attr,CPUEUTask * parent,const uint64_t & id)122 CPUEUTask::CPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id)
123     : CoTask(ffrt_normal_task, attr), parent(parent)
124 {
125     if (attr && !attr->name_.empty()) {
126         label = attr->name_;
127     } else if (IsRoot()) {
128         label = "root";
129     } else if ((parent != nullptr) && parent->IsRoot()) {
130         label = "t" + std::to_string(id);
131     } else if (parent != nullptr) {
132         label = parent->label + "." + std::to_string(id);
133     } else {
134         label = "t" + std::to_string(id);
135     }
136 
137     if (attr) {
138         notifyWorker_ = attr->notifyWorker_;
139 
140         if (attr->qos_ == qos_inherit && !IsRoot()) {
141             qos_ = parent->qos_;
142         }
143 #ifdef FFRT_TASK_LOCAL_ENABLE
144         if (attr->taskLocal_) {
145             tlsAttr = new TaskLocalAttr;
146             tlsAttr->tsd = static_cast<void**>(malloc(TSD_SIZE * sizeof(void*)));
147             if (unlikely(tlsAttr->tsd == nullptr)) {
148                 FFRT_SYSEVENT_LOGE("task local malloc tsd failed");
149                 return;
150             }
151             memset_s(tlsAttr->tsd, TSD_SIZE * sizeof(void *), 0, TSD_SIZE * sizeof(void *));
152             tlsAttr->taskLocal = true;
153         }
154 #endif
155     }
156 
157     aliveStatus.store(AliveStatus::INITED, std::memory_order_relaxed);
158 }
~CPUEUTask()159 CPUEUTask::~CPUEUTask()
160 {
161 #ifdef FFRT_TASK_LOCAL_ENABLE
162     if (tlsAttr != nullptr) {
163         delete tlsAttr;
164         tlsAttr = nullptr;
165     }
166 #endif
167     if (in_handles_ != nullptr) {
168         delete in_handles_;
169         in_handles_ = nullptr;
170     }
171     aliveStatus.store(AliveStatus::RELEASED, std::memory_order_relaxed);
172 }
173 } /* namespace ffrt */
174