• 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 #include <cstdio>
16 #include <cstdlib>
17 #include <cstring>
18 #include <mutex>
19 #include "workgroup_internal.h"
20 #include "dfx/log/ffrt_log_api.h"
21 #include "task_client_adapter.h"
22 
23 
24 #if (defined(QOS_WORKER_FRAME_RTG) || defined(QOS_FRAME_RTG))
25 constexpr int HWC_UID = 3039;
26 constexpr int ROOT_UID = 0;
27 constexpr int RS_RTG_ID = 10;
28 
29 namespace ffrt {
30 static int wgId = -1;
31 static WorkGroup* rsWorkGroup = nullptr;
32 static int wgCount = 0;
33 static std::mutex wgLock;
34 
35 #if (defined(QOS_WORKER_FRAME_RTG))
36 
WorkgroupInit(struct WorkGroup * wg,uint64_t interval,int rtgId)37 void WorkgroupInit(struct WorkGroup* wg, uint64_t interval, int rtgId)
38 {
39     wg->started = false;
40     wg->interval = interval;
41     wg->rtgId = rtgId;
42     wgId = rtgId;
43 
44     for (int i = 0; i < MAX_WG_THREADS; i++) {
45         wg->tids[i] = -1;
46     }
47 }
48 
FindThreadInWorkGroup(WorkGroup * workGroup,int tid)49 int FindThreadInWorkGroup(WorkGroup *workGroup, int tid)
50 {
51     if (workGroup == nullptr) {
52         FFRT_LOGE("[RSWorkGroup] find thread %{public}d in workGroup failed, workGroup is null", tid);
53         return -1;
54     }
55     for (int i = 0;i < MAX_WG_THREADS; i++) {
56         if (workGroup->tids[i] == tid) {
57             return i;
58         }
59     }
60     return -1;
61 }
62 
InsertThreadInWorkGroup(WorkGroup * workGroup,int tid)63 bool InsertThreadInWorkGroup(WorkGroup *workGroup, int tid)
64 {
65     if (workGroup == nullptr) {
66         FFRT_LOGE("[RSWorkGroup] join thread %{public}d into workGroup failed, workGroup is null", tid);
67         return false;
68     }
69     for (int i = 0; i < MAX_WG_THREADS; i++) {
70         if (workGroup->tids[i] == -1) {
71             workGroup->tids[i] = tid;
72             return true;
73         }
74     }
75     return false;
76 }
77 
CreateRSWorkGroup(uint64_t interval)78 WorkGroup* CreateRSWorkGroup(uint64_t interval)
79 {
80     IntervalReply rs;
81     rs.rtgId = -1;
82     rs.tid = -1;
83     {
84         std::lock_guard<std::mutex> lck(wgLock);
85         if (rsWorkGroup == nullptr) {
86             CTC_QUERY_INTERVAL(QUERY_RENDER_SERVICE, rs);
87             if (rs.rtgId > 0) {
88                 rsWorkGroup = new struct WorkGroup();
89                 if (rsWorkGroup == nullptr) {
90                     FFRT_LOGE("[RSWorkGroup] rsWorkGroup malloc failed!");
91                     return nullptr;
92                 }
93                 WorkgroupInit(rsWorkGroup, interval, rs.rtgId);
94                 wgCount++;
95             }
96         }
97     }
98     return rsWorkGroup;
99 }
100 
LeaveRSWorkGroup(int tid)101 bool LeaveRSWorkGroup(int tid)
102 {
103     std::lock_guard<std::mutex> lck(wgLock);
104     if (rsWorkGroup == nullptr) {
105         FFRT_LOGI("[RSWorkGroup] LeaveRSWorkGroup rsWorkGroup is null ,tid:%{public}d", tid);
106         return false;
107     }
108     int existIndex = FindThreadInWorkGroup(rsWorkGroup, tid);
109     if (existIndex != -1) {
110         rsWorkGroup->tids[existIndex] = -1;
111     }
112     FFRT_LOGI("[RSWorkGroup] LeaveRSWorkGroup ,tid: %{public}d, existIndex: %{public}d", tid, existIndex);
113     return true;
114 }
115 
JoinRSWorkGroup(int tid)116 bool JoinRSWorkGroup(int tid)
117 {
118     std::lock_guard<std::mutex> lck(wgLock);
119     if (rsWorkGroup == nullptr) {
120         FFRT_LOGE("[RSWorkGroup] join thread %{public}d into RSWorkGroup failed; Create RSWorkGroup first", tid);
121         return false;
122     }
123     int existIndex = FindThreadInWorkGroup(rsWorkGroup, tid);
124     if (existIndex == -1) {
125         IntervalReply rs;
126         rs.rtgId = -1;
127         rs.tid = tid;
128         CTC_QUERY_INTERVAL(QUERY_RENDER_SERVICE, rs);
129         if (rs.rtgId > 0) {
130             bool success = InsertThreadInWorkGroup(rsWorkGroup, tid);
131             if (!success) {
132                 return false;
133             }
134         }
135     }
136     FFRT_LOGI("[RSWorkGroup] update thread %{public}d success", tid);
137     return true;
138 }
139 
DestoryRSWorkGroup()140 bool DestoryRSWorkGroup()
141 {
142     std::lock_guard<std::mutex> lck(wgLock);
143     if (rsWorkGroup != nullptr) {
144         delete rsWorkGroup;
145         rsWorkGroup = nullptr;
146         wgId = -1;
147         return true;
148     }
149     return false;
150 }
151 #endif
152 
153 #if defined(QOS_FRAME_RTG)
JoinWG(int tid)154 bool JoinWG(int tid)
155 {
156     if (wgId < 0) {
157         if (wgCount > 0) {
158             FFRT_LOGE("[WorkGroup] interval is unavailable");
159         }
160         return false;
161     }
162     int uid = getuid();
163     if (uid == RS_UID) {
164         return JoinRSWorkGroup(tid);
165     }
166     int addRet = AddThreadToRtgAdapter(tid, wgId, 0);
167     if (addRet == 0) {
168         FFRT_LOGI("[WorkGroup] update thread %{public}d success", tid);
169     } else {
170         FFRT_LOGE("[WorkGroup] update thread %{public}d failed, return %{public}d", tid, addRet);
171     }
172     return true;
173 }
174 
LeaveWG(int tid)175 bool LeaveWG(int tid)
176 {
177     int uid = getuid();
178     if (uid == RS_UID) {
179         return LeaveRSWorkGroup(tid);
180     }
181     return false;
182 }
183 
WorkgroupCreate(uint64_t interval)184 struct WorkGroup* WorkgroupCreate(uint64_t interval)
185 {
186     int rtgId = -1;
187     int uid = getuid();
188     int num = 0;
189 
190     if (uid == RS_UID) {
191         CreateRSWorkGroup(interval);
192         return rsWorkGroup;
193     }
194 
195     if (rtgId < 0) {
196         FFRT_LOGE("[WorkGroup] create rtg group %d failed", rtgId);
197         return nullptr;
198     }
199     FFRT_LOGI("[WorkGroup] create rtg group %d success", rtgId);
200 
201     WorkGroup* wg = nullptr;
202     wg = new struct WorkGroup();
203     if (wg == nullptr) {
204         FFRT_LOGE("[WorkGroup] workgroup malloc failed!");
205         return nullptr;
206     }
207     WorkgroupInit(wg, interval, rtgId);
208     {
209         std::lock_guard<std::mutex> lck(wgLock);
210         wgCount++;
211     }
212     return wg;
213 }
214 
WorkgroupClear(struct WorkGroup * wg)215 int WorkgroupClear(struct WorkGroup* wg)
216 {
217     int uid = getuid();
218     if (uid == RS_UID) {
219         return DestoryRSWorkGroup();
220     }
221     if (wg == nullptr) {
222         FFRT_LOGE("[WorkGroup] input workgroup is null");
223         return 0;
224     }
225     int ret = -1;
226     if (uid != RS_UID) {
227         ret = DestroyRtgGrpAdapter(wg->rtgId);
228         if (ret != 0) {
229             FFRT_LOGE("[WorkGroup] destroy rtg group failed");
230         } else {
231             std::lock_guard<std::mutex> lck(wgLock);
232             wgCount--;
233         }
234     }
235     delete wg;
236     wg = nullptr;
237     return ret;
238 }
239 
WorkgroupStartInterval(struct WorkGroup * wg)240 void WorkgroupStartInterval(struct WorkGroup* wg)
241 {
242     if (wg == nullptr) {
243         FFRT_LOGE("[WorkGroup] input workgroup is null");
244         return;
245     }
246 
247     if (wg->started) {
248         FFRT_LOGW("[WorkGroup] already start");
249         return;
250     }
251 
252     if (BeginFrameFreqAdapter(0) == 0) {
253         wg->started = true;
254     } else {
255         FFRT_LOGE("[WorkGroup] start rtg(%d) work interval failed", wg->rtgId);
256     }
257 }
258 
WorkgroupStopInterval(struct WorkGroup * wg)259 void WorkgroupStopInterval(struct WorkGroup* wg)
260 {
261     if (wg == nullptr) {
262         FFRT_LOGE("[WorkGroup] input workgroup is null");
263         return;
264     }
265 
266     if (!wg->started) {
267         FFRT_LOGW("[WorkGroup] already stop");
268         return;
269     }
270 
271     int ret = EndFrameFreqAdapter(0);
272     if (ret == 0) {
273         wg->started = false;
274     } else {
275         FFRT_LOGE("[WorkGroup] stop rtg(%d) work interval failed", wg->rtgId);
276     }
277 }
278 
WorkgroupJoin(struct WorkGroup * wg,int tid)279 void WorkgroupJoin(struct WorkGroup* wg, int tid)
280 {
281     if (wg == nullptr) {
282         FFRT_LOGE("[WorkGroup] input workgroup is null");
283         return;
284     }
285     int uid = getuid();
286     FFRT_LOGI("[WorkGroup] %s uid = %d rtgid = %d", __func__, uid, wg->rtgId);
287     if (uid == RS_UID) {
288         IntervalReply rs;
289         rs.tid = tid;
290         CTC_QUERY_INTERVAL(QUERY_RENDER_SERVICE, rs);
291         FFRT_LOGI("[WorkGroup] join thread %{public}ld", tid);
292         return;
293     }
294     int addRet = AddThreadToRtgAdapter(tid, wg->rtgId, 0);
295     if (addRet == 0) {
296         FFRT_LOGI("[WorkGroup] join thread %{public}ld success", tid);
297     } else {
298         FFRT_LOGE("[WorkGroup] join fail with %{public}d threads for %{public}d", addRet, tid);
299     }
300 }
301 
302 #endif /* QOS_FRAME_RTG */
303 }
304 
305 #endif
306