1484543d1Sopenharmony_ci/*
2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License.
5484543d1Sopenharmony_ci * You may obtain a copy of the License at
6484543d1Sopenharmony_ci *
7484543d1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8484543d1Sopenharmony_ci *
9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and
13484543d1Sopenharmony_ci * limitations under the License.
14484543d1Sopenharmony_ci */
15484543d1Sopenharmony_ci
16484543d1Sopenharmony_ci#include <vector>
17484543d1Sopenharmony_ci#include <mutex>
18484543d1Sopenharmony_ci#include <thread>
19484543d1Sopenharmony_ci#include <condition_variable>
20484543d1Sopenharmony_ci#include <atomic>
21484543d1Sopenharmony_ci
22484543d1Sopenharmony_ci#include <gtest/gtest.h>
23484543d1Sopenharmony_ci
24484543d1Sopenharmony_ci#include "eu/rtg_ioctl.h"
25484543d1Sopenharmony_ci#include "dfx/log/ffrt_log_api.h"
26484543d1Sopenharmony_ci#include "../common.h"
27484543d1Sopenharmony_ci
28484543d1Sopenharmony_ciusing namespace testing;
29484543d1Sopenharmony_ci#ifdef HWTEST_TESTING_EXT_ENABLE
30484543d1Sopenharmony_ciusing namespace testing::ext;
31484543d1Sopenharmony_ci#endif
32484543d1Sopenharmony_ciusing namespace ffrt;
33484543d1Sopenharmony_ci
34484543d1Sopenharmony_ciclass RTGTest : public testing::Test {
35484543d1Sopenharmony_ciprotected:
36484543d1Sopenharmony_ci    static void SetUpTestCase()
37484543d1Sopenharmony_ci    {
38484543d1Sopenharmony_ci    }
39484543d1Sopenharmony_ci
40484543d1Sopenharmony_ci    static void TearDownTestCase()
41484543d1Sopenharmony_ci    {
42484543d1Sopenharmony_ci    }
43484543d1Sopenharmony_ci
44484543d1Sopenharmony_ci    virtual void SetUp()
45484543d1Sopenharmony_ci    {
46484543d1Sopenharmony_ci    }
47484543d1Sopenharmony_ci
48484543d1Sopenharmony_ci    virtual void TearDown()
49484543d1Sopenharmony_ci    {
50484543d1Sopenharmony_ci    }
51484543d1Sopenharmony_ci};
52484543d1Sopenharmony_ci
53484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_init_test, TestSize.Level1)
54484543d1Sopenharmony_ci{
55484543d1Sopenharmony_ci    bool enabled = RTGCtrl::Instance().Enabled();
56484543d1Sopenharmony_ci    FFRT_LOGE("RTGCtrl Init %s", enabled ? "Success" : "Failed");
57484543d1Sopenharmony_ci}
58484543d1Sopenharmony_ci
59484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_get_group_test, TestSize.Level1)
60484543d1Sopenharmony_ci{
61484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
62484543d1Sopenharmony_ci    if (tgid < 0) {
63484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
64484543d1Sopenharmony_ci    }
65484543d1Sopenharmony_ci
66484543d1Sopenharmony_ci    bool ret = RTGCtrl::Instance().PutThreadGroup(tgid);
67484543d1Sopenharmony_ci    if (!ret) {
68484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
69484543d1Sopenharmony_ci    }
70484543d1Sopenharmony_ci}
71484543d1Sopenharmony_ci
72484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_set_window_size_test, TestSize.Level1)
73484543d1Sopenharmony_ci{
74484543d1Sopenharmony_ci    constexpr int WINDOW_SIZE = 10000;
75484543d1Sopenharmony_ci
76484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
77484543d1Sopenharmony_ci    if (tgid < 0) {
78484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
79484543d1Sopenharmony_ci    }
80484543d1Sopenharmony_ci
81484543d1Sopenharmony_ci    bool ret = RTGCtrl::Instance().SetGroupWindowSize(tgid, WINDOW_SIZE);
82484543d1Sopenharmony_ci    if (!ret) {
83484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Set Window Size %d", WINDOW_SIZE);
84484543d1Sopenharmony_ci    }
85484543d1Sopenharmony_ci
86484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().PutThreadGroup(tgid);
87484543d1Sopenharmony_ci    if (!ret) {
88484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
89484543d1Sopenharmony_ci    }
90484543d1Sopenharmony_ci}
91484543d1Sopenharmony_ci
92484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_set_invalid_interval_test, TestSize.Level1)
93484543d1Sopenharmony_ci{
94484543d1Sopenharmony_ci    constexpr int INVALID_INTERVAL = 10;
95484543d1Sopenharmony_ci
96484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
97484543d1Sopenharmony_ci    if (tgid < 0) {
98484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
99484543d1Sopenharmony_ci    }
100484543d1Sopenharmony_ci
101484543d1Sopenharmony_ci    bool ret = RTGCtrl::Instance().SetInvalidInterval(tgid, INVALID_INTERVAL);
102484543d1Sopenharmony_ci    if (!ret) {
103484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Set Invalid Interval %d", INVALID_INTERVAL);
104484543d1Sopenharmony_ci    }
105484543d1Sopenharmony_ci
106484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().PutThreadGroup(tgid);
107484543d1Sopenharmony_ci    if (!ret) {
108484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
109484543d1Sopenharmony_ci    }
110484543d1Sopenharmony_ci}
111484543d1Sopenharmony_ci
112484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_set_preferred_cluster_test, TestSize.Level1)
113484543d1Sopenharmony_ci{
114484543d1Sopenharmony_ci    constexpr int CLUSTER_ID = 0;
115484543d1Sopenharmony_ci
116484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
117484543d1Sopenharmony_ci    if (tgid < 0) {
118484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
119484543d1Sopenharmony_ci    }
120484543d1Sopenharmony_ci
121484543d1Sopenharmony_ci    bool ret = RTGCtrl::Instance().SetPreferredCluster(tgid, CLUSTER_ID);
122484543d1Sopenharmony_ci    if (!ret) {
123484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Set Preferred Cluster %d", CLUSTER_ID);
124484543d1Sopenharmony_ci    }
125484543d1Sopenharmony_ci
126484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().PutThreadGroup(tgid);
127484543d1Sopenharmony_ci    if (!ret) {
128484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
129484543d1Sopenharmony_ci    }
130484543d1Sopenharmony_ci}
131484543d1Sopenharmony_ci
132484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_begin_end_test, TestSize.Level1)
133484543d1Sopenharmony_ci{
134484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
135484543d1Sopenharmony_ci    if (tgid < 0) {
136484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
137484543d1Sopenharmony_ci    }
138484543d1Sopenharmony_ci
139484543d1Sopenharmony_ci    bool ret = RTGCtrl::Instance().Begin(tgid);
140484543d1Sopenharmony_ci    if (!ret) {
141484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Begin");
142484543d1Sopenharmony_ci    }
143484543d1Sopenharmony_ci
144484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().End(tgid);
145484543d1Sopenharmony_ci    if (!ret) {
146484543d1Sopenharmony_ci        FFRT_LOGE("Failed to End");
147484543d1Sopenharmony_ci    }
148484543d1Sopenharmony_ci
149484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().PutThreadGroup(tgid);
150484543d1Sopenharmony_ci    if (!ret) {
151484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
152484543d1Sopenharmony_ci    }
153484543d1Sopenharmony_ci}
154484543d1Sopenharmony_ci
155484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_add_tread_test, TestSize.Level1)
156484543d1Sopenharmony_ci{
157484543d1Sopenharmony_ci    constexpr int THREAD_NUM = 8;
158484543d1Sopenharmony_ci    bool ret;
159484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
160484543d1Sopenharmony_ci    if (tgid < 0) {
161484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
162484543d1Sopenharmony_ci    }
163484543d1Sopenharmony_ci
164484543d1Sopenharmony_ci    std::vector<std::thread> threads;
165484543d1Sopenharmony_ci
166484543d1Sopenharmony_ci    std::mutex tidMutex;
167484543d1Sopenharmony_ci    std::vector<pid_t> tids;
168484543d1Sopenharmony_ci
169484543d1Sopenharmony_ci    std::mutex condMutex;
170484543d1Sopenharmony_ci    std::condition_variable cond;
171484543d1Sopenharmony_ci
172484543d1Sopenharmony_ci    auto f = [&]() {
173484543d1Sopenharmony_ci        pid_t tid = RTGCtrl::GetTID();
174484543d1Sopenharmony_ci
175484543d1Sopenharmony_ci        {
176484543d1Sopenharmony_ci            std::unique_lock lock(tidMutex);
177484543d1Sopenharmony_ci            tids.emplace_back(tid);
178484543d1Sopenharmony_ci        }
179484543d1Sopenharmony_ci
180484543d1Sopenharmony_ci        std::unique_lock lock(condMutex);
181484543d1Sopenharmony_ci        cond.wait(lock);
182484543d1Sopenharmony_ci    };
183484543d1Sopenharmony_ci
184484543d1Sopenharmony_ci    for (int i = 0; i < THREAD_NUM; ++i) {
185484543d1Sopenharmony_ci        threads.emplace_back(std::thread(f));
186484543d1Sopenharmony_ci    }
187484543d1Sopenharmony_ci
188484543d1Sopenharmony_ci    while (true) {
189484543d1Sopenharmony_ci        std::unique_lock lock(tidMutex);
190484543d1Sopenharmony_ci        if (tids.size() >= THREAD_NUM) {
191484543d1Sopenharmony_ci            break;
192484543d1Sopenharmony_ci        }
193484543d1Sopenharmony_ci    }
194484543d1Sopenharmony_ci
195484543d1Sopenharmony_ci    for (auto tid : tids) {
196484543d1Sopenharmony_ci        ret = RTGCtrl::Instance().JoinThread(tgid, tid);
197484543d1Sopenharmony_ci        if (!ret) {
198484543d1Sopenharmony_ci            FFRT_LOGE("Failed To Join Thread %d", tid);
199484543d1Sopenharmony_ci        }
200484543d1Sopenharmony_ci    }
201484543d1Sopenharmony_ci
202484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().UpdatePerfFreq(tgid, 960000);
203484543d1Sopenharmony_ci    for (auto tid : tids) {
204484543d1Sopenharmony_ci        auto [t_load, t_runtime] = RTGCtrl::Instance().UpdateAndGetLoad(tgid, tid);
205484543d1Sopenharmony_ci        FFRT_LOGE("Get Load %lu runtime %lu", t_load, t_runtime);
206484543d1Sopenharmony_ci        ret = RTGCtrl::Instance().RemoveThread(tgid, tid);
207484543d1Sopenharmony_ci        if (!ret) {
208484543d1Sopenharmony_ci            FFRT_LOGE("Failed To Leave Thread %d", tid);
209484543d1Sopenharmony_ci        }
210484543d1Sopenharmony_ci    }
211484543d1Sopenharmony_ci
212484543d1Sopenharmony_ci    cond.notify_all();
213484543d1Sopenharmony_ci    for (auto& thread : threads) {
214484543d1Sopenharmony_ci        thread.join();
215484543d1Sopenharmony_ci    }
216484543d1Sopenharmony_ci
217484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().PutThreadGroup(tgid);
218484543d1Sopenharmony_ci    if (!ret) {
219484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
220484543d1Sopenharmony_ci    }
221484543d1Sopenharmony_ci}
222484543d1Sopenharmony_ci
223484543d1Sopenharmony_ciHWTEST_F(RTGTest, rtg_update_util_test, TestSize.Level1)
224484543d1Sopenharmony_ci{
225484543d1Sopenharmony_ci    constexpr int THREAD_NUM = 8;
226484543d1Sopenharmony_ci
227484543d1Sopenharmony_ci    int tgid = RTGCtrl::Instance().GetThreadGroup();
228484543d1Sopenharmony_ci    if (tgid < 0) {
229484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Get RTG id %d", tgid);
230484543d1Sopenharmony_ci    }
231484543d1Sopenharmony_ci
232484543d1Sopenharmony_ci    std::vector<std::thread> threads;
233484543d1Sopenharmony_ci
234484543d1Sopenharmony_ci    std::mutex tidMutex;
235484543d1Sopenharmony_ci    std::vector<pid_t> tids;
236484543d1Sopenharmony_ci
237484543d1Sopenharmony_ci    std::mutex condMutex;
238484543d1Sopenharmony_ci    std::condition_variable cond;
239484543d1Sopenharmony_ci
240484543d1Sopenharmony_ci    auto f = [&]() {
241484543d1Sopenharmony_ci        pid_t tid = RTGCtrl::GetTID();
242484543d1Sopenharmony_ci
243484543d1Sopenharmony_ci        {
244484543d1Sopenharmony_ci            std::unique_lock lock(tidMutex);
245484543d1Sopenharmony_ci            tids.emplace_back(tid);
246484543d1Sopenharmony_ci        }
247484543d1Sopenharmony_ci
248484543d1Sopenharmony_ci        std::unique_lock lock(condMutex);
249484543d1Sopenharmony_ci        cond.wait(lock);
250484543d1Sopenharmony_ci    };
251484543d1Sopenharmony_ci
252484543d1Sopenharmony_ci    for (int i = 0; i < THREAD_NUM; ++i) {
253484543d1Sopenharmony_ci        threads.emplace_back(std::thread(f));
254484543d1Sopenharmony_ci    }
255484543d1Sopenharmony_ci
256484543d1Sopenharmony_ci    while (true) {
257484543d1Sopenharmony_ci        std::unique_lock lock(tidMutex);
258484543d1Sopenharmony_ci        if (tids.size() >= THREAD_NUM) {
259484543d1Sopenharmony_ci            break;
260484543d1Sopenharmony_ci        }
261484543d1Sopenharmony_ci    }
262484543d1Sopenharmony_ci
263484543d1Sopenharmony_ci    for (auto tid : tids) {
264484543d1Sopenharmony_ci        bool ret = RTGCtrl::Instance().JoinThread(tgid, tid);
265484543d1Sopenharmony_ci        if (!ret) {
266484543d1Sopenharmony_ci            FFRT_LOGE("Failed To Join Thread %d", tid);
267484543d1Sopenharmony_ci        }
268484543d1Sopenharmony_ci    }
269484543d1Sopenharmony_ci
270484543d1Sopenharmony_ci    bool ret = RTGCtrl::Instance().Begin(tgid);
271484543d1Sopenharmony_ci    if (!ret) {
272484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Begin");
273484543d1Sopenharmony_ci    }
274484543d1Sopenharmony_ci
275484543d1Sopenharmony_ci    for (int util = 8; util <= 1024; util <<= 1) {
276484543d1Sopenharmony_ci        auto [load, runtime] = RTGCtrl::Instance().UpdateAndGetLoad(tgid);
277484543d1Sopenharmony_ci        FFRT_LOGE("Get Load %lu runtime %lu", load, runtime);
278484543d1Sopenharmony_ci
279484543d1Sopenharmony_ci        ret = RTGCtrl::Instance().UpdatePerfUtil(tgid, util);
280484543d1Sopenharmony_ci        if (!ret) {
281484543d1Sopenharmony_ci            FFRT_LOGE("Failed To Update Util %d", util);
282484543d1Sopenharmony_ci        }
283484543d1Sopenharmony_ci    }
284484543d1Sopenharmony_ci
285484543d1Sopenharmony_ci    for (auto tid : tids) {
286484543d1Sopenharmony_ci        ret = RTGCtrl::Instance().RemoveThread(tgid, tid);
287484543d1Sopenharmony_ci        if (!ret) {
288484543d1Sopenharmony_ci            FFRT_LOGE("Failed To Leave Thread %d", tid);
289484543d1Sopenharmony_ci        }
290484543d1Sopenharmony_ci    }
291484543d1Sopenharmony_ci
292484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().End(tgid);
293484543d1Sopenharmony_ci    if (!ret) {
294484543d1Sopenharmony_ci        FFRT_LOGE("Failed to End");
295484543d1Sopenharmony_ci    }
296484543d1Sopenharmony_ci
297484543d1Sopenharmony_ci    cond.notify_all();
298484543d1Sopenharmony_ci    for (auto& thread : threads) {
299484543d1Sopenharmony_ci        thread.join();
300484543d1Sopenharmony_ci    }
301484543d1Sopenharmony_ci
302484543d1Sopenharmony_ci    ret = RTGCtrl::Instance().PutThreadGroup(tgid);
303484543d1Sopenharmony_ci    if (!ret) {
304484543d1Sopenharmony_ci        FFRT_LOGE("Failed to Put RTG id %d", tgid);
305484543d1Sopenharmony_ci    }
306484543d1Sopenharmony_ci}
307