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