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 <array>
24 #include "internal_inc/types.h"
25 #include "core/entity.h"
26 #include "eu/execute_unit.h"
27 #include "sync/sync.h"
28 #include "sched/task_scheduler.h"
29 #include "eu/worker_thread.h"
30 #include "tm/cpu_task.h"
31 #include "util/cb_func.h"
32 #include "dfx/bbox/bbox.h"
33 
34 namespace ffrt {
35 class FFRTScheduler {
36 public:
37     FFRTScheduler(const FFRTScheduler&) = delete;
38     FFRTScheduler& operator=(const FFRTScheduler&) = delete;
~FFRTScheduler()39     virtual ~FFRTScheduler()
40     {
41         for (int i = 0; i < QoS::Max(); i++) {
42             SchedulerFactory::Recycle(fifoQue[i]);
43         }
44     }
45 
46     // 获取调度器的单例
47     static FFRTScheduler* Instance();
48     static void RegistInsCb(SingleInsCB<FFRTScheduler>::Instance &&cb);
49 
50 #ifdef QOS_DEPENDENCY
onWait(const std::vector<VersionCtx * > & waitDatas,int64_t deadline)51     void onWait(const std::vector<VersionCtx*>& waitDatas, int64_t deadline)
52     {
53         for (auto data : waitDatas) {
54             if (!data->childVersions.empty()) {
55                 auto waitVersion = data->childVersions.back();
56                 if (waitVersion->status != DataStatus::IDLE) { // 数据已经被生产出来
57                     continue;
58                 }
59                 FFRT_LOGD("wait task=%p deadline=%ld", waitVersion->myProducer, deadline);
60                 updateTask(waitVersion->myProducer, deadline);
61                 UpdateVersion(waitVersion->preVersion, deadline);
62             }
63         }
64     }
65 #endif
66 
GetScheduler(const QoS & qos)67     TaskScheduler& GetScheduler(const QoS& qos)
68     {
69         return *fifoQue[static_cast<unsigned short>(qos)];
70     }
71 
72     virtual bool InsertNode(LinkedList* node, const QoS qos);
73 
74     virtual bool RemoveNode(LinkedList* node, const QoS qos);
75 
76     virtual bool WakeupTask(CPUEUTask* task);
77 
78 protected:
FFRTScheduler()79     FFRTScheduler()
80     {
81         TaskState::RegisterOps(TaskState::READY, ([this] (CPUEUTask* task) { return this->WakeupTask(task); }));
82         for (int i = 0; i < QoS::Max(); i++) {
83             fifoQue[i] = SchedulerFactory::Alloc();
84             fifoQue[i]->qos = i;
85         }
86     }
87 
88 private:
89     std::array<TaskScheduler*, QoS::MaxNum()> fifoQue;
90 #ifdef QOS_DEPENDENCY
ResetDeadline(CPUEUTask * task,int64_t deadline)91     void ResetDeadline(CPUEUTask* task, int64_t deadline)
92     {
93         auto it = std::find_if(readyTasks.begin(), readyTasks.end(), [task](auto& p) { return p.second == task; });
94         if (it == readyTasks.end()) {
95             return;
96         }
97         auto node = readyTasks.extract(it);
98         task->qos.deadline.relative += deadline - task->qos.deadline.absolute;
99         task->qos.deadline.absolute = deadline;
100         readyTasks.insert(std::move(node));
101     }
updateTask(CPUEUTask * task,int64_t deadline)102     void updateTask(CPUEUTask* task, int64_t deadline)
103     {
104         if (task == nullptr) {
105             return;
106         }
107         ResetDeadline(task, deadline);
108         onWait(task->ins, deadline);
109         for (auto data : task->outs) {
110             UpdateVersion(data, deadline);
111         }
112         UpdateChildTask(task, deadline);
113     }
UpdateChildTask(CPUEUTask * task,int64_t deadline)114     void UpdateChildTask(CPUEUTask* task, int64_t deadline)
115     {
116         (void)task;
117         (void)deadline;
118     }
UpdateVersion(VersionCtx * data,int64_t deadline)119     void UpdateVersion(VersionCtx* data, int64_t deadline)
120     {
121         if (data == nullptr) {
122             return;
123         }
124         updateTask(data->myProducer, deadline);
125         for (auto task : data->consumers) {
126             updateTask(task, deadline);
127         }
128         UpdateVersion(data->preVersion, deadline);
129     }
130 #endif
131 };
132 
133 class SFFRTScheduler : public FFRTScheduler {
134 public:
Instance()135     static FFRTScheduler& Instance()
136     {
137         static SFFRTScheduler ins;
138         return ins;
139     }
140 private:
SFFRTScheduler()141     SFFRTScheduler()
142     {
143     }
144 };
145 } // namespace ffrt
146 #endif
147