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 #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 "dm/dependence_manager.h"
23 #include "util/slab.h"
24 #include "internal_inc/osal.h"
25 #include "tm/task_factory.h"
26 #include "tm/cpu_task.h"
27
28 namespace ffrt {
29 static std::atomic_uint64_t s_gid(0);
TaskBase()30 TaskBase::TaskBase() : gid(++s_gid) {}
31
SetQos(QoS & new_qos)32 void CPUEUTask::SetQos(QoS& new_qos)
33 {
34 if (new_qos == qos_inherit) {
35 if (!this->IsRoot()) {
36 this->qos = parent->qos;
37 }
38 FFRT_LOGD("Change task %s QoS %d", label.c_str(), this->qos());
39 } else {
40 this->qos = new_qos;
41 }
42 }
43
freeMem()44 void CPUEUTask::freeMem()
45 {
46 BboxCheckAndFreeze();
47 ffrt::TaskFactory::Free(this);
48 }
49
CPUEUTask(const task_attr_private * attr,CPUEUTask * parent,const uint64_t & id,const QoS & qos)50 CPUEUTask::CPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id,
51 const QoS &qos)
52 : parent(parent), rank(id), qos(qos)
53 {
54 wue = nullptr;
55 fq_we.task = this;
56 if (attr && !attr->name_.empty()) {
57 label = attr->name_;
58 } else if (IsRoot()) {
59 label = "root";
60 } else if (parent->parent == nullptr) {
61 label = "t" + std::to_string(rank);
62 } else {
63 label = parent->label + "." + std::to_string(rank);
64 }
65 if (!IsRoot()) {
66 FFRT_SUBMIT_MARKER(label, gid);
67 }
68 FFRT_LOGD("create task name:%s gid=%lu", label.c_str(), gid);
69 }
70
71 #ifdef FFRT_CO_BACKTRACE_OH_ENABLE
DumpTask(CPUEUTask * task,std::string & stackInfo,uint8_t flag)72 void CPUEUTask::DumpTask(CPUEUTask* task, std::string& stackInfo, uint8_t flag)
73 {
74 unw_context_t ctx;
75 unw_cursor_t unw_cur;
76 unw_proc_info_t unw_proc;
77
78 if (ExecuteCtx::Cur()->task == task || task == nullptr) {
79 if (flag == 0) {
80 OHOS::HiviewDFX::PrintTrace(-1);
81 } else {
82 OHOS::HiviewDFX::GetBacktrace(stackInfo, false);
83 }
84 return;
85 } else {
86 memset(&ctx, 0, sizeof(ctx));
87 #if defined(__aarch64__)
88 ctx.uc_mcontext.regs[UNW_AARCH64_X29] = task->coRoutine->ctx.regs[10];
89 ctx.uc_mcontext.sp = task->coRoutine->ctx.regs[13];
90 ctx.uc_mcontext.pc = task->coRoutine->ctx.regs[11];
91 #elif defined(__x86_64__)
92 ctx.uc_mcontext.gregs[REG_RBX] = task->coRoutine->ctx.regs[0];
93 ctx.uc_mcontext.gregs[REG_RBP] = task->coRoutine->ctx.regs[1];
94 ctx.uc_mcontext.gregs[REG_RSP] = task->coRoutine->ctx.regs[6];
95 ctx.uc_mcontext.gregs[REG_RIP] = *(reinterpret_cast<greg_t *>(ctx.uc_mcontext.gregs[REG_RSP] - 8));
96 #elif defined(__arm__)
97 ctx.regs[13] = task->coRoutine->ctx.regs[0]; /* sp */
98 ctx.regs[15] = task->coRoutine->ctx.regs[1]; /* pc */
99 ctx.regs[14] = task->coRoutine->ctx.regs[1]; /* lr */
100 ctx.regs[11] = task->coRoutine->ctx.regs[10]; /* fp */
101 #endif
102 }
103
104 int ret;
105 int frame_id = 0;
106 ret = unw_init_local(&unw_cur, &ctx);
107 if (ret < 0) {
108 return;
109 }
110
111 Dl_info info;
112 unw_word_t prevPc = 0;
113 unw_word_t offset;
114 char symbol[512];
115 std::ostringstream ss;
116 do {
117 ret = unw_get_proc_info(&unw_cur, &unw_proc);
118 if (ret) {
119 break;
120 }
121
122 if (prevPc == unw_proc.start_ip) {
123 break;
124 }
125
126 prevPc = unw_proc.start_ip;
127
128 ret = dladdr(reinterpret_cast<void *>(unw_proc.start_ip), &info);
129 if (!ret) {
130 break;
131 }
132
133 memset(symbol, 0, sizeof(symbol));
134 if (unw_get_proc_name(&unw_cur, symbol, sizeof(symbol), &offset) == 0) {
135 if (flag == 0) {
136 FFRT_LOGE("FFRT | #%d pc: %lx %s(%p) %s", frame_id, unw_proc.start_ip, info.dli_fname,
137 (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)), symbol);
138 } else {
139 ss << "FFRT | #" << frame_id << " pc: " << unw_proc.start_ip << " " << info.dli_fname;
140 ss << "(" << (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)) << ") ";
141 ss << std::string(symbol, strlen(symbol)) <<std::endl;
142 }
143 } else {
144 if (flag == 0) {
145 FFRT_LOGE("FFRT | #%d pc: %lx %s(%p)", frame_id, unw_proc.start_ip, info.dli_fname,
146 (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)));
147 } else {
148 ss << "FFRT | #" << frame_id << " pc: " << unw_proc.start_ip << " " << info.dli_fname;
149 ss << "(" << (unw_proc.start_ip - reinterpret_cast<unw_word_t>(info.dli_fbase)) << ")";
150 ss << std::endl;
151 }
152 }
153 ++frame_id;
154 } while (unw_step(&unw_cur) > 0);
155
156 if (flag != 0) {
157 stackInfo = ss.str();
158 }
159 return;
160 }
161 #endif
162 } /* namespace ffrt */