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_SCHEDULER_HPP 17 #define FFRT_SCHEDULER_HPP 18 #include <list> 19 #include <vector> 20 #include <string> 21 #include <map> 22 #include <mutex> 23 #include <atomic> 24 #include <array> 25 #include "internal_inc/types.h" 26 #include "core/entity.h" 27 #include "eu/execute_unit.h" 28 #include "sync/sync.h" 29 #include "sched/task_scheduler.h" 30 #include "eu/worker_thread.h" 31 32 namespace ffrt { 33 class FFRTScheduler { 34 public: 35 FFRTScheduler(const FFRTScheduler&) = delete; 36 FFRTScheduler& operator=(const FFRTScheduler&) = delete; ~FFRTScheduler()37 ~FFRTScheduler() 38 { 39 } 40 41 // 获取调度器的单例 Instance()42 static inline FFRTScheduler* Instance() 43 { 44 static FFRTScheduler sched; 45 return &sched; 46 } 47 48 #ifdef QOS_DEPENDENCY onWait(const std::vector<VersionCtx * > & waitDatas,int64_t deadline)49 void onWait(const std::vector<VersionCtx*>& waitDatas, int64_t deadline) 50 { 51 for (auto data : waitDatas) { 52 if (!data->childVersions.empty()) { 53 auto waitVersion = data->childVersions.back(); 54 if (waitVersion->status != DataStatus::IDLE) { // 数据已经被生产出来 55 continue; 56 } 57 FFRT_LOGD("wait task=%p deadline=%ld", waitVersion->myProducer, deadline); 58 updateTask(waitVersion->myProducer, deadline); 59 updateVersion(waitVersion->preVersion, deadline); 60 } 61 } 62 } 63 #endif 64 GetScheduler(const QoS & qos)65 FIFOScheduler& GetScheduler(const QoS& qos) 66 { 67 return fifoQue[static_cast<size_t>(qos)]; 68 } 69 PushTask(TaskCtx * task)70 void PushTask(TaskCtx* task) 71 { 72 fifoQue[static_cast<size_t>(task->qos())].WakeupTask(task); 73 } 74 WakeupTask(TaskCtx * task)75 bool WakeupTask(TaskCtx* task) 76 { 77 int qos_level = static_cast<int>(qos_default); 78 if (task != nullptr) { 79 qos_level = task->qos(); 80 if (qos_level == qos_inherit) { 81 return false; 82 } 83 } 84 QoS _qos = QoS(qos_level); 85 int level = _qos(); 86 auto lock = ExecuteUnit::Instance().GetSleepCtl(level); 87 lock->lock(); 88 fifoQue[static_cast<size_t>(level)].WakeupTask(task); 89 lock->unlock(); 90 FFRT_LOGI("qos[%d] task[%lu] entered q", level, task->gid); 91 ExecuteUnit::Instance().NotifyTaskAdded(level); 92 return true; 93 } 94 InsertNode(LinkedList * node,const QoS qos)95 bool InsertNode(LinkedList* node, const QoS qos) 96 { 97 int qos_level = static_cast<int>(qos_default); 98 if (node != nullptr) { 99 qos_level = qos(); 100 if (qos_level == qos_inherit) { 101 return false; 102 } 103 } 104 QoS _qos = QoS(qos_level); 105 int level = _qos(); 106 auto lock = ExecuteUnit::Instance().GetSleepCtl(level); 107 lock->lock(); 108 fifoQue[static_cast<size_t>(level)].WakeupNode(node); 109 lock->unlock(); 110 ExecuteUnit::Instance().NotifyTaskAdded(level); 111 return true; 112 } 113 RemoveNode(LinkedList * node,const QoS qos)114 bool RemoveNode(LinkedList* node, const QoS qos) 115 { 116 int qos_level = static_cast<int>(qos_default); 117 if (node != nullptr) { 118 qos_level = qos(); 119 if (qos_level == qos_inherit) { 120 return false; 121 } 122 } 123 QoS _qos = QoS(qos_level); 124 int level = _qos(); 125 auto lock = ExecuteUnit::Instance().GetSleepCtl(level); 126 lock->lock(); 127 if (!node->InList()) { 128 lock->unlock(); 129 return false; 130 } 131 fifoQue[static_cast<size_t>(level)].RemoveNode(node); 132 lock->unlock(); 133 #ifdef FFRT_BBOX_ENABLE 134 TaskFinishCounterInc(); 135 #endif 136 return true; 137 } 138 139 private: FFRTScheduler()140 FFRTScheduler() 141 { 142 TaskState::RegisterOps(TaskState::READY, std::bind(&FFRTScheduler::WakeupTask, this, std::placeholders::_1)); 143 } 144 std::array<FIFOScheduler, QoS::Max()> fifoQue; 145 146 #ifdef QOS_DEPENDENCY resetDeadline(TaskCtx * task,int64_t deadline)147 void resetDeadline(TaskCtx* task, int64_t deadline) 148 { 149 auto it = std::find_if(readyTasks.begin(), readyTasks.end(), [task](auto& p) { return p.second == task; }); 150 if (it == readyTasks.end()) { 151 return; 152 } 153 auto node = readyTasks.extract(it); 154 task->qos.deadline.relative += deadline - task->qos.deadline.absolute; 155 task->qos.deadline.absolute = deadline; 156 readyTasks.insert(std::move(node)); 157 } updateTask(TaskCtx * task,int64_t deadline)158 void updateTask(TaskCtx* task, int64_t deadline) 159 { 160 if (task == nullptr) { 161 return; 162 } 163 resetDeadline(task, deadline); 164 onWait(task->ins, deadline); 165 for (auto data : task->outs) { 166 updateVersion(data, deadline); 167 } 168 updateChildTask(task, deadline); 169 } updateChildTask(TaskCtx * task,int64_t deadline)170 void updateChildTask(TaskCtx* task, int64_t deadline) 171 { 172 (void)task; 173 (void)deadline; 174 } updateVersion(VersionCtx * data,int64_t deadline)175 void updateVersion(VersionCtx* data, int64_t deadline) 176 { 177 if (data == nullptr) { 178 return; 179 } 180 updateTask(data->myProducer, deadline); 181 for (auto task : data->consumers) { 182 updateTask(task, deadline); 183 } 184 updateVersion(data->preVersion, deadline); 185 } 186 #endif 187 }; 188 } // namespace ffrt 189 #endif 190