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 {
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 
SCPUEUTask(const task_attr_private * attr,CPUEUTask * parent,const uint64_t & id,const QoS & qos)39 SCPUEUTask::SCPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id,
40     const QoS &qos)
41     : CPUEUTask(attr, parent, id, qos)
42 {
43 }
44 
DecDepRef()45 void SCPUEUTask::DecDepRef()
46 {
47     if (--dataRefCnt.submitDep == 0) {
48         FFRT_LOGD("Undependency completed, enter ready queue, task[%lu], name[%s]", gid, label.c_str());
49         FFRT_WAKE_TRACER(this->gid);
50         FFRTTraceRecord::TaskEnqueue<ffrt_normal_task>(GetQos());
51         this->UpdateState(TaskState::READY);
52     }
53 }
54 
DecChildRef()55 void SCPUEUTask::DecChildRef()
56 {
57     SCPUEUTask* parent = reinterpret_cast<SCPUEUTask*>(this->parent);
58     FFRT_TRACE_SCOPE(2, taskDecChildRef);
59     std::unique_lock<decltype(parent->mutex_)> lck(parent->mutex_);
60     parent->childRefCnt--;
61     if (parent->childRefCnt != 0) {
62         return;
63     }
64     if (FFRT_UNLIKELY(parent->IsRoot())) {
65         RootTask *root = static_cast<RootTask *>(parent);
66         if (root->thread_exit) {
67             lck.unlock();
68             delete root;
69             return;
70         }
71     }
72 
73     if (!parent->IsRoot() && parent->status == TaskStatus::RELEASED && parent->childRefCnt == 0) {
74         FFRT_LOGD("free CPUEUTask:%s gid=%lu", parent->label.c_str(), parent->gid);
75         lck.unlock();
76         parent->DecDeleteRef();
77         return;
78     }
79     if (parent->denpenceStatus != Denpence::CALL_DEPENCE) {
80         return;
81     }
82     parent->denpenceStatus = Denpence::DEPENCE_INIT;
83 
84     if (ThreadNotifyMode(parent) || parent->IsRoot()) {
85         if (BlockThread(parent)) {
86             parent->blockType = BlockType::BLOCK_COROUTINE;
87         }
88         parent->waitCond_.notify_all();
89     } else {
90         FFRT_WAKE_TRACER(parent->gid);
91         parent->UpdateState(TaskState::READY);
92     }
93 }
94 
DecWaitDataRef()95 void SCPUEUTask::DecWaitDataRef()
96 {
97     FFRT_TRACE_SCOPE(2, taskDecWaitData);
98     {
99         std::lock_guard<decltype(mutex_)> lck(mutex_);
100         if (--dataRefCnt.waitDep != 0) {
101             return;
102         }
103         if (denpenceStatus != Denpence::DATA_DEPENCE) {
104             return;
105         }
106         denpenceStatus = Denpence::DEPENCE_INIT;
107     }
108 
109     if (ThreadNotifyMode(this) || IsRoot()) {
110         if (BlockThread(this)) {
111             blockType = BlockType::BLOCK_COROUTINE;
112         }
113         waitCond_.notify_all();
114     } else {
115         FFRT_WAKE_TRACER(this->gid);
116         FFRTTraceRecord::TaskEnqueue<ffrt_normal_task>(GetQos());
117         this->UpdateState(TaskState::READY);
118     }
119 }
120 
RecycleTask()121 void SCPUEUTask::RecycleTask()
122 {
123     std::unique_lock<decltype(mutex_)> lck(mutex_);
124     if (childRefCnt == 0) {
125         FFRT_LOGD("free SCPUEUTask:%s gid=%lu", label.c_str(), gid);
126         lck.unlock();
127         DecDeleteRef();
128         return;
129     } else {
130         status = TaskStatus::RELEASED;
131     }
132 }
133 
MultiDepenceAdd(Denpence depType)134 void SCPUEUTask::MultiDepenceAdd(Denpence depType)
135 {
136     FFRT_LOGD("task(%s) ADD_DENPENCE(%s)", this->label.c_str(), DenpenceStr(depType));
137     denpenceStatus = depType;
138 }
139 } /* namespace ffrt */