106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. 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 "cpu_data_plugin.h"
1706f6ba60Sopenharmony_ci
1806f6ba60Sopenharmony_ci#include <ctime>
1906f6ba60Sopenharmony_ci#include <vector>
2006f6ba60Sopenharmony_ci#include <sstream>
2106f6ba60Sopenharmony_ci#include "cpu_plugin_result.pbencoder.h"
2206f6ba60Sopenharmony_ci#include "buffer_splitter.h"
2306f6ba60Sopenharmony_ci
2406f6ba60Sopenharmony_cinamespace {
2506f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
2606f6ba60Sopenharmony_ciconstexpr size_t READ_BUFFER_SIZE = 1024 * 16;
2706f6ba60Sopenharmony_ciconstexpr int SYSTEM_STAT_COUNT = 9;
2806f6ba60Sopenharmony_ciconstexpr int STAT_COUNT = 17;
2906f6ba60Sopenharmony_ciconstexpr int STAT_START = 13;
3006f6ba60Sopenharmony_ciconstexpr int THREAD_NAME_POS = 1;
3106f6ba60Sopenharmony_ciconstexpr int THREAD_STATE_POS = 2;
3206f6ba60Sopenharmony_ciconstexpr int CPU_USER_HZ_L = 100;
3306f6ba60Sopenharmony_ciconstexpr int CPU_USER_HZ_H = 1000;
3406f6ba60Sopenharmony_ciconstexpr int CPU_HZ_H = 10;
3506f6ba60Sopenharmony_ciconst int PERCENT = 100;
3606f6ba60Sopenharmony_ci
3706f6ba60Sopenharmony_ciconst std::string FREQUENCY_PATH = "/sys/devices/system/cpu";
3806f6ba60Sopenharmony_ciconst std::string FREQUENCY_MIN_PATH = "/cpufreq/cpuinfo_min_freq";
3906f6ba60Sopenharmony_ciconst std::string FREQUENCY_MAX_PATH = "/cpufreq/cpuinfo_max_freq";
4006f6ba60Sopenharmony_ciconst std::string FREQUENCY_CUR_PATH = "/cpufreq/cpuinfo_cur_freq";
4106f6ba60Sopenharmony_ci} // namespace
4206f6ba60Sopenharmony_ci
4306f6ba60Sopenharmony_ciCpuDataPlugin::CpuDataPlugin()
4406f6ba60Sopenharmony_ci{
4506f6ba60Sopenharmony_ci    buffer_ = nullptr;
4606f6ba60Sopenharmony_ci    path_ = "/proc/";
4706f6ba60Sopenharmony_ci    err_ = -1;
4806f6ba60Sopenharmony_ci    pid_ = -1;
4906f6ba60Sopenharmony_ci    prevProcessCpuTime_ = 0;
5006f6ba60Sopenharmony_ci    prevCpuTimeData_ = {};
5106f6ba60Sopenharmony_ci    maxFreqIndex_ = -1;
5206f6ba60Sopenharmony_ci    freqPath_ = FREQUENCY_PATH;
5306f6ba60Sopenharmony_ci}
5406f6ba60Sopenharmony_ci
5506f6ba60Sopenharmony_ciCpuDataPlugin::~CpuDataPlugin()
5606f6ba60Sopenharmony_ci{
5706f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:~CpuDataPlugin!", __func__);
5806f6ba60Sopenharmony_ci    if (buffer_ != nullptr) {
5906f6ba60Sopenharmony_ci        free(buffer_);
6006f6ba60Sopenharmony_ci        buffer_ = nullptr;
6106f6ba60Sopenharmony_ci    }
6206f6ba60Sopenharmony_ci
6306f6ba60Sopenharmony_ci    tidVec_.clear();
6406f6ba60Sopenharmony_ci    prevThreadCpuTimeMap_.clear();
6506f6ba60Sopenharmony_ci    prevCoreSystemCpuTimeMap_.clear();
6606f6ba60Sopenharmony_ci    prevCoreSystemBootTimeMap_.clear();
6706f6ba60Sopenharmony_ci    maxFrequencyVec_.clear();
6806f6ba60Sopenharmony_ci    minFrequencyVec_.clear();
6906f6ba60Sopenharmony_ci}
7006f6ba60Sopenharmony_ci
7106f6ba60Sopenharmony_ciint CpuDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
7206f6ba60Sopenharmony_ci{
7306f6ba60Sopenharmony_ci    buffer_ = malloc(READ_BUFFER_SIZE);
7406f6ba60Sopenharmony_ci    CHECK_NOTNULL(buffer_, RET_FAIL, "%s:malloc buffer_ failed!", __func__);
7506f6ba60Sopenharmony_ci    if (memset_s(buffer_, READ_BUFFER_SIZE, 0, READ_BUFFER_SIZE) != EOK) {
7606f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:memset_s error!", __func__);
7706f6ba60Sopenharmony_ci    }
7806f6ba60Sopenharmony_ci    CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, RET_FAIL,
7906f6ba60Sopenharmony_ci               "%s:parseFromArray failed!", __func__);
8006f6ba60Sopenharmony_ci    if (protoConfig_.pid() > 0) {
8106f6ba60Sopenharmony_ci        pid_ = protoConfig_.pid();
8206f6ba60Sopenharmony_ci    } else if (protoConfig_.report_process_info()) {
8306f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "%s:need report process info", __func__);
8406f6ba60Sopenharmony_ci    } else {
8506f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:invalid pid", __func__);
8606f6ba60Sopenharmony_ci        return RET_FAIL;
8706f6ba60Sopenharmony_ci    }
8806f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:start success!", __func__);
8906f6ba60Sopenharmony_ci    return RET_SUCC;
9006f6ba60Sopenharmony_ci}
9106f6ba60Sopenharmony_ci
9206f6ba60Sopenharmony_ciint CpuDataPlugin::ReportOptimize(RandomWriteCtx* randomWrite)
9306f6ba60Sopenharmony_ci{
9406f6ba60Sopenharmony_ci    ProtoEncoder::CpuData dataProto(randomWrite);
9506f6ba60Sopenharmony_ci
9606f6ba60Sopenharmony_ci    ProtoEncoder::CpuUsageInfo* cpuUsageInfo = nullptr;
9706f6ba60Sopenharmony_ci    WriteCpuUsageInfo(dataProto, cpuUsageInfo);
9806f6ba60Sopenharmony_ci
9906f6ba60Sopenharmony_ci    if (pid_ > 0) {
10006f6ba60Sopenharmony_ci        WriteThreadInfo(dataProto);
10106f6ba60Sopenharmony_ci    }
10206f6ba60Sopenharmony_ci    if (protoConfig_.report_process_info()) {
10306f6ba60Sopenharmony_ci        WriteProcnum(dataProto);
10406f6ba60Sopenharmony_ci    }
10506f6ba60Sopenharmony_ci
10606f6ba60Sopenharmony_ci    int msgSize = dataProto.Finish();
10706f6ba60Sopenharmony_ci    return msgSize;
10806f6ba60Sopenharmony_ci}
10906f6ba60Sopenharmony_ci
11006f6ba60Sopenharmony_ciint CpuDataPlugin::Report(uint8_t* data, uint32_t dataSize)
11106f6ba60Sopenharmony_ci{
11206f6ba60Sopenharmony_ci    CpuData dataProto;
11306f6ba60Sopenharmony_ci    uint32_t length;
11406f6ba60Sopenharmony_ci
11506f6ba60Sopenharmony_ci    CpuUsageInfo* cpuUsageInfo = nullptr;
11606f6ba60Sopenharmony_ci    WriteCpuUsageInfo(dataProto, cpuUsageInfo);
11706f6ba60Sopenharmony_ci
11806f6ba60Sopenharmony_ci    if (pid_ > 0) {
11906f6ba60Sopenharmony_ci        WriteThreadInfo(dataProto);
12006f6ba60Sopenharmony_ci    }
12106f6ba60Sopenharmony_ci    if (protoConfig_.report_process_info()) {
12206f6ba60Sopenharmony_ci        WriteProcnum(dataProto);
12306f6ba60Sopenharmony_ci    }
12406f6ba60Sopenharmony_ci
12506f6ba60Sopenharmony_ci    length = dataProto.ByteSizeLong();
12606f6ba60Sopenharmony_ci    if (length > dataSize) {
12706f6ba60Sopenharmony_ci        return -length;
12806f6ba60Sopenharmony_ci    }
12906f6ba60Sopenharmony_ci    if (dataProto.SerializeToArray(data, length) > 0) {
13006f6ba60Sopenharmony_ci        return length;
13106f6ba60Sopenharmony_ci    }
13206f6ba60Sopenharmony_ci    return 0;
13306f6ba60Sopenharmony_ci}
13406f6ba60Sopenharmony_ci
13506f6ba60Sopenharmony_citemplate <typename T> bool CpuDataPlugin::WriteProcnum(T& cpuData)
13606f6ba60Sopenharmony_ci{
13706f6ba60Sopenharmony_ci    DIR* procDir = nullptr;
13806f6ba60Sopenharmony_ci    procDir = OpenDestDir(path_);
13906f6ba60Sopenharmony_ci    if (procDir == nullptr) {
14006f6ba60Sopenharmony_ci        return false;
14106f6ba60Sopenharmony_ci    }
14206f6ba60Sopenharmony_ci
14306f6ba60Sopenharmony_ci    uint32_t i = 0;
14406f6ba60Sopenharmony_ci    while (int32_t tid = GetValidTid(procDir)) {
14506f6ba60Sopenharmony_ci        if (tid <= 0) {
14606f6ba60Sopenharmony_ci            closedir(procDir);
14706f6ba60Sopenharmony_ci            PROFILER_LOG_WARN(LOG_CORE, "%s: get pid[%d] failed", __func__, tid);
14806f6ba60Sopenharmony_ci            return false;
14906f6ba60Sopenharmony_ci        }
15006f6ba60Sopenharmony_ci        i++;
15106f6ba60Sopenharmony_ci    }
15206f6ba60Sopenharmony_ci    cpuData.set_process_num(i);
15306f6ba60Sopenharmony_ci    closedir(procDir);
15406f6ba60Sopenharmony_ci
15506f6ba60Sopenharmony_ci    return true;
15606f6ba60Sopenharmony_ci}
15706f6ba60Sopenharmony_ci
15806f6ba60Sopenharmony_ciint CpuDataPlugin::Stop()
15906f6ba60Sopenharmony_ci{
16006f6ba60Sopenharmony_ci    if (buffer_ != nullptr) {
16106f6ba60Sopenharmony_ci        free(buffer_);
16206f6ba60Sopenharmony_ci        buffer_ = nullptr;
16306f6ba60Sopenharmony_ci    }
16406f6ba60Sopenharmony_ci
16506f6ba60Sopenharmony_ci    tidVec_.clear();
16606f6ba60Sopenharmony_ci    prevThreadCpuTimeMap_.clear();
16706f6ba60Sopenharmony_ci    prevCoreSystemCpuTimeMap_.clear();
16806f6ba60Sopenharmony_ci    prevCoreSystemBootTimeMap_.clear();
16906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "%s:stop success!", __func__);
17006f6ba60Sopenharmony_ci    return 0;
17106f6ba60Sopenharmony_ci}
17206f6ba60Sopenharmony_ci
17306f6ba60Sopenharmony_ciint32_t CpuDataPlugin::ReadFile(std::string& fileName)
17406f6ba60Sopenharmony_ci{
17506f6ba60Sopenharmony_ci    int fd = -1;
17606f6ba60Sopenharmony_ci    ssize_t bytesRead = 0;
17706f6ba60Sopenharmony_ci    char filePath[PATH_MAX + 1] = {0};
17806f6ba60Sopenharmony_ci    char realPath[PATH_MAX + 1] = {0};
17906f6ba60Sopenharmony_ci
18006f6ba60Sopenharmony_ci    if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s", fileName.c_str()) < 0) {
18106f6ba60Sopenharmony_ci        const int bufSize = 256;
18206f6ba60Sopenharmony_ci        char buf[bufSize] = { 0 };
18306f6ba60Sopenharmony_ci        strerror_r(errno, buf, bufSize);
18406f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "snprintf_s(%s) error, errno(%d:%s)", fileName.c_str(), errno, buf);
18506f6ba60Sopenharmony_ci        return RET_FAIL;
18606f6ba60Sopenharmony_ci    }
18706f6ba60Sopenharmony_ci    if (realpath(filePath, realPath) == nullptr) {
18806f6ba60Sopenharmony_ci        const int bufSize = 256;
18906f6ba60Sopenharmony_ci        char buf[bufSize] = { 0 };
19006f6ba60Sopenharmony_ci        strerror_r(errno, buf, bufSize);
19106f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "realpath(%s) failed, errno(%d:%s)", fileName.c_str(), errno, buf);
19206f6ba60Sopenharmony_ci        return RET_FAIL;
19306f6ba60Sopenharmony_ci    }
19406f6ba60Sopenharmony_ci
19506f6ba60Sopenharmony_ci    fd = open(realPath, O_RDONLY | O_CLOEXEC);
19606f6ba60Sopenharmony_ci    if (fd == -1) {
19706f6ba60Sopenharmony_ci        const int bufSize = 256;
19806f6ba60Sopenharmony_ci        char buf[bufSize] = { 0 };
19906f6ba60Sopenharmony_ci        strerror_r(errno, buf, bufSize);
20006f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, realPath, errno, buf);
20106f6ba60Sopenharmony_ci        err_ = errno;
20206f6ba60Sopenharmony_ci        return RET_FAIL;
20306f6ba60Sopenharmony_ci    }
20406f6ba60Sopenharmony_ci    if (buffer_ == nullptr) {
20506f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:empty address, buffer_ is NULL", __func__);
20606f6ba60Sopenharmony_ci        err_ = RET_NULL_ADDR;
20706f6ba60Sopenharmony_ci        close(fd);
20806f6ba60Sopenharmony_ci        return RET_FAIL;
20906f6ba60Sopenharmony_ci    }
21006f6ba60Sopenharmony_ci    if (memset_s(buffer_, READ_BUFFER_SIZE, 0, READ_BUFFER_SIZE) != EOK) {
21106f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:memset_s error!", __func__);
21206f6ba60Sopenharmony_ci    }
21306f6ba60Sopenharmony_ci    bytesRead = read(fd, buffer_, READ_BUFFER_SIZE - 1);
21406f6ba60Sopenharmony_ci    if (bytesRead <= 0) {
21506f6ba60Sopenharmony_ci        close(fd);
21606f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to read(%s), errno=%d", __func__, realPath, errno);
21706f6ba60Sopenharmony_ci        err_ = errno;
21806f6ba60Sopenharmony_ci        return RET_FAIL;
21906f6ba60Sopenharmony_ci    }
22006f6ba60Sopenharmony_ci    close(fd);
22106f6ba60Sopenharmony_ci
22206f6ba60Sopenharmony_ci    return bytesRead;
22306f6ba60Sopenharmony_ci}
22406f6ba60Sopenharmony_ci
22506f6ba60Sopenharmony_citemplate <typename T> void CpuDataPlugin::SetTimestamp(T& sampleTimeStamp)
22606f6ba60Sopenharmony_ci{
22706f6ba60Sopenharmony_ci    timespec time;
22806f6ba60Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &time);
22906f6ba60Sopenharmony_ci    sampleTimeStamp.set_tv_sec(time.tv_sec);
23006f6ba60Sopenharmony_ci    sampleTimeStamp.set_tv_nsec(time.tv_nsec);
23106f6ba60Sopenharmony_ci}
23206f6ba60Sopenharmony_ci
23306f6ba60Sopenharmony_ciint64_t CpuDataPlugin::GetUserHz()
23406f6ba60Sopenharmony_ci{
23506f6ba60Sopenharmony_ci    int64_t hz = -1;
23606f6ba60Sopenharmony_ci    int64_t user_hz = sysconf(_SC_CLK_TCK);
23706f6ba60Sopenharmony_ci    switch (user_hz) {
23806f6ba60Sopenharmony_ci        case CPU_USER_HZ_L:
23906f6ba60Sopenharmony_ci            hz = CPU_HZ_H;
24006f6ba60Sopenharmony_ci            break;
24106f6ba60Sopenharmony_ci        case CPU_USER_HZ_H:
24206f6ba60Sopenharmony_ci            hz = 1;
24306f6ba60Sopenharmony_ci            break;
24406f6ba60Sopenharmony_ci        default:
24506f6ba60Sopenharmony_ci            break;
24606f6ba60Sopenharmony_ci    }
24706f6ba60Sopenharmony_ci    return hz;
24806f6ba60Sopenharmony_ci}
24906f6ba60Sopenharmony_ci
25006f6ba60Sopenharmony_ciint64_t CpuDataPlugin::GetCpuUsageTime(std::vector<std::string>& cpuUsageVec)
25106f6ba60Sopenharmony_ci{
25206f6ba60Sopenharmony_ci    int64_t utime = 0;
25306f6ba60Sopenharmony_ci    int64_t stime = 0;
25406f6ba60Sopenharmony_ci    int64_t usageTime = 0;
25506f6ba60Sopenharmony_ci    utime = atoi(cpuUsageVec[PROCESS_UTIME].c_str());
25606f6ba60Sopenharmony_ci    stime = atoi(cpuUsageVec[PROCESS_STIME].c_str());
25706f6ba60Sopenharmony_ci    // 进程,线程CPU占用率只计算utime(用户态时间),stime(核心态时间)
25806f6ba60Sopenharmony_ci    usageTime = (utime + stime) * GetUserHz();
25906f6ba60Sopenharmony_ci
26006f6ba60Sopenharmony_ci    return usageTime;
26106f6ba60Sopenharmony_ci}
26206f6ba60Sopenharmony_ci
26306f6ba60Sopenharmony_citemplate <typename T> void CpuDataPlugin::WriteProcessCpuUsage(T& cpuUsageInfo, const char* pFile, uint32_t fileLen)
26406f6ba60Sopenharmony_ci{
26506f6ba60Sopenharmony_ci    BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
26606f6ba60Sopenharmony_ci    std::vector<std::string> cpuUsageVec;
26706f6ba60Sopenharmony_ci    for (int i = 0; i < STAT_COUNT; i++) {
26806f6ba60Sopenharmony_ci        totalbuffer.NextWord(' ');
26906f6ba60Sopenharmony_ci        if (!totalbuffer.CurWord()) {
27006f6ba60Sopenharmony_ci            return;
27106f6ba60Sopenharmony_ci        }
27206f6ba60Sopenharmony_ci
27306f6ba60Sopenharmony_ci        if (i < STAT_START) {
27406f6ba60Sopenharmony_ci            continue;
27506f6ba60Sopenharmony_ci        } else {
27606f6ba60Sopenharmony_ci            std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
27706f6ba60Sopenharmony_ci            cpuUsageVec.push_back(curWord);
27806f6ba60Sopenharmony_ci        }
27906f6ba60Sopenharmony_ci    }
28006f6ba60Sopenharmony_ci
28106f6ba60Sopenharmony_ci    // 获取到的数据不包含utime、stime、cutime、cstime四个数值时返回
28206f6ba60Sopenharmony_ci    if (cpuUsageVec.size() != PROCESS_UNSPECIFIED) {
28306f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to get process cpu usage, size=%zu", __func__, cpuUsageVec.size());
28406f6ba60Sopenharmony_ci        return;
28506f6ba60Sopenharmony_ci    }
28606f6ba60Sopenharmony_ci
28706f6ba60Sopenharmony_ci    int64_t usageTime = GetCpuUsageTime(cpuUsageVec);
28806f6ba60Sopenharmony_ci    cpuUsageInfo.set_prev_process_cpu_time_ms(prevProcessCpuTime_);
28906f6ba60Sopenharmony_ci    cpuUsageInfo.set_process_cpu_time_ms(usageTime);
29006f6ba60Sopenharmony_ci    prevProcessCpuTime_ = usageTime;
29106f6ba60Sopenharmony_ci}
29206f6ba60Sopenharmony_ci
29306f6ba60Sopenharmony_ciint32_t CpuDataPlugin::GetCpuFrequency(std::string fileName)
29406f6ba60Sopenharmony_ci{
29506f6ba60Sopenharmony_ci    int32_t frequency = 0;
29606f6ba60Sopenharmony_ci    int32_t ret = ReadFile(fileName);
29706f6ba60Sopenharmony_ci    if (ret != RET_FAIL) {
29806f6ba60Sopenharmony_ci        std::string tempStr(static_cast<char*>(buffer_));
29906f6ba60Sopenharmony_ci        // 去掉首尾特殊字符
30006f6ba60Sopenharmony_ci        size_t start = tempStr.find_first_not_of(" \t\n\r");
30106f6ba60Sopenharmony_ci        if (start == std::string::npos) {
30206f6ba60Sopenharmony_ci            return frequency;
30306f6ba60Sopenharmony_ci        }
30406f6ba60Sopenharmony_ci        size_t end = tempStr.find_last_not_of(" \t\n\r");
30506f6ba60Sopenharmony_ci        tempStr = tempStr.substr(start, end - start + 1);
30606f6ba60Sopenharmony_ci        if (std::all_of(tempStr.begin(), tempStr.end(), ::isdigit)) {
30706f6ba60Sopenharmony_ci            frequency = atoi(static_cast<char*>(buffer_));
30806f6ba60Sopenharmony_ci        }
30906f6ba60Sopenharmony_ci    }
31006f6ba60Sopenharmony_ci    return frequency;
31106f6ba60Sopenharmony_ci}
31206f6ba60Sopenharmony_ci
31306f6ba60Sopenharmony_ciint CpuDataPlugin::GetCpuCoreSize()
31406f6ba60Sopenharmony_ci{
31506f6ba60Sopenharmony_ci    int coreSize = 0;
31606f6ba60Sopenharmony_ci    DIR* procDir = nullptr;
31706f6ba60Sopenharmony_ci    procDir = OpenDestDir(freqPath_);
31806f6ba60Sopenharmony_ci    CHECK_NOTNULL(procDir, -1, "procDir is nullptr");
31906f6ba60Sopenharmony_ci
32006f6ba60Sopenharmony_ci    while (struct dirent* dirEnt = readdir(procDir)) {
32106f6ba60Sopenharmony_ci        if (dirEnt->d_type != DT_DIR) {
32206f6ba60Sopenharmony_ci            continue;
32306f6ba60Sopenharmony_ci        }
32406f6ba60Sopenharmony_ci        if (strncmp(dirEnt->d_name, "cpu", strlen("cpu")) == 0) {
32506f6ba60Sopenharmony_ci            coreSize++;
32606f6ba60Sopenharmony_ci        }
32706f6ba60Sopenharmony_ci    }
32806f6ba60Sopenharmony_ci    closedir(procDir);
32906f6ba60Sopenharmony_ci    return coreSize;
33006f6ba60Sopenharmony_ci}
33106f6ba60Sopenharmony_ci
33206f6ba60Sopenharmony_ciint32_t CpuDataPlugin::GetMaxCpuFrequencyIndex()
33306f6ba60Sopenharmony_ci{
33406f6ba60Sopenharmony_ci    int coreSize = GetCpuCoreSize();
33506f6ba60Sopenharmony_ci    int index = -1;
33606f6ba60Sopenharmony_ci    int32_t maxFreq = -1;
33706f6ba60Sopenharmony_ci    maxFrequencyVec_.clear();
33806f6ba60Sopenharmony_ci    minFrequencyVec_.clear();
33906f6ba60Sopenharmony_ci    for (int i = 0; i < coreSize; i++) {
34006f6ba60Sopenharmony_ci        std::string fileName = freqPath_ + "/cpu" + std::to_string(i) + FREQUENCY_MAX_PATH;
34106f6ba60Sopenharmony_ci        int32_t maxFrequency = GetCpuFrequency(fileName);
34206f6ba60Sopenharmony_ci        maxFrequencyVec_.push_back(maxFrequency);
34306f6ba60Sopenharmony_ci        fileName = freqPath_ + "/cpu" + std::to_string(i) + FREQUENCY_MIN_PATH;
34406f6ba60Sopenharmony_ci        int32_t minFrequency = GetCpuFrequency(fileName);
34506f6ba60Sopenharmony_ci        minFrequencyVec_.push_back(minFrequency);
34606f6ba60Sopenharmony_ci
34706f6ba60Sopenharmony_ci        if (maxFreq < maxFrequency) {
34806f6ba60Sopenharmony_ci            maxFreq = maxFrequency;
34906f6ba60Sopenharmony_ci            index = i;
35006f6ba60Sopenharmony_ci        }
35106f6ba60Sopenharmony_ci    }
35206f6ba60Sopenharmony_ci
35306f6ba60Sopenharmony_ci    // 单核或所有核最大频率相同,默认小核
35406f6ba60Sopenharmony_ci    if (coreSize == 1 || (coreSize > 1 && index == 0 && maxFreq == maxFrequencyVec_[1])) {
35506f6ba60Sopenharmony_ci        index = -1;
35606f6ba60Sopenharmony_ci    }
35706f6ba60Sopenharmony_ci
35806f6ba60Sopenharmony_ci    return index;
35906f6ba60Sopenharmony_ci}
36006f6ba60Sopenharmony_ci
36106f6ba60Sopenharmony_citemplate <typename T> void CpuDataPlugin::SetCpuFrequency(T& cpuCoreUsageInfo, int32_t coreNum)
36206f6ba60Sopenharmony_ci{
36306f6ba60Sopenharmony_ci    // 第一次获取最大频率核位置,并保存各核最大最小频率到vector
36406f6ba60Sopenharmony_ci    if (maxFrequencyVec_.empty() || minFrequencyVec_.empty()) {
36506f6ba60Sopenharmony_ci        maxFreqIndex_ = GetMaxCpuFrequencyIndex();
36606f6ba60Sopenharmony_ci    }
36706f6ba60Sopenharmony_ci    std::string fileName = freqPath_ + "/cpu" + std::to_string(coreNum) + FREQUENCY_CUR_PATH;
36806f6ba60Sopenharmony_ci    int32_t curFrequency = GetCpuFrequency(fileName);
36906f6ba60Sopenharmony_ci    int32_t maxFrequency = maxFrequencyVec_[coreNum];
37006f6ba60Sopenharmony_ci    int32_t minFrequency = minFrequencyVec_[coreNum];
37106f6ba60Sopenharmony_ci
37206f6ba60Sopenharmony_ci    if (coreNum == maxFreqIndex_) {
37306f6ba60Sopenharmony_ci        cpuCoreUsageInfo.set_is_little_core(false);
37406f6ba60Sopenharmony_ci    } else {
37506f6ba60Sopenharmony_ci        cpuCoreUsageInfo.set_is_little_core(true);
37606f6ba60Sopenharmony_ci    }
37706f6ba60Sopenharmony_ci    auto* frequency = cpuCoreUsageInfo.mutable_frequency();
37806f6ba60Sopenharmony_ci    frequency->set_min_frequency_khz(minFrequency);
37906f6ba60Sopenharmony_ci    frequency->set_max_frequency_khz(maxFrequency);
38006f6ba60Sopenharmony_ci    frequency->set_cur_frequency_khz(curFrequency);
38106f6ba60Sopenharmony_ci}
38206f6ba60Sopenharmony_ci
38306f6ba60Sopenharmony_cibool CpuDataPlugin::GetSystemCpuTime(std::vector<std::string>& cpuUsageVec, CpuTimeData& cpuTimeData)
38406f6ba60Sopenharmony_ci{
38506f6ba60Sopenharmony_ci    // 获取到的数据不包含user, nice, system, idle, iowait, irq, softirq, steal八个数值时返回
38606f6ba60Sopenharmony_ci    CHECK_TRUE(cpuUsageVec.size() == SYSTEM_UNSPECIFIED, false,
38706f6ba60Sopenharmony_ci               "%s:failed to get system cpu usage, size=%zu", __func__, cpuUsageVec.size());
38806f6ba60Sopenharmony_ci
38906f6ba60Sopenharmony_ci    int64_t user = 0;
39006f6ba60Sopenharmony_ci    int64_t nice = 0;
39106f6ba60Sopenharmony_ci    int64_t system = 0;
39206f6ba60Sopenharmony_ci    int64_t idle = 0;
39306f6ba60Sopenharmony_ci    int64_t iowait = 0;
39406f6ba60Sopenharmony_ci    int64_t irq = 0;
39506f6ba60Sopenharmony_ci    int64_t softirq = 0;
39606f6ba60Sopenharmony_ci    int64_t steal = 0;
39706f6ba60Sopenharmony_ci    user = atoi(cpuUsageVec[SYSTEM_USER].c_str());
39806f6ba60Sopenharmony_ci    nice = atoi(cpuUsageVec[SYSTEM_NICE].c_str());
39906f6ba60Sopenharmony_ci    system = atoi(cpuUsageVec[SYSTEM_SYSTEM].c_str());
40006f6ba60Sopenharmony_ci    idle = atoi(cpuUsageVec[SYSTEM_IDLE].c_str());
40106f6ba60Sopenharmony_ci    iowait = atoi(cpuUsageVec[SYSTEM_IOWAIT].c_str());
40206f6ba60Sopenharmony_ci    irq = atoi(cpuUsageVec[SYSTEM_IRQ].c_str());
40306f6ba60Sopenharmony_ci    softirq = atoi(cpuUsageVec[SYSTEM_SOFTIRQ].c_str());
40406f6ba60Sopenharmony_ci    steal = atoi(cpuUsageVec[SYSTEM_STEAL].c_str());
40506f6ba60Sopenharmony_ci
40606f6ba60Sopenharmony_ci    cpuTimeData.userModeUsageTime = user * GetUserHz();
40706f6ba60Sopenharmony_ci    cpuTimeData.systemModeUsageTime = system * GetUserHz();
40806f6ba60Sopenharmony_ci    cpuTimeData.systemUsageTime = (user + nice + system + irq + softirq + steal) * GetUserHz();
40906f6ba60Sopenharmony_ci    cpuTimeData.systemBootTime = cpuTimeData.systemUsageTime + (idle + iowait) * GetUserHz();
41006f6ba60Sopenharmony_ci    return true;
41106f6ba60Sopenharmony_ci}
41206f6ba60Sopenharmony_ci
41306f6ba60Sopenharmony_citemplate <typename T>
41406f6ba60Sopenharmony_civoid CpuDataPlugin::WriteSystemCpuUsage(T& cpuUsageInfo, CpuLoadData& cpuLoadData, const char* pFile, uint32_t fileLen)
41506f6ba60Sopenharmony_ci{
41606f6ba60Sopenharmony_ci    std::vector<std::string> cpuUsageVec;
41706f6ba60Sopenharmony_ci    size_t cpuLength = strlen("cpu");
41806f6ba60Sopenharmony_ci    std::stringstream ss(pFile);
41906f6ba60Sopenharmony_ci    std::string line;
42006f6ba60Sopenharmony_ci    while (std::getline(ss, line)) {
42106f6ba60Sopenharmony_ci        BufferSplitter totalbuffer(const_cast<char*>(line.c_str()), line.length());
42206f6ba60Sopenharmony_ci        totalbuffer.NextWord(' ');
42306f6ba60Sopenharmony_ci        if (!totalbuffer.CurWord() || strncmp(totalbuffer.CurWord(), "cpu", cpuLength) != 0) {
42406f6ba60Sopenharmony_ci            return;
42506f6ba60Sopenharmony_ci        }
42606f6ba60Sopenharmony_ci
42706f6ba60Sopenharmony_ci        for (int i = 0; i < SYSTEM_STAT_COUNT; i++) {
42806f6ba60Sopenharmony_ci            if (!totalbuffer.CurWord()) {
42906f6ba60Sopenharmony_ci                return;
43006f6ba60Sopenharmony_ci            }
43106f6ba60Sopenharmony_ci            std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
43206f6ba60Sopenharmony_ci            cpuUsageVec.push_back(curWord);
43306f6ba60Sopenharmony_ci            totalbuffer.NextWord(' ');
43406f6ba60Sopenharmony_ci        }
43506f6ba60Sopenharmony_ci
43606f6ba60Sopenharmony_ci        // 获取数据失败返回
43706f6ba60Sopenharmony_ci        CpuTimeData cpuTimeData;
43806f6ba60Sopenharmony_ci        if (!GetSystemCpuTime(cpuUsageVec, cpuTimeData)) {
43906f6ba60Sopenharmony_ci            return;
44006f6ba60Sopenharmony_ci        }
44106f6ba60Sopenharmony_ci
44206f6ba60Sopenharmony_ci        if (strcmp(cpuUsageVec[0].c_str(), "cpu") == 0) {
44306f6ba60Sopenharmony_ci            cpuUsageInfo.set_prev_system_cpu_time_ms(prevCpuTimeData_.systemUsageTime);
44406f6ba60Sopenharmony_ci            cpuUsageInfo.set_prev_system_boot_time_ms(prevCpuTimeData_.systemBootTime);
44506f6ba60Sopenharmony_ci            cpuUsageInfo.set_system_cpu_time_ms(cpuTimeData.systemUsageTime);
44606f6ba60Sopenharmony_ci            cpuUsageInfo.set_system_boot_time_ms(cpuTimeData.systemBootTime);
44706f6ba60Sopenharmony_ci            bool isTest = false;
44806f6ba60Sopenharmony_ci            if (strncmp(path_.c_str(), "/proc/", strlen("/proc/")) != 0) {
44906f6ba60Sopenharmony_ci                isTest = true; // UT needs report load data for the first time
45006f6ba60Sopenharmony_ci            }
45106f6ba60Sopenharmony_ci            if ((protoConfig_.report_process_info() && prevCpuTimeData_.systemBootTime != 0) || isTest) {
45206f6ba60Sopenharmony_ci                cpuLoadData.userLoad = static_cast<double>(cpuTimeData.userModeUsageTime -
45306f6ba60Sopenharmony_ci                    prevCpuTimeData_.userModeUsageTime) /
45406f6ba60Sopenharmony_ci                    static_cast<double>(cpuTimeData.systemBootTime -
45506f6ba60Sopenharmony_ci                    prevCpuTimeData_.systemBootTime) * PERCENT;
45606f6ba60Sopenharmony_ci                cpuLoadData.sysLoad = static_cast<double>(cpuTimeData.systemModeUsageTime -
45706f6ba60Sopenharmony_ci                    prevCpuTimeData_.systemModeUsageTime) /
45806f6ba60Sopenharmony_ci                    static_cast<double>(cpuTimeData.systemBootTime -
45906f6ba60Sopenharmony_ci                    prevCpuTimeData_.systemBootTime) * PERCENT;
46006f6ba60Sopenharmony_ci                cpuLoadData.totalLoad = static_cast<double>(cpuTimeData.systemUsageTime -
46106f6ba60Sopenharmony_ci                    prevCpuTimeData_.systemUsageTime) /
46206f6ba60Sopenharmony_ci                    static_cast<double>(cpuTimeData.systemBootTime -
46306f6ba60Sopenharmony_ci                    prevCpuTimeData_.systemBootTime) * PERCENT;
46406f6ba60Sopenharmony_ci            }
46506f6ba60Sopenharmony_ci            prevCpuTimeData_ = cpuTimeData;
46606f6ba60Sopenharmony_ci            if (pid_ < 0 && protoConfig_.report_process_info()) {
46706f6ba60Sopenharmony_ci                return;
46806f6ba60Sopenharmony_ci            }
46906f6ba60Sopenharmony_ci        } else {
47006f6ba60Sopenharmony_ci            std::string core = std::string(cpuUsageVec[0].c_str() + cpuLength, cpuUsageVec[0].size() - cpuLength);
47106f6ba60Sopenharmony_ci            int32_t coreNum = atoi(core.c_str());
47206f6ba60Sopenharmony_ci            // 第一次获取数据时需要将前一个数据置为0
47306f6ba60Sopenharmony_ci            if (prevCoreSystemCpuTimeMap_.size() == static_cast<size_t>(coreNum)) {
47406f6ba60Sopenharmony_ci                prevCoreSystemCpuTimeMap_[coreNum] = 0;
47506f6ba60Sopenharmony_ci                prevCoreSystemBootTimeMap_[coreNum] = 0;
47606f6ba60Sopenharmony_ci            }
47706f6ba60Sopenharmony_ci            auto* cpuCore = cpuUsageInfo.add_cores();
47806f6ba60Sopenharmony_ci            cpuCore->set_cpu_core(coreNum);
47906f6ba60Sopenharmony_ci            cpuCore->set_prev_system_cpu_time_ms(prevCoreSystemCpuTimeMap_[coreNum]);
48006f6ba60Sopenharmony_ci            cpuCore->set_prev_system_boot_time_ms(prevCoreSystemBootTimeMap_[coreNum]);
48106f6ba60Sopenharmony_ci            cpuCore->set_system_cpu_time_ms(cpuTimeData.systemUsageTime);
48206f6ba60Sopenharmony_ci            cpuCore->set_system_boot_time_ms(cpuTimeData.systemBootTime);
48306f6ba60Sopenharmony_ci
48406f6ba60Sopenharmony_ci            SetCpuFrequency(*cpuCore, coreNum);
48506f6ba60Sopenharmony_ci            prevCoreSystemCpuTimeMap_[coreNum] = cpuTimeData.systemUsageTime;
48606f6ba60Sopenharmony_ci            prevCoreSystemBootTimeMap_[coreNum] = cpuTimeData.systemBootTime;
48706f6ba60Sopenharmony_ci        }
48806f6ba60Sopenharmony_ci
48906f6ba60Sopenharmony_ci        cpuUsageVec.clear();
49006f6ba60Sopenharmony_ci    }
49106f6ba60Sopenharmony_ci}
49206f6ba60Sopenharmony_ci
49306f6ba60Sopenharmony_citemplate <typename T, typename I> void CpuDataPlugin::WriteCpuUsageInfo(T& cpuData, I cpuUsageInfo)
49406f6ba60Sopenharmony_ci{
49506f6ba60Sopenharmony_ci    // write process info
49606f6ba60Sopenharmony_ci    if (pid_ > 0) {
49706f6ba60Sopenharmony_ci        std::string fileName = path_ + std::to_string(pid_) + "/stat";
49806f6ba60Sopenharmony_ci        int32_t ret = ReadFile(fileName);
49906f6ba60Sopenharmony_ci        if (ret == RET_FAIL) {
50006f6ba60Sopenharmony_ci            return;
50106f6ba60Sopenharmony_ci        }
50206f6ba60Sopenharmony_ci        if ((buffer_ == nullptr) || (ret == 0)) {
50306f6ba60Sopenharmony_ci            return;
50406f6ba60Sopenharmony_ci        }
50506f6ba60Sopenharmony_ci
50606f6ba60Sopenharmony_ci        cpuUsageInfo = cpuData.mutable_cpu_usage_info();
50706f6ba60Sopenharmony_ci        WriteProcessCpuUsage(*cpuUsageInfo, reinterpret_cast<char*>(buffer_), ret);
50806f6ba60Sopenharmony_ci    }
50906f6ba60Sopenharmony_ci
51006f6ba60Sopenharmony_ci    // write system info
51106f6ba60Sopenharmony_ci    std::string fileName = path_ + "stat";
51206f6ba60Sopenharmony_ci    int32_t ret = ReadFile(fileName);
51306f6ba60Sopenharmony_ci    if (ret == RET_FAIL) {
51406f6ba60Sopenharmony_ci        return;
51506f6ba60Sopenharmony_ci    }
51606f6ba60Sopenharmony_ci    if ((buffer_ == nullptr) || (ret == 0)) {
51706f6ba60Sopenharmony_ci        return;
51806f6ba60Sopenharmony_ci    }
51906f6ba60Sopenharmony_ci
52006f6ba60Sopenharmony_ci    CpuLoadData cpuLoadData;
52106f6ba60Sopenharmony_ci    if (cpuUsageInfo == nullptr) {
52206f6ba60Sopenharmony_ci        cpuUsageInfo = cpuData.mutable_cpu_usage_info();
52306f6ba60Sopenharmony_ci    }
52406f6ba60Sopenharmony_ci    WriteSystemCpuUsage(*cpuUsageInfo, cpuLoadData, reinterpret_cast<char*>(buffer_), ret);
52506f6ba60Sopenharmony_ci
52606f6ba60Sopenharmony_ci    auto* timestamp = cpuUsageInfo->mutable_timestamp();
52706f6ba60Sopenharmony_ci    SetTimestamp(*timestamp);
52806f6ba60Sopenharmony_ci
52906f6ba60Sopenharmony_ci    cpuData.set_user_load(cpuLoadData.userLoad);
53006f6ba60Sopenharmony_ci    cpuData.set_sys_load(cpuLoadData.sysLoad);
53106f6ba60Sopenharmony_ci    cpuData.set_total_load(cpuLoadData.totalLoad);
53206f6ba60Sopenharmony_ci}
53306f6ba60Sopenharmony_ci
53406f6ba60Sopenharmony_cibool CpuDataPlugin::addTidBySort(int32_t tid)
53506f6ba60Sopenharmony_ci{
53606f6ba60Sopenharmony_ci    auto tidsEnd = tidVec_.end();
53706f6ba60Sopenharmony_ci    auto it = std::lower_bound(tidVec_.begin(), tidsEnd, tid);
53806f6ba60Sopenharmony_ci    CHECK_TRUE(!(it != tidsEnd && *it == tid), false, "addTidBySort failed");
53906f6ba60Sopenharmony_ci    it = tidVec_.insert(it, std::move(tid));
54006f6ba60Sopenharmony_ci    return true;
54106f6ba60Sopenharmony_ci}
54206f6ba60Sopenharmony_ci
54306f6ba60Sopenharmony_ciDIR* CpuDataPlugin::OpenDestDir(std::string& dirPath)
54406f6ba60Sopenharmony_ci{
54506f6ba60Sopenharmony_ci    DIR* destDir = nullptr;
54606f6ba60Sopenharmony_ci
54706f6ba60Sopenharmony_ci    destDir = opendir(dirPath.c_str());
54806f6ba60Sopenharmony_ci    CHECK_NOTNULL(destDir, nullptr, "%s:failed to opendir(%s), errno=%d", __func__, dirPath.c_str(), errno);
54906f6ba60Sopenharmony_ci
55006f6ba60Sopenharmony_ci    return destDir;
55106f6ba60Sopenharmony_ci}
55206f6ba60Sopenharmony_ci
55306f6ba60Sopenharmony_ciint32_t CpuDataPlugin::GetValidTid(DIR* dirp)
55406f6ba60Sopenharmony_ci{
55506f6ba60Sopenharmony_ci    CHECK_TRUE(dirp, 0, "dirp is nullptr");
55606f6ba60Sopenharmony_ci    while (struct dirent* dirEnt = readdir(dirp)) {
55706f6ba60Sopenharmony_ci        if (dirEnt->d_type != DT_DIR) {
55806f6ba60Sopenharmony_ci            continue;
55906f6ba60Sopenharmony_ci        }
56006f6ba60Sopenharmony_ci
56106f6ba60Sopenharmony_ci        int32_t tid = atoi(dirEnt->d_name);
56206f6ba60Sopenharmony_ci        if (tid) {
56306f6ba60Sopenharmony_ci            return tid;
56406f6ba60Sopenharmony_ci        }
56506f6ba60Sopenharmony_ci    }
56606f6ba60Sopenharmony_ci    return 0;
56706f6ba60Sopenharmony_ci}
56806f6ba60Sopenharmony_ci
56906f6ba60Sopenharmony_ciThreadState CpuDataPlugin::GetThreadState(const char threadState)
57006f6ba60Sopenharmony_ci{
57106f6ba60Sopenharmony_ci    ThreadState state = THREAD_UNSPECIFIED;
57206f6ba60Sopenharmony_ci    switch (threadState) {
57306f6ba60Sopenharmony_ci        case 'R':
57406f6ba60Sopenharmony_ci            state = THREAD_RUNNING;
57506f6ba60Sopenharmony_ci            break;
57606f6ba60Sopenharmony_ci        case 'S':
57706f6ba60Sopenharmony_ci            state = THREAD_SLEEPING;
57806f6ba60Sopenharmony_ci            break;
57906f6ba60Sopenharmony_ci        case 'T':
58006f6ba60Sopenharmony_ci            state = THREAD_STOPPED;
58106f6ba60Sopenharmony_ci            break;
58206f6ba60Sopenharmony_ci        case 'D':
58306f6ba60Sopenharmony_ci            state = THREAD_WAITING;
58406f6ba60Sopenharmony_ci            break;
58506f6ba60Sopenharmony_ci        default:
58606f6ba60Sopenharmony_ci            break;
58706f6ba60Sopenharmony_ci    }
58806f6ba60Sopenharmony_ci
58906f6ba60Sopenharmony_ci    return state;
59006f6ba60Sopenharmony_ci}
59106f6ba60Sopenharmony_ci
59206f6ba60Sopenharmony_citemplate <typename T> void CpuDataPlugin::WriteThread(T& threadInfo, const char* pFile, uint32_t fileLen, int32_t tid)
59306f6ba60Sopenharmony_ci{
59406f6ba60Sopenharmony_ci    BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
59506f6ba60Sopenharmony_ci    std::vector<std::string> cpuUsageVec;
59606f6ba60Sopenharmony_ci    for (int i = 0; i < STAT_COUNT; i++) {
59706f6ba60Sopenharmony_ci        if (i == THREAD_NAME_POS) { // 线程名是')'作为结束符
59806f6ba60Sopenharmony_ci            totalbuffer.NextWord(')');
59906f6ba60Sopenharmony_ci        } else {
60006f6ba60Sopenharmony_ci            totalbuffer.NextWord(' ');
60106f6ba60Sopenharmony_ci        }
60206f6ba60Sopenharmony_ci
60306f6ba60Sopenharmony_ci        if (!totalbuffer.CurWord()) {
60406f6ba60Sopenharmony_ci            return;
60506f6ba60Sopenharmony_ci        }
60606f6ba60Sopenharmony_ci
60706f6ba60Sopenharmony_ci        if (i == THREAD_NAME_POS) {
60806f6ba60Sopenharmony_ci            size_t nameLeng = totalbuffer.CurWordSize() > 1 ? static_cast<size_t>(totalbuffer.CurWordSize() - 1) : 0;
60906f6ba60Sopenharmony_ci            std::string curWord = std::string(totalbuffer.CurWord() + 1, nameLeng);
61006f6ba60Sopenharmony_ci            threadInfo.set_thread_name(curWord);
61106f6ba60Sopenharmony_ci        } else if (i == THREAD_STATE_POS) {
61206f6ba60Sopenharmony_ci            std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
61306f6ba60Sopenharmony_ci            ThreadState state = GetThreadState(curWord[0]);
61406f6ba60Sopenharmony_ci            threadInfo.set_thread_state(state);
61506f6ba60Sopenharmony_ci        } else if (i >= STAT_START) {
61606f6ba60Sopenharmony_ci            std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
61706f6ba60Sopenharmony_ci            cpuUsageVec.push_back(curWord);
61806f6ba60Sopenharmony_ci        }
61906f6ba60Sopenharmony_ci    }
62006f6ba60Sopenharmony_ci
62106f6ba60Sopenharmony_ci    // 获取到的数据不包含utime、stime、cutime、cstime四个数值时返回
62206f6ba60Sopenharmony_ci    if (cpuUsageVec.size() != PROCESS_UNSPECIFIED) {
62306f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to get thread cpu usage, size=%zu", __func__, cpuUsageVec.size());
62406f6ba60Sopenharmony_ci        return;
62506f6ba60Sopenharmony_ci    }
62606f6ba60Sopenharmony_ci
62706f6ba60Sopenharmony_ci    // 第一次获取该线程数据时需要将前一个数据置为0
62806f6ba60Sopenharmony_ci    if (prevThreadCpuTimeMap_.find(tid) == prevThreadCpuTimeMap_.end()) {
62906f6ba60Sopenharmony_ci        prevThreadCpuTimeMap_[tid] = 0;
63006f6ba60Sopenharmony_ci    }
63106f6ba60Sopenharmony_ci
63206f6ba60Sopenharmony_ci    int64_t usageTime = GetCpuUsageTime(cpuUsageVec);
63306f6ba60Sopenharmony_ci    threadInfo.set_prev_thread_cpu_time_ms(prevThreadCpuTimeMap_[tid]);
63406f6ba60Sopenharmony_ci    threadInfo.set_thread_cpu_time_ms(usageTime);
63506f6ba60Sopenharmony_ci    prevThreadCpuTimeMap_[tid] = usageTime;
63606f6ba60Sopenharmony_ci    threadInfo.set_tid(tid);
63706f6ba60Sopenharmony_ci
63806f6ba60Sopenharmony_ci    auto* timestamp = threadInfo.mutable_timestamp();
63906f6ba60Sopenharmony_ci    SetTimestamp(*timestamp);
64006f6ba60Sopenharmony_ci}
64106f6ba60Sopenharmony_ci
64206f6ba60Sopenharmony_citemplate <typename T> void CpuDataPlugin::WriteSingleThreadInfo(T& cpuData, int32_t tid)
64306f6ba60Sopenharmony_ci{
64406f6ba60Sopenharmony_ci    std::string fileName = path_ + std::to_string(pid_) + "/task/" + std::to_string(tid) + "/stat";
64506f6ba60Sopenharmony_ci    int32_t ret = ReadFile(fileName);
64606f6ba60Sopenharmony_ci    if (ret == RET_FAIL) {
64706f6ba60Sopenharmony_ci        return;
64806f6ba60Sopenharmony_ci    }
64906f6ba60Sopenharmony_ci    if ((buffer_ == nullptr) || (ret == 0)) {
65006f6ba60Sopenharmony_ci        return;
65106f6ba60Sopenharmony_ci    }
65206f6ba60Sopenharmony_ci    auto* threadInfo = cpuData.add_thread_info();
65306f6ba60Sopenharmony_ci    WriteThread(*threadInfo, reinterpret_cast<char*>(buffer_), ret, tid);
65406f6ba60Sopenharmony_ci}
65506f6ba60Sopenharmony_ci
65606f6ba60Sopenharmony_citemplate <typename T> void CpuDataPlugin::WriteThreadInfo(T& cpuData)
65706f6ba60Sopenharmony_ci{
65806f6ba60Sopenharmony_ci    DIR* procDir = nullptr;
65906f6ba60Sopenharmony_ci    std::string path = path_ + std::to_string(pid_) + "/task";
66006f6ba60Sopenharmony_ci    procDir = OpenDestDir(path);
66106f6ba60Sopenharmony_ci    if (procDir == nullptr) {
66206f6ba60Sopenharmony_ci        return;
66306f6ba60Sopenharmony_ci    }
66406f6ba60Sopenharmony_ci
66506f6ba60Sopenharmony_ci    tidVec_.clear();
66606f6ba60Sopenharmony_ci    while (int32_t tid = GetValidTid(procDir)) {
66706f6ba60Sopenharmony_ci        addTidBySort(tid);
66806f6ba60Sopenharmony_ci    }
66906f6ba60Sopenharmony_ci
67006f6ba60Sopenharmony_ci    for (unsigned int i = 0; i < tidVec_.size(); i++) {
67106f6ba60Sopenharmony_ci        WriteSingleThreadInfo(cpuData, tidVec_[i]);
67206f6ba60Sopenharmony_ci    }
67306f6ba60Sopenharmony_ci    closedir(procDir);
67406f6ba60Sopenharmony_ci}
67506f6ba60Sopenharmony_ci
67606f6ba60Sopenharmony_ci// for UT
67706f6ba60Sopenharmony_civoid CpuDataPlugin::SetFreqPath(std::string path)
67806f6ba60Sopenharmony_ci{
67906f6ba60Sopenharmony_ci    freqPath_ = path + FREQUENCY_PATH;
68006f6ba60Sopenharmony_ci}
681