• 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 "core/task_ctx.h"
16 #ifdef FFRT_CO_BACKTRACE_OH_ENABLE
17 #include <dlfcn.h>
18 #include <sstream>
19 #include "libunwind.h"
20 #include "backtrace_local.h"
21 #endif
22 #include "core/dependence_manager.h"
23 #include "util/slab.h"
24 #include "internal_inc/osal.h"
25 #include "internal_inc/types.h"
26 
27 namespace ffrt {
DenpenceStr(Denpence d)28 static inline const char* DenpenceStr(Denpence d)
29 {
30     static const char* m[] = {
31         "DEPENCE_INIT",
32         "DATA_DEPENCE",
33         "CALL_DEPENCE",
34         "CONDITION_DEPENCE",
35     };
36     return m[static_cast<uint64_t>(d)];
37 }
38 
TaskCtx(const task_attr_private * attr,TaskCtx * parent,const uint64_t & id,const char * identity,const QoS & qos)39 TaskCtx::TaskCtx(const task_attr_private *attr, TaskCtx *parent, const uint64_t &id, const char *identity,
40     const QoS &qos)
41     : parent(parent), rank(id), identity(identity), qos(qos)
42 {
43     wue = nullptr;
44     fq_we.task = this;
45     if (attr && !attr->name_.empty()) {
46         label = attr->name_;
47     } else if (IsRoot()) {
48         label = "root";
49     } else if (parent->parent == nullptr) {
50         label = "t" + std::to_string(rank);
51     } else {
52         label = parent->label + "." + std::to_string(rank);
53     }
54     if (!IsRoot()) {
55         FFRT_SUBMIT_MARKER(label, gid);
56     }
57     FFRT_LOGD("create task name:%s gid=%lu", label.c_str(), gid);
58 }
59 
SetQos(QoS & target_qos)60 void TaskCtx::SetQos(QoS& target_qos)
61 {
62     if (target_qos == qos_inherit) {
63         if (!this->IsRoot()) {
64             this->qos = parent->qos;
65         }
66         FFRT_LOGD("Change task %s QoS %d", label.c_str(), this->qos());
67     } else {
68         this->qos = target_qos;
69     }
70 }
71 
72 /* For interval based userspace load tracking
73  * Inherit parent's active intervals for a new task
74  */
InitRelatedIntervals(TaskCtx * curr)75 void TaskCtx::InitRelatedIntervals(TaskCtx* curr)
76 {
77     auto& parentIntervals = curr->relatedIntervals;
78     if (parentIntervals.empty()) {
79         return;
80     }
81 
82     for (auto it : std::as_const(parentIntervals)) {
83         if (it->Qos() == curr->qos) {
84             curr->relatedIntervals.insert(it);
85         }
86     }
87 }
88 
DecDepRef()89 void TaskCtx::DecDepRef()
90 {
91     if (--depRefCnt == 0) {
92         FFRT_LOGI("Undependency completed, enter ready queue, task[%lu], name[%s]", gid, label.c_str());
93         FFRT_WAKE_TRACER(this->gid);
94         this->UpdateState(TaskState::READY);
95 #ifdef FFRT_BBOX_ENABLE
96         TaskEnQueuCounterInc();
97 #endif
98     }
99 }
100 
DecChildRef()101 void TaskCtx::DecChildRef()
102 {
103     FFRT_LOGD("DecChildRef parent task:%s, childWaitRefCnt=%u", parent->label.c_str(), parent->childWaitRefCnt.load());
104     FFRT_TRACE_SCOPE(2, taskDecChildRef);
105     std::unique_lock<decltype(parent->lock)> lck(parent->lock);
106     parent->childWaitRefCnt--;
107     if (parent->childWaitRefCnt != 0) {
108         return;
109     }
110     if (FFRT_UNLIKELY(parent->IsRoot())) {
111         RootTaskCtx *root = static_cast<RootTaskCtx *>(parent);
112         if (root->thread_exit == true) {
113             lck.unlock();
114             delete root;
115             return;
116         }
117     }
118 
119     if (!parent->IsRoot() && parent->status == TaskStatus::RELEASED && parent->childWaitRefCnt == 0) {
120         FFRT_LOGD("free TaskCtx:%s gid=%lu", parent->label.c_str(), parent->gid);
121         lck.unlock();
122         parent->DecDeleteRef();
123         return;
124     }
125     if (parent->denpenceStatus != Denpence::CALL_DEPENCE) {
126         return;
127     }
128     parent->denpenceStatus = Denpence::DEPENCE_INIT;
129 
130     if (!USE_COROUTINE || parent->parent == nullptr) {
131         parent->childWaitCond_.notify_all();
132     } else {
133         FFRT_WAKE_TRACER(parent->gid);
134         parent->UpdateState(TaskState::READY);
135     }
136 }
137 
DecWaitDataRef()138 void TaskCtx::DecWaitDataRef()
139 {
140     FFRT_TRACE_SCOPE(2, taskDecWaitData);
141     {
142         std::lock_guard<decltype(lock)> lck(lock);
143         dataWaitRefCnt--;
144         if (dataWaitRefCnt != 0) {
145             return;
146         }
147         if (denpenceStatus != Denpence::DATA_DEPENCE) {
148             return;
149         }
150         denpenceStatus = Denpence::DEPENCE_INIT;
151     }
152 
153     if (!USE_COROUTINE || parent == nullptr) {
154         dataWaitCond_.notify_all();
155     } else {
156         FFRT_WAKE_TRACER(this->gid);
157         this->UpdateState(TaskState::READY);
158 #ifdef FFRT_BBOX_ENABLE
159         TaskEnQueuCounterInc();
160 #endif
161     }
162 }
163 
IsPrevTask(const TaskCtx * task) const164 bool TaskCtx::IsPrevTask(const TaskCtx* task) const
165 {
166     std::list<uint64_t> ThisTaskIds;
167     std::list<uint64_t> OtherTaskIds;
168     const TaskCtx* now = this;
169     while (now != nullptr && now != DependenceManager::Root()) {
170         ThisTaskIds.push_front(now->rank);
171         now = now->parent;
172     }
173     while (task != nullptr && task != DependenceManager::Root()) {
174         OtherTaskIds.push_front(task->rank);
175         task = task->parent;
176     }
177     return ThisTaskIds < OtherTaskIds;
178 }
179 
RecycleTask()180 void TaskCtx::RecycleTask()
181 {
182     std::unique_lock<decltype(lock)> lck(lock);
183     if (childWaitRefCnt == 0) {
184         FFRT_LOGD("free TaskCtx:%s gid=%lu", label.c_str(), gid);
185         lck.unlock();
186         DecDeleteRef();
187         return;
188     } else {
189         status = TaskStatus::RELEASED;
190     }
191 }
192 
MultiDepenceAdd(Denpence depType)193 void TaskCtx::MultiDepenceAdd(Denpence depType)
194 {
195     FFRT_LOGD("task(%s) ADD_DENPENCE(%s)", this->label.c_str(), DenpenceStr(depType));
196     denpenceStatus = depType;
197 }
198 #ifdef FFRT_CO_BACKTRACE_OH_ENABLE
DumpTask(TaskCtx * task,std::string & stackInfo,uint8_t flag)199 void TaskCtx::DumpTask(TaskCtx* task, std::string& stackInfo, uint8_t flag)
200 {
201     unw_context_t ctx;
202     unw_cursor_t unw_cur;
203     unw_proc_info_t unw_proc;
204 
205     if (ExecuteCtx::Cur()->task == task || task == nullptr) {
206         if (flag == 0) {
207             OHOS::HiviewDFX::PrintTrace(-1);
208         } else {
209             OHOS::HiviewDFX::GetBacktrace(stackInfo, false);
210         }
211         return;
212     } else {
213         memset(&ctx, 0, sizeof(ctx));
214 #if defined(__aarch64__)
215         ctx.uc_mcontext.regs[UNW_AARCH64_X29] = task->coRoutine->ctx.regs[10];
216         ctx.uc_mcontext.sp = task->coRoutine->ctx.regs[13];
217         ctx.uc_mcontext.pc = task->coRoutine->ctx.regs[11];
218 #elif defined(__x86_64__)
219         ctx.uc_mcontext.gregs[REG_RBX] = task->coRoutine->ctx.regs[0];
220         ctx.uc_mcontext.gregs[REG_RBP] = task->coRoutine->ctx.regs[1];
221         ctx.uc_mcontext.gregs[REG_RSP] = task->coRoutine->ctx.regs[6];
222         ctx.uc_mcontext.gregs[REG_RIP] = *(reinterpret_cast<greg_t *>(ctx.uc_mcontext.gregs[REG_RSP] - 8));
223 #elif defined(__arm__)
224         ctx.regs[13] = task->coRoutine->ctx.regs[0]; /* sp */
225         ctx.regs[15] = task->coRoutine->ctx.regs[1]; /* pc */
226         ctx.regs[14] = task->coRoutine->ctx.regs[1]; /* lr */
227         ctx.regs[11] = task->coRoutine->ctx.regs[10]; /* fp */
228 #endif
229     }
230 
231     int ret;
232     int frame_id = 0;
233     ret = unw_init_local(&unw_cur, &ctx);
234     if (ret < 0) {
235         return;
236     }
237 
238     Dl_info info;
239     unw_word_t prevPc = 0;
240     unw_word_t offset;
241     char symbol[512];
242     std::ostringstream ss;
243     do {
244         ret = unw_get_proc_info(&unw_cur, &unw_proc);
245         if (ret) {
246             break;
247         }
248 
249         if (prevPc == unw_proc.start_ip) {
250             break;
251         }
252 
253         prevPc = unw_proc.start_ip;
254 
255         ret = dladdr(reinterpret_cast<void *>(unw_proc.start_ip), &info);
256         if (!ret) {
257             break;
258         }
259 
260         memset(symbol, 0, sizeof(symbol));
261         if (unw_get_proc_name(&unw_cur, symbol, sizeof(symbol), &offset) == 0) {
262             if (flag == 0) {
263                 FFRT_LOGE("FFRT | #%d pc: %lx %s(%p) %s", frame_id, unw_proc.start_ip, info.dli_fname,
264                           (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)), symbol);
265             } else {
266                 ss << "FFRT | #" << frame_id << " pc: " << unw_proc.start_ip << " " << info.dli_fname;
267                 ss << "(" << (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)) << ") ";
268                 ss << std::string(symbol, strlen(symbol)) <<std::endl;
269             }
270         } else {
271             if (flag == 0) {
272                 FFRT_LOGE("FFRT | #%d pc: %lx %s(%p)", frame_id, unw_proc.start_ip, info.dli_fname,
273                           (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)));
274             } else {
275                 ss << "FFRT | #" << frame_id << " pc: " << unw_proc.start_ip << " " << info.dli_fname;
276                 ss << "(" << (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)) << ") ";
277                 ss << std::endl;
278             }
279         }
280         ++frame_id;
281     } while (unw_step(&unw_cur) > 0);
282 
283     if (flag != 0) {
284         stackInfo = ss.str();
285     }
286     return;
287 }
288 #endif
289 } /* namespace ffrt */