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 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 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 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 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 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 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 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 __anone3ead2840102() 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 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 __anone3ead2840202() 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