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 <sstream>
18 #include "backtrace_local.h"
19 #endif
20 #include "dfx/trace_record/ffrt_trace_record.h"
21 #include "dm/dependence_manager.h"
22 #include "util/slab.h"
23 #include "internal_inc/osal.h"
24 #include "internal_inc/types.h"
25 #include "tm/cpu_task.h"
26
27 namespace ffrt {
DependenceStr(Dependence d)28 static inline const char* DependenceStr(Dependence d)
29 {
30 static const char* m[] = {
31 "DEPENDENCE_INIT",
32 "DATA_DEPENDENCE",
33 "CALL_DEPENDENCE",
34 "CONDITION_DEPENDENCE",
35 };
36 return m[static_cast<uint64_t>(d)];
37 }
38
SCPUEUTask(const task_attr_private * attr,CPUEUTask * parent,const uint64_t & id)39 SCPUEUTask::SCPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id)
40 : CPUEUTask(attr, parent, id)
41 {
42 }
43
DecDepRef()44 void SCPUEUTask::DecDepRef()
45 {
46 if (--dataRefCnt.submitDep == 0) {
47 FFRT_LOGD("Undependency completed, enter ready queue, task[%lu], name[%s]", gid, label.c_str());
48 FFRT_WAKE_TRACER(gid);
49 Ready();
50 }
51 }
52
DecChildRef()53 void SCPUEUTask::DecChildRef()
54 {
55 SCPUEUTask* parent = reinterpret_cast<SCPUEUTask*>(this->parent);
56 FFRT_TRACE_SCOPE(2, taskDecChildRef);
57 std::unique_lock<decltype(parent->mutex_)> lck(parent->mutex_);
58 parent->childRefCnt--;
59 if (parent->childRefCnt != 0) {
60 return;
61 }
62 if (FFRT_UNLIKELY(parent->IsRoot())) {
63 RootTask *root = static_cast<RootTask *>(parent);
64 if (root->thread_exit) {
65 lck.unlock();
66 delete root;
67 return;
68 }
69 }
70
71 if (!parent->IsRoot() && parent->curStatus == TaskStatus::WAIT_RELEASING && parent->childRefCnt == 0) {
72 FFRT_LOGD("free CPUEUTask:%s gid=%lu", parent->GetLabel().c_str(), parent->gid);
73 lck.unlock();
74 parent->DecDeleteRef();
75 return;
76 }
77 if (parent->dependenceStatus != Dependence::CALL_DEPENDENCE) {
78 return;
79 }
80 parent->dependenceStatus = Dependence::DEPENDENCE_INIT;
81
82 if (parent->GetBlockType() == BlockType::BLOCK_THREAD) {
83 parent->waitCond_.notify_all();
84 } else {
85 FFRT_WAKE_TRACER(parent->gid);
86 parent->Ready();
87 }
88 }
89
DecWaitDataRef()90 void SCPUEUTask::DecWaitDataRef()
91 {
92 FFRT_TRACE_SCOPE(2, taskDecWaitData);
93 {
94 std::lock_guard<decltype(mutex_)> lck(mutex_);
95 if (--dataRefCnt.waitDep != 0) {
96 return;
97 }
98 if (dependenceStatus != Dependence::DATA_DEPENDENCE) {
99 return;
100 }
101 dependenceStatus = Dependence::DEPENDENCE_INIT;
102 }
103
104 if (GetBlockType() == BlockType::BLOCK_THREAD) {
105 waitCond_.notify_all();
106 } else {
107 FFRT_WAKE_TRACER(gid);
108 Ready();
109 }
110 }
111
Finish()112 void SCPUEUTask::Finish()
113 {
114 std::unique_lock<decltype(mutex_)> lck(mutex_);
115 if (childRefCnt == 0) {
116 FFRT_LOGD("free SCPUEUTask:%s gid=%lu", label.c_str(), gid);
117 lck.unlock();
118 DecDeleteRef();
119 } else {
120 SetStatus(TaskStatus::WAIT_RELEASING);
121 }
122 }
123
MultiDependenceAdd(Dependence depType)124 void SCPUEUTask::MultiDependenceAdd(Dependence depType)
125 {
126 FFRT_LOGD("task(%s) ADD_DENPENCE(%s)", label.c_str(), DependenceStr(depType));
127 dependenceStatus = depType;
128 }
129 } /* namespace ffrt */
130