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 #include <vector>
17 #include <mutex>
18 #include <thread>
19 #include <condition_variable>
20 #include <atomic>
21
22 #include <gtest/gtest.h>
23
24 #include "eu/rtg_ioctl.h"
25 #include "dfx/log/ffrt_log_api.h"
26 #include "../common.h"
27
28 using namespace testing;
29 #ifdef HWTEST_TESTING_EXT_ENABLE
30 using namespace testing::ext;
31 #endif
32 using namespace ffrt;
33
34 class RTGTest : public testing::Test {
35 protected:
SetUpTestCase()36 static void SetUpTestCase()
37 {
38 }
39
TearDownTestCase()40 static void TearDownTestCase()
41 {
42 }
43
SetUp()44 virtual void SetUp()
45 {
46 }
47
TearDown()48 virtual void TearDown()
49 {
50 }
51 };
52
HWTEST_F(RTGTest, rtg_init_test, TestSize.Level1)53 HWTEST_F(RTGTest, rtg_init_test, TestSize.Level1)
54 {
55 bool enabled = RTGCtrl::Instance().Enabled();
56 FFRT_LOGE("RTGCtrl Init %s", enabled ? "Success" : "Failed");
57 }
58
HWTEST_F(RTGTest, rtg_get_group_test, TestSize.Level1)59 HWTEST_F(RTGTest, rtg_get_group_test, TestSize.Level1)
60 {
61 int tgid = RTGCtrl::Instance().GetThreadGroup();
62 if (tgid < 0) {
63 FFRT_LOGE("Failed to Get RTG id %d", tgid);
64 }
65
66 bool ret = RTGCtrl::Instance().PutThreadGroup(tgid);
67 if (!ret) {
68 FFRT_LOGE("Failed to Put RTG id %d", tgid);
69 }
70 }
71
HWTEST_F(RTGTest, rtg_set_window_size_test, TestSize.Level1)72 HWTEST_F(RTGTest, rtg_set_window_size_test, TestSize.Level1)
73 {
74 constexpr int WINDOW_SIZE = 10000;
75
76 int tgid = RTGCtrl::Instance().GetThreadGroup();
77 if (tgid < 0) {
78 FFRT_LOGE("Failed to Get RTG id %d", tgid);
79 }
80
81 bool ret = RTGCtrl::Instance().SetGroupWindowSize(tgid, WINDOW_SIZE);
82 if (!ret) {
83 FFRT_LOGE("Failed to Set Window Size %d", WINDOW_SIZE);
84 }
85
86 ret = RTGCtrl::Instance().PutThreadGroup(tgid);
87 if (!ret) {
88 FFRT_LOGE("Failed to Put RTG id %d", tgid);
89 }
90 }
91
HWTEST_F(RTGTest, rtg_set_invalid_interval_test, TestSize.Level1)92 HWTEST_F(RTGTest, rtg_set_invalid_interval_test, TestSize.Level1)
93 {
94 constexpr int INVALID_INTERVAL = 10;
95
96 int tgid = RTGCtrl::Instance().GetThreadGroup();
97 if (tgid < 0) {
98 FFRT_LOGE("Failed to Get RTG id %d", tgid);
99 }
100
101 bool ret = RTGCtrl::Instance().SetInvalidInterval(tgid, INVALID_INTERVAL);
102 if (!ret) {
103 FFRT_LOGE("Failed to Set Invalid Interval %d", INVALID_INTERVAL);
104 }
105
106 ret = RTGCtrl::Instance().PutThreadGroup(tgid);
107 if (!ret) {
108 FFRT_LOGE("Failed to Put RTG id %d", tgid);
109 }
110 }
111
HWTEST_F(RTGTest, rtg_set_preferred_cluster_test, TestSize.Level1)112 HWTEST_F(RTGTest, rtg_set_preferred_cluster_test, TestSize.Level1)
113 {
114 constexpr int CLUSTER_ID = 0;
115
116 int tgid = RTGCtrl::Instance().GetThreadGroup();
117 if (tgid < 0) {
118 FFRT_LOGE("Failed to Get RTG id %d", tgid);
119 }
120
121 bool ret = RTGCtrl::Instance().SetPreferredCluster(tgid, CLUSTER_ID);
122 if (!ret) {
123 FFRT_LOGE("Failed to Set Preferred Cluster %d", CLUSTER_ID);
124 }
125
126 ret = RTGCtrl::Instance().PutThreadGroup(tgid);
127 if (!ret) {
128 FFRT_LOGE("Failed to Put RTG id %d", tgid);
129 }
130 }
131
HWTEST_F(RTGTest, rtg_begin_end_test, TestSize.Level1)132 HWTEST_F(RTGTest, rtg_begin_end_test, TestSize.Level1)
133 {
134 int tgid = RTGCtrl::Instance().GetThreadGroup();
135 if (tgid < 0) {
136 FFRT_LOGE("Failed to Get RTG id %d", tgid);
137 }
138
139 bool ret = RTGCtrl::Instance().Begin(tgid);
140 if (!ret) {
141 FFRT_LOGE("Failed to Begin");
142 }
143
144 ret = RTGCtrl::Instance().End(tgid);
145 if (!ret) {
146 FFRT_LOGE("Failed to End");
147 }
148
149 ret = RTGCtrl::Instance().PutThreadGroup(tgid);
150 if (!ret) {
151 FFRT_LOGE("Failed to Put RTG id %d", tgid);
152 }
153 }
154
HWTEST_F(RTGTest, rtg_add_tread_test, TestSize.Level1)155 HWTEST_F(RTGTest, rtg_add_tread_test, TestSize.Level1)
156 {
157 constexpr int THREAD_NUM = 8;
158 bool ret;
159 int tgid = RTGCtrl::Instance().GetThreadGroup();
160 if (tgid < 0) {
161 FFRT_LOGE("Failed to Get RTG id %d", tgid);
162 }
163
164 std::vector<std::thread> threads;
165
166 std::mutex tidMutex;
167 std::vector<pid_t> tids;
168
169 std::mutex condMutex;
170 std::condition_variable cond;
171
172 auto f = [&]() {
173 pid_t tid = RTGCtrl::GetTID();
174
175 {
176 std::unique_lock lock(tidMutex);
177 tids.emplace_back(tid);
178 }
179
180 std::unique_lock lock(condMutex);
181 cond.wait(lock);
182 };
183
184 for (int i = 0; i < THREAD_NUM; ++i) {
185 threads.emplace_back(std::thread(f));
186 }
187
188 while (true) {
189 std::unique_lock lock(tidMutex);
190 if (tids.size() >= THREAD_NUM) {
191 break;
192 }
193 }
194
195 for (auto tid : tids) {
196 ret = RTGCtrl::Instance().JoinThread(tgid, tid);
197 if (!ret) {
198 FFRT_LOGE("Failed To Join Thread %d", tid);
199 }
200 }
201
202 ret = RTGCtrl::Instance().UpdatePerfFreq(tgid, 960000);
203 for (auto tid : tids) {
204 auto [t_load, t_runtime] = RTGCtrl::Instance().UpdateAndGetLoad(tgid, tid);
205 FFRT_LOGE("Get Load %lu runtime %lu", t_load, t_runtime);
206 ret = RTGCtrl::Instance().RemoveThread(tgid, tid);
207 if (!ret) {
208 FFRT_LOGE("Failed To Leave Thread %d", tid);
209 }
210 }
211
212 cond.notify_all();
213 for (auto& thread : threads) {
214 thread.join();
215 }
216
217 ret = RTGCtrl::Instance().PutThreadGroup(tgid);
218 if (!ret) {
219 FFRT_LOGE("Failed to Put RTG id %d", tgid);
220 }
221 }
222
HWTEST_F(RTGTest, rtg_update_util_test, TestSize.Level1)223 HWTEST_F(RTGTest, rtg_update_util_test, TestSize.Level1)
224 {
225 constexpr int THREAD_NUM = 8;
226
227 int tgid = RTGCtrl::Instance().GetThreadGroup();
228 if (tgid < 0) {
229 FFRT_LOGE("Failed to Get RTG id %d", tgid);
230 }
231
232 std::vector<std::thread> threads;
233
234 std::mutex tidMutex;
235 std::vector<pid_t> tids;
236
237 std::mutex condMutex;
238 std::condition_variable cond;
239
240 auto f = [&]() {
241 pid_t tid = RTGCtrl::GetTID();
242
243 {
244 std::unique_lock lock(tidMutex);
245 tids.emplace_back(tid);
246 }
247
248 std::unique_lock lock(condMutex);
249 cond.wait(lock);
250 };
251
252 for (int i = 0; i < THREAD_NUM; ++i) {
253 threads.emplace_back(std::thread(f));
254 }
255
256 while (true) {
257 std::unique_lock lock(tidMutex);
258 if (tids.size() >= THREAD_NUM) {
259 break;
260 }
261 }
262
263 for (auto tid : tids) {
264 bool ret = RTGCtrl::Instance().JoinThread(tgid, tid);
265 if (!ret) {
266 FFRT_LOGE("Failed To Join Thread %d", tid);
267 }
268 }
269
270 bool ret = RTGCtrl::Instance().Begin(tgid);
271 if (!ret) {
272 FFRT_LOGE("Failed to Begin");
273 }
274
275 for (int util = 8; util <= 1024; util <<= 1) {
276 auto [load, runtime] = RTGCtrl::Instance().UpdateAndGetLoad(tgid);
277 FFRT_LOGE("Get Load %lu runtime %lu", load, runtime);
278
279 ret = RTGCtrl::Instance().UpdatePerfUtil(tgid, util);
280 if (!ret) {
281 FFRT_LOGE("Failed To Update Util %d", util);
282 }
283 }
284
285 for (auto tid : tids) {
286 ret = RTGCtrl::Instance().RemoveThread(tgid, tid);
287 if (!ret) {
288 FFRT_LOGE("Failed To Leave Thread %d", tid);
289 }
290 }
291
292 ret = RTGCtrl::Instance().End(tgid);
293 if (!ret) {
294 FFRT_LOGE("Failed to End");
295 }
296
297 cond.notify_all();
298 for (auto& thread : threads) {
299 thread.join();
300 }
301
302 ret = RTGCtrl::Instance().PutThreadGroup(tgid);
303 if (!ret) {
304 FFRT_LOGE("Failed to Put RTG id %d", tgid);
305 }
306 }
307