1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 "gpu_data_plugin.h"
17 #include <ctime>
18 #include "gpu_plugin_result.pbencoder.h"
19
20 namespace {
21 using namespace OHOS::Developtools::Profiler;
22 const std::string GPU_PATH = "/sys/class/devfreq/gpufreq/gpu_scene_aware/utilisation";
23 } // namespace
24
Start(const uint8_t * configData,uint32_t configSize)25 int GpuDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
26 {
27 CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, RET_FAIL,
28 "%s:parseFromArray failed!", __func__);
29
30 if (protoConfig_.pid() > 0) {
31 pid_ = protoConfig_.pid();
32 }
33
34 file_.open(GPU_PATH);
35 if (!file_.is_open()) {
36 PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s)", __func__, GPU_PATH.c_str());
37 return RET_FAIL;
38 }
39 PROFILER_LOG_INFO(LOG_CORE, "%s:start success!", __func__);
40 return RET_SUCC;
41 }
42
ReportOptimize(RandomWriteCtx * randomWrite)43 int GpuDataPlugin::ReportOptimize(RandomWriteCtx* randomWrite)
44 {
45 ProtoEncoder::GpuData dataProto(randomWrite);
46 WriteGpuDataInfo(dataProto);
47 int msgSize = dataProto.Finish();
48 return msgSize;
49 }
50
Report(uint8_t * data,uint32_t dataSize)51 int GpuDataPlugin::Report(uint8_t* data, uint32_t dataSize)
52 {
53 GpuData dataProto;
54 uint32_t length;
55 WriteGpuDataInfo(dataProto);
56
57 length = dataProto.ByteSizeLong();
58 if (length > dataSize) {
59 return -length;
60 }
61 if (dataProto.SerializeToArray(data, length) > 0) {
62 return length;
63 }
64 return 0;
65 }
66
Stop()67 int GpuDataPlugin::Stop()
68 {
69 file_.close();
70 PROFILER_LOG_INFO(LOG_CORE, "%s:stop success!", __func__);
71 return 0;
72 }
73
ReadFile()74 int GpuDataPlugin::ReadFile()
75 {
76 file_.clear();
77 file_.seekg(0);
78 std::string line;
79 std::getline(file_, line);
80 for (char charac : line) {
81 if (!isdigit(charac)) {
82 PROFILER_LOG_ERROR(LOG_CORE, "invalid file content for (%s)", GPU_PATH.c_str());
83 return RET_FAIL;
84 }
85 }
86 return stoi(line);
87 }
88
WriteGpuDataInfo(T & gpuData)89 template <typename T> void GpuDataPlugin::WriteGpuDataInfo(T& gpuData)
90 {
91 int ret = ReadFile();
92 if (ret == RET_FAIL) {
93 return;
94 }
95
96 constexpr uint64_t nanoSeconds = 1000000000;
97 struct timespec ts;
98 clock_gettime(CLOCK_BOOTTIME, &ts);
99 uint64_t boottime = (static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
100 static_cast<uint64_t>(ts.tv_nsec)) / 1000000;
101 gpuData.set_boottime(boottime);
102 gpuData.set_gpu_utilisation(static_cast<uint64_t>(ret));
103 }
104