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