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_INTERVAL_HPP 17 #define FFRT_INTERVAL_HPP 18 19 #include <deque> 20 #ifdef USE_OHOS_QOS 21 #include "qos.h" 22 #else 23 #include "staging_qos/sched/qos.h" 24 #endif 25 #include "sched/load_predictor.h" 26 #include "sched/load_tracking.h" 27 #include "eu/thread_group.h" 28 #include "sync/sync.h" 29 30 namespace ffrt { 31 class Interval; 32 constexpr uint64_t NS_PER_US = 1000; 33 constexpr uint64_t NS_PER_MS = 1000000; 34 class Deadline { 35 public: Deadline(uint64_t deadlineUs)36 Deadline(uint64_t deadlineUs) 37 { 38 Update(deadlineUs); 39 } 40 ToNs()41 uint64_t ToNs() const 42 { 43 return deadlineNs; 44 } 45 ToUs()46 uint64_t ToUs() const 47 { 48 uint64_t us = deadlineNs / NS_PER_US; 49 return us > 0 ? us : 1; 50 } 51 ToMs()52 uint64_t ToMs() const 53 { 54 uint64_t ms = deadlineNs / NS_PER_MS; 55 return ms > 0 ? ms : 1; 56 } 57 LeftNs()58 uint64_t LeftNs() const 59 { 60 uint64_t nowNs = AbsNowNs(); 61 uint64_t left = (absDeadlineNs > nowNs) ? (absDeadlineNs - nowNs) : 1; 62 return left; 63 } 64 65 void Update(uint64_t deadlineUs); 66 67 private: 68 static uint64_t AbsNowNs(); 69 70 uint64_t deadlineNs = 0; 71 uint64_t absDeadlineNs = 0; 72 }; 73 74 class PerfCtrl { 75 public: 76 PerfCtrl(const QoS& qos); 77 ~PerfCtrl(); 78 Qos()79 const QoS& Qos() const 80 { 81 return qos; 82 } 83 TG()84 ThreadGroup* TG() 85 { 86 return tg; 87 } 88 isBusy()89 bool isBusy() 90 { 91 if (tg) { 92 return tg->isBegin(); 93 } 94 95 return false; 96 } 97 Begin()98 void Begin() 99 { 100 if (tg) { 101 tg->Begin(); 102 } 103 } 104 End()105 void End() 106 { 107 if (tg) { 108 tg->End(); 109 } 110 } 111 GetLoad()112 uint64_t GetLoad() 113 { 114 return tg ? tg->GetLoad().load : 0; 115 } 116 SetWindowSize(uint64_t size)117 void SetWindowSize(uint64_t size) 118 { 119 if (tg) { 120 tg->SetWindowSize(size); 121 } 122 } 123 SetInvalidInterval(uint64_t interval)124 void SetInvalidInterval(uint64_t interval) 125 { 126 if (tg) { 127 tg->SetInvalidInterval(interval); 128 } 129 } 130 Join()131 bool Join() 132 { 133 return tg ? tg->Join() : false; 134 } 135 Leave()136 bool Leave() 137 { 138 return tg ? tg->Leave() : false; 139 } 140 Clear()141 void Clear() 142 { 143 predUtil = 0; 144 curUtil = 0; 145 } 146 147 void Update(bool force = false); 148 void Update(uint64_t deadlineNs, uint64_t load, bool force = false); 149 150 private: 151 static constexpr int SCHED_CAPACITY_SHIFT = 10; 152 static constexpr int SCHED_MAX_CAPACITY = 1 << SCHED_CAPACITY_SHIFT; 153 154 QoS qos; 155 ThreadGroup* tg = nullptr; 156 157 uint64_t predUtil = 0; 158 uint64_t curUtil = 0; 159 }; 160 161 class IntervalLoadPredictor { 162 public: IntervalLoadPredictor()163 IntervalLoadPredictor() 164 { 165 cpLoad.resize(1); 166 } 167 ResetCPIndex()168 void ResetCPIndex() 169 { 170 cpLoadIndex = 0; 171 } 172 173 void UpdateTotalLoad(uint64_t load); 174 void UpdateCPLoad(uint64_t load); 175 176 uint64_t GetTotalLoad(); 177 uint64_t GetCPLoad(); 178 179 private: 180 SimpleLoadPredictor totalLoad; 181 std::deque<SimpleLoadPredictor> cpLoad; 182 uint32_t cpLoadIndex = 0; 183 }; 184 185 class Interval { 186 public: 187 Interval(uint64_t deadlineUs,const QoS & qos)188 Interval(uint64_t deadlineUs, const QoS& qos) : dl(deadlineUs) 189 { 190 (void)qos; 191 } 192 virtual ~Interval() = default; 193 194 virtual int Begin() = 0; 195 196 virtual void Update(uint64_t deadlineUs) = 0; 197 198 virtual void End() = 0; 199 200 virtual void CheckPoint() = 0; 201 202 virtual void Join() = 0; 203 204 virtual void Leave() = 0; 205 206 virtual const QoS& Qos() const = 0; 207 UpdateTaskSwitch(TaskSwitchState state)208 virtual void UpdateTaskSwitch(TaskSwitchState state) 209 { 210 } 211 Ddl()212 Deadline& Ddl() 213 { 214 return dl; 215 } 216 private: 217 Deadline dl; 218 }; 219 220 class DefaultInterval : public Interval { 221 public: 222 DefaultInterval(uint64_t deadlineUs, const QoS& qos); 223 ~DefaultInterval() override; 224 Enabled()225 bool Enabled() const 226 { 227 return enabled; 228 } 229 Qos()230 const QoS& Qos() const override 231 { 232 return ctrl.Qos(); 233 } 234 Ctrl()235 PerfCtrl& Ctrl() 236 { 237 return ctrl; 238 } 239 240 int Begin() override; 241 242 void Update(uint64_t deadlineUs) override; 243 244 void End() override; 245 246 void CheckPoint() override; 247 248 void Join() override; 249 250 void Leave() override; 251 252 void UpdateTaskSwitch(TaskSwitchState state) override; 253 254 private: 255 bool enabled = false; 256 257 KernelLoadTracking lt; 258 IntervalLoadPredictor lp; 259 PerfCtrl ctrl; 260 261 fast_mutex mutex; 262 }; 263 } // namespace ffrt 264 265 #endif 266