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 #ifndef FFRT_TASK_CTX_H 17 #define FFRT_TASK_CTX_H 18 19 #include <string> 20 #include <functional> 21 #include <unordered_set> 22 #include <vector> 23 #include <mutex> 24 #include <atomic> 25 #include <string> 26 #include <set> 27 #include <list> 28 #include <memory> 29 #include "internal_inc/types.h" 30 #include "sched/task_state.h" 31 #include "sched/interval.h" 32 #include "eu/co_routine.h" 33 #include "task_attr_private.h" 34 #include "util/slab.h" 35 #include "util/task_deleter.h" 36 #include "dfx/bbox/bbox.h" 37 38 namespace ffrt { 39 struct TaskCtx; 40 struct VersionCtx; 41 42 /* 43 TaskCtx 必须是数据结构ffrt_executor_task_t的子类 44 */ 45 struct TaskCtx : public TaskDeleter { 46 TaskCtx(const task_attr_private* attr, 47 TaskCtx* parent, const uint64_t& id, const char *identity = nullptr, const QoS& qos = QoS()); 48 WaitUntilEntry* wue; 49 bool wakeupTimeOut = false; 50 bool is_native_func = false; 51 SkipStatus skipped = SkipStatus::SUBMITTED; 52 53 uint8_t func_storage[ffrt_auto_managed_function_storage_size]; // 函数闭包、指针或函数对象 54 TaskCtx* parent = nullptr; 55 const uint64_t rank = 0x0; 56 std::unordered_set<VersionCtx*> ins; 57 std::unordered_set<VersionCtx*> outs; 58 std::vector<TaskCtx*> in_handles; 59 CoRoutine* coRoutine = nullptr; 60 std::vector<std::string> traceTag; 61 62 #ifdef MUTEX_PERF // Mutex Lock&Unlock Cycles Statistic 63 xx::mutex lock {"TaskCtx::lock"}; 64 #else 65 std::mutex lock; // used in coroute 66 #endif 67 uint64_t myRefCnt = 0; 68 69 TaskState state; 70 #ifdef MUTEX_PERF // Mutex Lock&Unlock Cycles Statistic 71 xx::mutex denpenceStatusLock {"TaskCtx::denpenceStatusLock"}; 72 #else 73 std::mutex denpenceStatusLock; 74 #endif 75 uint64_t pmuCntBegin = 0; 76 uint64_t pmuCnt = 0; 77 Denpence denpenceStatus {Denpence::DEPENCE_INIT}; 78 /* The current number of child nodes does not represent the real number of child nodes, 79 * because the dynamic graph child nodes will grow to assist in the generation of id 80 */ 81 std::atomic<uint64_t> childNum {0}; 82 std::atomic_uint64_t depRefCnt {0}; 83 84 std::atomic_uint64_t childWaitRefCnt {0}; 85 std::condition_variable childWaitCond_; 86 87 uint64_t dataWaitRefCnt {0}; // waited data count called by ffrt_wait() 88 std::condition_variable dataWaitCond_; // wait data cond 89 TaskStatus status = TaskStatus::PENDING; 90 91 void InitRelatedIntervals(TaskCtx* curr); 92 std::unordered_set<Interval*> relatedIntervals; 93 94 const char* identity; 95 int64_t ddlSlack = INT64_MAX; 96 uint64_t load = 0; 97 int64_t ddl = INT64_MAX; 98 99 QoS qos; 100 void SetQos(QoS& qos); 101 freeMemTaskCtx102 inline void freeMem() override 103 { 104 BboxCheckAndFreeze(); 105 SimpleAllocator<TaskCtx>::freeMem(this); 106 } 107 IncDepRefTaskCtx108 inline void IncDepRef() 109 { 110 ++depRefCnt; 111 } 112 void DecDepRef(); 113 IncChildRefTaskCtx114 inline void IncChildRef() 115 { 116 ++(parent->childWaitRefCnt); 117 } 118 void DecChildRef(); 119 IncWaitDataRefTaskCtx120 inline void IncWaitDataRef() 121 { 122 ++dataWaitRefCnt; 123 } 124 void DecWaitDataRef(); 125 126 void DealChildWait(); 127 void DealDataWait(); 128 void RecycleTask(); 129 bool IsPrevTask(const TaskCtx* task) const; 130 void MultiDepenceAdd(Denpence depType); 131 132 std::string label; // used for debug 133 IsRootTaskCtx134 inline bool IsRoot() 135 { 136 if (parent == nullptr) { 137 return true; 138 } 139 return false; 140 } 141 UpdateStateTaskCtx142 int UpdateState(TaskState::State taskState) 143 { 144 return TaskState::OnTransition(taskState, this); 145 } 146 UpdateStateTaskCtx147 int UpdateState(TaskState::State taskState, TaskState::Op&& op) 148 { 149 return TaskState::OnTransition(taskState, this, std::move(op)); 150 } 151 SetTraceTagTaskCtx152 void SetTraceTag(const std::string& name) 153 { 154 traceTag.push_back(name); 155 } 156 ClearTraceTagTaskCtx157 void ClearTraceTag() 158 { 159 if (!traceTag.empty()) { 160 traceTag.pop_back(); 161 } 162 } 163 164 #ifdef FFRT_CO_BACKTRACE_OH_ENABLE 165 static void DumpTask(TaskCtx* task, std::string& stackInfo, uint8_t flag = 0); /* 0:hilog others:hiview */ 166 #endif 167 }; 168 169 class RootTaskCtx : public TaskCtx { 170 public: 171 RootTaskCtx(const task_attr_private* attr, TaskCtx* parent, const uint64_t& id, TaskCtx(attr,parent,id,identity,qos)172 const char *identity = nullptr, const QoS& qos = QoS()) : TaskCtx(attr, parent, id, identity, qos) 173 { 174 } 175 public: 176 bool thread_exit = false; 177 }; 178 179 class RootTaskCtxWrapper { 180 public: RootTaskCtxWrapper()181 RootTaskCtxWrapper() 182 { 183 task_attr_private task_attr; 184 root = new RootTaskCtx {&task_attr, nullptr, 0, nullptr}; 185 } ~RootTaskCtxWrapper()186 ~RootTaskCtxWrapper() 187 { 188 std::unique_lock<decltype(root->lock) > lck(root->lock); 189 if (root->childWaitRefCnt == 0) { 190 lck.unlock(); 191 delete root; 192 } else { 193 root->thread_exit = true ; 194 } 195 } Root()196 TaskCtx* Root() 197 { 198 return root; 199 } 200 private: 201 RootTaskCtx *root = nullptr; 202 }; 203 } /* namespace ffrt */ 204 #endif 205