• 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 
16 #ifdef QOS_FRAME_RTG
17 #include "workgroup_internal.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <cstring>
21 #include <mutex>
22 #include "rtg_interface.h"
23 #include "concurrent_task_client.h"
24 #include "dfx/log/ffrt_log_api.h"
25 
26 constexpr int HWC_UID = 3039;
27 constexpr int ROOT_UID = 0;
28 constexpr int SYSTEM_UID = 1000;
29 constexpr int RS_RTG_ID = 10;
30 
31 using namespace OHOS::ConcurrentTask;
32 
33 namespace ffrt {
34 static int wgId = -1;
35 static int wgCount = 0;
36 static std::mutex wgLock;
37 
JoinWG(int tid)38 bool JoinWG(int tid)
39 {
40     if (wgId < 0) {
41         if (wgCount > 0) {
42             FFRT_LOGE("[WorkGroup] interval is unavailable");
43         }
44         return false;
45     }
46     int addRet = OHOS::RME::AddThreadToRtg(tid, wgId);
47     if (addRet == 0) {
48         FFRT_LOGI("[WorkGroup] update thread %{public}d success", tid);
49     } else {
50         FFRT_LOGE("[WorkGroup] update thread %{public}d failed, return %{public}d", tid, addRet);
51     }
52     return true;
53 }
54 
WorkgroupStartInterval(struct Workgroup * wg)55 void WorkgroupStartInterval(struct Workgroup* wg)
56 {
57     if (wg == nullptr) {
58         FFRT_LOGE("[WorkGroup] input workgroup is null");
59         return;
60     }
61 
62     if (wg->started) {
63         FFRT_LOGW("[WorkGroup] already start");
64         return;
65     }
66 
67     if (OHOS::RME::BeginFrameFreq(wg->rtgId, 0) == 0) {
68         wg->started = true;
69     } else {
70         FFRT_LOGE("[WorkGroup] start rtg(%{public}d) work interval failed", wg->rtgId);
71     }
72 }
73 
WorkgroupStopInterval(struct Workgroup * wg)74 void WorkgroupStopInterval(struct Workgroup* wg)
75 {
76     if (wg == nullptr) {
77         FFRT_LOGE("[WorkGroup] input workgroup is null");
78         return;
79     }
80 
81     if (!wg->started) {
82         FFRT_LOGW("[WorkGroup] already stop");
83         return;
84     }
85 
86     int ret = OHOS::RME::EndFrameFreq(wg->rtgId);
87     if (ret == 0) {
88         wg->started = false;
89     } else {
90         FFRT_LOGE("[WorkGroup] stop rtg(%{public}d) work interval failed", wg->rtgId);
91     }
92 }
93 
WorkgroupInit(struct Workgroup * wg,uint64_t interval,int rtgId)94 static void WorkgroupInit(struct Workgroup* wg, uint64_t interval, int rtgId)
95 {
96     wg->started = false;
97     wg->interval = interval;
98     wg->rtgId = rtgId;
99     wgId = rtgId;
100 
101     for (int i = 0; i < MAX_WG_THREADS; i++) {
102         wg->tids[i] = -1;
103     }
104 }
105 
WorkgroupCreate(uint64_t interval)106 struct Workgroup* WorkgroupCreate(uint64_t interval)
107 {
108     IntervalReply rs;
109     rs.rtgId = -1;
110     int rtgId = -1;
111     int uid = getuid();
112     int num = 0;
113 
114     if (uid == SYSTEM_UID || uid == HWC_UID) {
115         ConcurrentTaskClient::GetInstance().QueryInterval(QUERY_RENDER_SERVICE, rs);
116         rtgId = rs.rtgId;
117     } else if (uid == ROOT_UID) {
118         rtgId = OHOS::RME::CreateNewRtgGrp(num);
119     } else {
120         ConcurrentTaskClient::GetInstance().QueryInterval(QUERY_UI, rs);
121         rtgId = rs.rtgId;
122     }
123 
124     if (rtgId < 0) {
125         FFRT_LOGE("[WorkGroup] create rtg group %{public}d failed", rtgId);
126         return nullptr;
127     }
128     FFRT_LOGI("[WorkGroup] create rtg group %{public}d success", rtgId);
129 
130     Workgroup* wg = nullptr;
131     wg = new struct Workgroup();
132     if (wg == nullptr) {
133         FFRT_LOGE("[WorkGroup] workgroup malloc failed!");
134         return nullptr;
135     }
136     WorkgroupInit(wg, interval, rtgId);
137     {
138         std::lock_guard<std::mutex> lck(wgLock);
139         wgCount++;
140     }
141     return wg;
142 }
143 
WorkgroupJoin(struct Workgroup * wg,int tid)144 void WorkgroupJoin(struct Workgroup* wg, int tid)
145 {
146     if (wg == nullptr) {
147         FFRT_LOGE("[WorkGroup] input workgroup is null");
148         return;
149     }
150     FFRT_LOGI("[WorkGroup] %{public}s uid = %{public}d rtgid = %{public}d", __func__, (int)getuid(), wg->rtgId);
151     int addRet = OHOS::RME::AddThreadToRtg(tid, wg->rtgId);
152     if (addRet == 0) {
153         FFRT_LOGI("[WorkGroup] join thread %{public}ld success", tid);
154     } else {
155         FFRT_LOGE("[WorkGroup] join fail with %{public}d threads for %{public}d", addRet, tid);
156     }
157 }
158 
WorkgroupClear(struct Workgroup * wg)159 int WorkgroupClear(struct Workgroup* wg)
160 {
161     if (wg == nullptr) {
162         FFRT_LOGE("[WorkGroup] input workgroup is null");
163         return 0;
164     }
165     int ret = -1;
166     int uid = getuid();
167     if (uid != SYSTEM_UID && uid != HWC_UID) {
168         ret = OHOS::RME::DestroyRtgGrp(wg->rtgId);
169         if (ret != 0) {
170             FFRT_LOGE("[WorkGroup] destroy rtg group failed");
171         } else {
172             FFRT_LOGI("[WorkGroup] destroy rtg group success");
173             {
174                 std::lock_guard<std::mutex> lck(wgLock);
175                 wgCount--;
176             }
177         }
178     }
179     delete wg;
180     wg = nullptr;
181     return ret;
182 }
183 }
184 
185 #endif /* QOS_FRAME_RTG */
186