• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "UClampVoter.h"
18 
19 namespace aidl {
20 namespace google {
21 namespace hardware {
22 namespace power {
23 namespace impl {
24 namespace pixel {
25 
confine(UclampRange & uclampRange,const CpuVote & cpu_vote,std::chrono::steady_clock::time_point t)26 static void confine(UclampRange &uclampRange, const CpuVote &cpu_vote,
27                     std::chrono::steady_clock::time_point t) {
28     if (!cpu_vote.isTimeInRange(t)) {
29         return;
30     }
31     uclampRange.uclampMin = std::max(uclampRange.uclampMin, cpu_vote.mUclampRange.uclampMin);
32     uclampRange.uclampMax = std::min(uclampRange.uclampMax, cpu_vote.mUclampRange.uclampMax);
33 }
34 
operator <<(std::ostream & o,const UclampRange & uc)35 std::ostream &operator<<(std::ostream &o, const UclampRange &uc) {
36     o << "[" << uc.uclampMin << "," << uc.uclampMax << "]";
37     return o;
38 }
39 
Votes()40 Votes::Votes() {}
41 
42 constexpr static auto gpu_vote_id = static_cast<int>(AdpfVoteType::GPU_CAPACITY);
43 
isGpuVote(int type_raw)44 static inline bool isGpuVote(int type_raw) {
45     AdpfVoteType const type = static_cast<AdpfVoteType>(type_raw);
46     return type == AdpfVoteType::GPU_CAPACITY || type == AdpfVoteType::GPU_LOAD_UP ||
47            type == AdpfVoteType::GPU_LOAD_DOWN || type == AdpfVoteType::GPU_LOAD_RESET;
48 }
49 
add(int id,CpuVote const & vote)50 void Votes::add(int id, CpuVote const &vote) {
51     if (!isGpuVote(id)) {
52         mCpuVotes[id] = vote;
53     }
54 }
55 
getGpuCapacityRequest(std::chrono::steady_clock::time_point t) const56 std::optional<Cycles> Votes::getGpuCapacityRequest(std::chrono::steady_clock::time_point t) const {
57     std::optional<Cycles> res = std::nullopt;
58 
59     constexpr AdpfVoteType gpu_capacity_hints[] = {
60             AdpfVoteType::GPU_CAPACITY,
61             AdpfVoteType::GPU_LOAD_UP,
62     };
63     for (auto const hint : gpu_capacity_hints) {
64         auto it = mGpuVotes.find(static_cast<int>(hint));
65         if (it != mGpuVotes.end() && it->second.isTimeInRange(t)) {
66             res = res.value_or(Cycles(0)) + it->second.mCapacity;
67         }
68     }
69 
70     return res;
71 }
72 
add(int id,GpuVote const & vote)73 void Votes::add(int id, GpuVote const &vote) {
74     if (isGpuVote(id)) {
75         mGpuVotes[id] = vote;
76     }
77 }
78 
updateDuration(int voteId,std::chrono::nanoseconds durationNs)79 void Votes::updateDuration(int voteId, std::chrono::nanoseconds durationNs) {
80     if (isGpuVote(voteId)) {
81         auto const it = mGpuVotes.find(voteId);
82         if (it != mGpuVotes.end()) {
83             it->second.updateDuration(durationNs);
84         }
85         return;
86     }
87 
88     auto const voteItr = mCpuVotes.find(voteId);
89     if (voteItr != mCpuVotes.end()) {
90         voteItr->second.updateDuration(durationNs);
91     }
92 }
93 
getUclampRange(UclampRange & uclampRange,std::chrono::steady_clock::time_point t) const94 void Votes::getUclampRange(UclampRange &uclampRange,
95                            std::chrono::steady_clock::time_point t) const {
96     for (auto it = mCpuVotes.begin(); it != mCpuVotes.end(); it++) {
97         auto timings_it = mCpuVotes.find(it->first);
98         confine(uclampRange, it->second, t);
99     }
100 }
101 
anyTimedOut(std::chrono::steady_clock::time_point t) const102 bool Votes::anyTimedOut(std::chrono::steady_clock::time_point t) const {
103     for (const auto &v : mGpuVotes) {
104         if (!v.second.isTimeInRange(t)) {
105             return true;
106         }
107     }
108 
109     for (const auto &v : mCpuVotes) {
110         if (!v.second.isTimeInRange(t)) {
111             return true;
112         }
113     }
114     return false;
115 }
116 
allTimedOut(std::chrono::steady_clock::time_point t) const117 bool Votes::allTimedOut(std::chrono::steady_clock::time_point t) const {
118     for (const auto &v : mGpuVotes) {
119         if (v.second.isTimeInRange(t)) {
120             return false;
121         }
122     }
123 
124     for (const auto &v : mCpuVotes) {
125         if (v.second.isTimeInRange(t)) {
126             return false;
127         }
128     }
129     return true;
130 }
131 
remove(int voteId)132 bool Votes::remove(int voteId) {
133     if (isGpuVote(voteId)) {
134         auto const it = mGpuVotes.find(voteId);
135         if (it != mGpuVotes.end()) {
136             mGpuVotes.erase(it);
137             return true;
138         }
139         return false;
140     }
141 
142     auto const it = mCpuVotes.find(voteId);
143     if (it != mCpuVotes.end()) {
144         mCpuVotes.erase(it);
145         return true;
146     }
147 
148     return false;
149 }
150 
setUseVote(int voteId,bool active)151 bool Votes::setUseVote(int voteId, bool active) {
152     if (isGpuVote(voteId)) {
153         auto const itr = mGpuVotes.find(voteId);
154         if (itr == mGpuVotes.end()) {
155             return false;
156         }
157         itr->second.setActive(active);
158         return true;
159     }
160 
161     auto const itr = mCpuVotes.find(voteId);
162     if (itr == mCpuVotes.end()) {
163         return false;
164     }
165     itr->second.setActive(active);
166     return true;
167 }
168 
size() const169 size_t Votes::size() const {
170     return mCpuVotes.size() + mGpuVotes.size();
171 }
172 
voteIsActive(int voteId) const173 bool Votes::voteIsActive(int voteId) const {
174     if (isGpuVote(voteId)) {
175         auto const itr = mGpuVotes.find(voteId);
176         if (itr == mGpuVotes.end()) {
177             return false;
178         }
179         return itr->second.active();
180     }
181 
182     auto const itr = mCpuVotes.find(voteId);
183     if (itr == mCpuVotes.end()) {
184         return false;
185     }
186     return itr->second.active();
187 }
188 
voteTimeout(int voteId) const189 std::chrono::steady_clock::time_point Votes::voteTimeout(int voteId) const {
190     if (isGpuVote(voteId)) {
191         auto const itr = mGpuVotes.find(voteId);
192         if (itr == mGpuVotes.end()) {
193             return std::chrono::steady_clock::time_point{};
194         }
195         return itr->second.startTime() + itr->second.durationNs();
196     }
197 
198     auto const itr = mCpuVotes.find(voteId);
199     if (itr == mCpuVotes.end()) {
200         return std::chrono::steady_clock::time_point{};
201     }
202     return itr->second.startTime() + itr->second.durationNs();
203 }
204 
205 }  // namespace pixel
206 }  // namespace impl
207 }  // namespace power
208 }  // namespace hardware
209 }  // namespace google
210 }  // namespace aidl
211