106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include "gpu_data_plugin.h"
1706f6ba60Sopenharmony_ci#include <ctime>
1806f6ba60Sopenharmony_ci#include "gpu_plugin_result.pbencoder.h"
1906f6ba60Sopenharmony_ci
2006f6ba60Sopenharmony_cinamespace {
2106f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
2206f6ba60Sopenharmony_ciconst std::string GPU_PATH = "/sys/class/devfreq/gpufreq/gpu_scene_aware/utilisation";
2306f6ba60Sopenharmony_ci} // namespace
2406f6ba60Sopenharmony_ci
2506f6ba60Sopenharmony_ciint GpuDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
2606f6ba60Sopenharmony_ci{
2706f6ba60Sopenharmony_ci    CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, RET_FAIL,
2806f6ba60Sopenharmony_ci               "%s:parseFromArray failed!", __func__);
2906f6ba60Sopenharmony_ci
3006f6ba60Sopenharmony_ci    if (protoConfig_.pid() > 0) {
3106f6ba60Sopenharmony_ci        pid_ = protoConfig_.pid();
3206f6ba60Sopenharmony_ci    }
3306f6ba60Sopenharmony_ci
3406f6ba60Sopenharmony_ci    file_.open(GPU_PATH);
3506f6ba60Sopenharmony_ci    if (!file_.is_open()) {
3606f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s)", __func__, GPU_PATH.c_str());
3706f6ba60Sopenharmony_ci        return RET_FAIL;
3806f6ba60Sopenharmony_ci    }
3906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:start success!", __func__);
4006f6ba60Sopenharmony_ci    return RET_SUCC;
4106f6ba60Sopenharmony_ci}
4206f6ba60Sopenharmony_ci
4306f6ba60Sopenharmony_ciint GpuDataPlugin::ReportOptimize(RandomWriteCtx* randomWrite)
4406f6ba60Sopenharmony_ci{
4506f6ba60Sopenharmony_ci    ProtoEncoder::GpuData dataProto(randomWrite);
4606f6ba60Sopenharmony_ci    WriteGpuDataInfo(dataProto);
4706f6ba60Sopenharmony_ci    int msgSize = dataProto.Finish();
4806f6ba60Sopenharmony_ci    return msgSize;
4906f6ba60Sopenharmony_ci}
5006f6ba60Sopenharmony_ci
5106f6ba60Sopenharmony_ciint GpuDataPlugin::Report(uint8_t* data, uint32_t dataSize)
5206f6ba60Sopenharmony_ci{
5306f6ba60Sopenharmony_ci    GpuData dataProto;
5406f6ba60Sopenharmony_ci    uint32_t length;
5506f6ba60Sopenharmony_ci    WriteGpuDataInfo(dataProto);
5606f6ba60Sopenharmony_ci
5706f6ba60Sopenharmony_ci    length = dataProto.ByteSizeLong();
5806f6ba60Sopenharmony_ci    if (length > dataSize) {
5906f6ba60Sopenharmony_ci        return -length;
6006f6ba60Sopenharmony_ci    }
6106f6ba60Sopenharmony_ci    if (dataProto.SerializeToArray(data, length) > 0) {
6206f6ba60Sopenharmony_ci        return length;
6306f6ba60Sopenharmony_ci    }
6406f6ba60Sopenharmony_ci    return 0;
6506f6ba60Sopenharmony_ci}
6606f6ba60Sopenharmony_ci
6706f6ba60Sopenharmony_ciint GpuDataPlugin::Stop()
6806f6ba60Sopenharmony_ci{
6906f6ba60Sopenharmony_ci    file_.close();
7006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:stop success!", __func__);
7106f6ba60Sopenharmony_ci    return 0;
7206f6ba60Sopenharmony_ci}
7306f6ba60Sopenharmony_ci
7406f6ba60Sopenharmony_ciint GpuDataPlugin::ReadFile()
7506f6ba60Sopenharmony_ci{
7606f6ba60Sopenharmony_ci    file_.clear();
7706f6ba60Sopenharmony_ci    file_.seekg(0);
7806f6ba60Sopenharmony_ci    std::string line;
7906f6ba60Sopenharmony_ci    std::getline(file_, line);
8006f6ba60Sopenharmony_ci    if (line == "") {
8106f6ba60Sopenharmony_ci        return RET_FAIL;
8206f6ba60Sopenharmony_ci    }
8306f6ba60Sopenharmony_ci    for (char charac : line) {
8406f6ba60Sopenharmony_ci        if (!isdigit(charac)) {
8506f6ba60Sopenharmony_ci            PROFILER_LOG_ERROR(LOG_CORE, "invalid file content for (%s)", GPU_PATH.c_str());
8606f6ba60Sopenharmony_ci            return RET_FAIL;
8706f6ba60Sopenharmony_ci        }
8806f6ba60Sopenharmony_ci    }
8906f6ba60Sopenharmony_ci    return stoi(line);
9006f6ba60Sopenharmony_ci}
9106f6ba60Sopenharmony_ci
9206f6ba60Sopenharmony_citemplate <typename T> void GpuDataPlugin::WriteGpuDataInfo(T& gpuData)
9306f6ba60Sopenharmony_ci{
9406f6ba60Sopenharmony_ci    int ret = ReadFile();
9506f6ba60Sopenharmony_ci    if (ret == RET_FAIL) {
9606f6ba60Sopenharmony_ci        return;
9706f6ba60Sopenharmony_ci    }
9806f6ba60Sopenharmony_ci
9906f6ba60Sopenharmony_ci    constexpr uint64_t nanoSeconds = 1000000000;
10006f6ba60Sopenharmony_ci    struct timespec ts;
10106f6ba60Sopenharmony_ci    clock_gettime(CLOCK_BOOTTIME, &ts);
10206f6ba60Sopenharmony_ci    uint64_t boottime = (static_cast<uint64_t>(ts.tv_sec) * nanoSeconds +
10306f6ba60Sopenharmony_ci        static_cast<uint64_t>(ts.tv_nsec)) / 1000000;
10406f6ba60Sopenharmony_ci    gpuData.set_boottime(boottime);
10506f6ba60Sopenharmony_ci    gpuData.set_gpu_utilisation(static_cast<uint64_t>(ret));
10606f6ba60Sopenharmony_ci}
107