• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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