• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "cpu_data_plugin.h"
17 
18 #include <ctime>
19 #include <vector>
20 
21 #include "buffer_splitter.h"
22 
23 namespace {
24 constexpr size_t READ_BUFFER_SIZE = 1024 * 16;
25 constexpr int SYSTEM_STAT_COUNT = 9;
26 constexpr int STAT_COUNT = 17;
27 constexpr int STAT_START = 13;
28 constexpr int THREAD_NAME_POS = 1;
29 constexpr int THREAD_STATE_POS = 2;
30 constexpr int CPU_USER_HZ_L = 100;
31 constexpr int CPU_USER_HZ_H = 1000;
32 constexpr int CPU_HZ_H = 10;
33 const int PERCENT = 100;
34 
35 const std::string FREQUENCY_PATH = "/sys/devices/system/cpu";
36 const std::string FREQUENCY_MIN_PATH = "/cpufreq/cpuinfo_min_freq";
37 const std::string FREQUENCY_MAX_PATH = "/cpufreq/cpuinfo_max_freq";
38 const std::string FREQUENCY_CUR_PATH = "/cpufreq/cpuinfo_cur_freq";
39 } // namespace
40 
CpuDataPlugin()41 CpuDataPlugin::CpuDataPlugin()
42 {
43     buffer_ = nullptr;
44     path_ = "/proc/";
45     err_ = -1;
46     pid_ = -1;
47     prevProcessCpuTime_ = 0;
48     prevCpuTimeData_ = {};
49     maxFreqIndex_ = -1;
50     freqPath_ = FREQUENCY_PATH;
51 }
52 
~CpuDataPlugin()53 CpuDataPlugin::~CpuDataPlugin()
54 {
55     HILOG_INFO(LOG_CORE, "%s:~CpuDataPlugin!", __func__);
56     if (buffer_ != nullptr) {
57         free(buffer_);
58         buffer_ = nullptr;
59     }
60 
61     tidVec_.clear();
62     prevThreadCpuTimeMap_.clear();
63     prevCoreSystemCpuTimeMap_.clear();
64     prevCoreSystemBootTimeMap_.clear();
65     maxFrequencyVec_.clear();
66     minFrequencyVec_.clear();
67 }
68 
Start(const uint8_t * configData,uint32_t configSize)69 int CpuDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
70 {
71     buffer_ = malloc(READ_BUFFER_SIZE);
72     CHECK_NOTNULL(buffer_, RET_FAIL, "%s:malloc buffer_ failed!", __func__);
73 
74     CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, RET_FAIL,
75                "%s:parseFromArray failed!", __func__);
76 
77     if (protoConfig_.pid() > 0) {
78         pid_ = protoConfig_.pid();
79     } else if (protoConfig_.report_process_info()) {
80         HILOG_INFO(LOG_CORE, "%s:need report process info", __func__);
81     } else {
82         HILOG_ERROR(LOG_CORE, "%s:invalid pid", __func__);
83         return RET_FAIL;
84     }
85     HILOG_INFO(LOG_CORE, "%s:start success!", __func__);
86     return RET_SUCC;
87 }
88 
Report(uint8_t * data,uint32_t dataSize)89 int CpuDataPlugin::Report(uint8_t* data, uint32_t dataSize)
90 {
91     CpuData dataProto;
92     uint32_t length;
93 
94     WriteCpuUsageInfo(dataProto);
95 
96     if (pid_ > 0) {
97         WriteThreadInfo(dataProto);
98     }
99     if (protoConfig_.report_process_info()) {
100         WriteProcnum(dataProto);
101     }
102 
103     length = dataProto.ByteSizeLong();
104     if (length > dataSize) {
105         return -length;
106     }
107     if (dataProto.SerializeToArray(data, length) > 0) {
108         return length;
109     }
110     return 0;
111 }
112 
WriteProcnum(CpuData & data)113 bool CpuDataPlugin::WriteProcnum(CpuData& data)
114 {
115     DIR* procDir = nullptr;
116     procDir = OpenDestDir(path_);
117     if (procDir == nullptr) {
118         return false;
119     }
120 
121     uint32_t i = 0;
122     while (int32_t tid = GetValidTid(procDir)) {
123         if (tid <= 0) {
124             closedir(procDir);
125             HILOG_WARN(LOG_CORE, "%s: get pid[%d] failed", __func__, tid);
126             return false;
127         }
128         i++;
129     }
130     data.set_process_num(i);
131     closedir(procDir);
132 
133     return true;
134 }
135 
Stop()136 int CpuDataPlugin::Stop()
137 {
138     if (buffer_ != nullptr) {
139         free(buffer_);
140         buffer_ = nullptr;
141     }
142 
143     tidVec_.clear();
144     prevThreadCpuTimeMap_.clear();
145     prevCoreSystemCpuTimeMap_.clear();
146     prevCoreSystemBootTimeMap_.clear();
147     HILOG_INFO(LOG_CORE, "%s:stop success!", __func__);
148     return 0;
149 }
150 
ReadFile(std::string & fileName)151 int32_t CpuDataPlugin::ReadFile(std::string& fileName)
152 {
153     int fd = -1;
154     ssize_t bytesRead = 0;
155     char filePath[PATH_MAX + 1] = {0};
156     char realPath[PATH_MAX + 1] = {0};
157 
158     if (snprintf_s(filePath, sizeof(filePath), sizeof(filePath) - 1, "%s", fileName.c_str()) < 0) {
159         const int bufSize = 256;
160         char buf[bufSize] = { 0 };
161         strerror_r(errno, buf, bufSize);
162         HILOG_ERROR(LOG_CORE, "snprintf_s(%s) error, errno(%d:%s)", fileName.c_str(), errno, buf);
163         return RET_FAIL;
164     }
165     if (realpath(filePath, realPath) == nullptr) {
166         const int bufSize = 256;
167         char buf[bufSize] = { 0 };
168         strerror_r(errno, buf, bufSize);
169         HILOG_ERROR(LOG_CORE, "realpath(%s) failed, errno(%d:%s)", fileName.c_str(), errno, buf);
170         return RET_FAIL;
171     }
172 
173     fd = open(realPath, O_RDONLY | O_CLOEXEC);
174     if (fd == -1) {
175         const int bufSize = 256;
176         char buf[bufSize] = { 0 };
177         strerror_r(errno, buf, bufSize);
178         HILOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, realPath, errno, buf);
179         err_ = errno;
180         return RET_FAIL;
181     }
182     if (buffer_ == nullptr) {
183         HILOG_ERROR(LOG_CORE, "%s:empty address, buffer_ is NULL", __func__);
184         err_ = RET_NULL_ADDR;
185         close(fd);
186         return RET_FAIL;
187     }
188     bytesRead = read(fd, buffer_, READ_BUFFER_SIZE - 1);
189     if (bytesRead <= 0) {
190         close(fd);
191         HILOG_ERROR(LOG_CORE, "%s:failed to read(%s), errno=%d", __func__, realPath, errno);
192         err_ = errno;
193         return RET_FAIL;
194     }
195     close(fd);
196 
197     return bytesRead;
198 }
199 
SetTimestamp(SampleTimeStamp & timestamp)200 void CpuDataPlugin::SetTimestamp(SampleTimeStamp& timestamp)
201 {
202     timespec time;
203     clock_gettime(CLOCK_MONOTONIC, &time);
204     timestamp.set_tv_sec(time.tv_sec);
205     timestamp.set_tv_nsec(time.tv_nsec);
206 }
207 
GetUserHz()208 int64_t CpuDataPlugin::GetUserHz()
209 {
210     int64_t hz = -1;
211     int64_t user_hz = sysconf(_SC_CLK_TCK);
212     switch (user_hz) {
213         case CPU_USER_HZ_L:
214             hz = CPU_HZ_H;
215             break;
216         case CPU_USER_HZ_H:
217             hz = 1;
218             break;
219         default:
220             break;
221     }
222     return hz;
223 }
224 
GetCpuUsageTime(std::vector<std::string> & cpuUsageVec)225 int64_t CpuDataPlugin::GetCpuUsageTime(std::vector<std::string>& cpuUsageVec)
226 {
227     int64_t utime = 0;
228     int64_t stime = 0;
229     int64_t usageTime = 0;
230     utime = atoi(cpuUsageVec[PROCESS_UTIME].c_str());
231     stime = atoi(cpuUsageVec[PROCESS_STIME].c_str());
232     // 进程,线程CPU占用率只计算utime(用户态时间),stime(核心态时间)
233     usageTime = (utime + stime) * GetUserHz();
234 
235     return usageTime;
236 }
237 
WriteProcessCpuUsage(CpuUsageInfo & cpuUsageInfo,const char * pFile,uint32_t fileLen)238 void CpuDataPlugin::WriteProcessCpuUsage(CpuUsageInfo& cpuUsageInfo, const char* pFile, uint32_t fileLen)
239 {
240     BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
241     std::vector<std::string> cpuUsageVec;
242     for (int i = 0; i < STAT_COUNT; i++) {
243         totalbuffer.NextWord(' ');
244         if (!totalbuffer.CurWord()) {
245             return;
246         }
247 
248         if (i < STAT_START) {
249             continue;
250         } else {
251             std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
252             cpuUsageVec.push_back(curWord);
253         }
254     }
255 
256     // 获取到的数据不包含utime、stime、cutime、cstime四个数值时返回
257     if (cpuUsageVec.size() != PROCESS_UNSPECIFIED) {
258         HILOG_ERROR(LOG_CORE, "%s:failed to get process cpu usage, size=%zu", __func__, cpuUsageVec.size());
259         return;
260     }
261 
262     int64_t usageTime = GetCpuUsageTime(cpuUsageVec);
263     cpuUsageInfo.set_prev_process_cpu_time_ms(prevProcessCpuTime_);
264     cpuUsageInfo.set_process_cpu_time_ms(usageTime);
265     prevProcessCpuTime_ = usageTime;
266 }
267 
GetCpuFrequency(std::string fileName)268 int32_t CpuDataPlugin::GetCpuFrequency(std::string fileName)
269 {
270     int32_t frequency = 0;
271     int32_t ret = ReadFile(fileName);
272     if (ret != RET_FAIL) {
273         frequency = atoi((char*)buffer_);
274     }
275     return frequency;
276 }
277 
GetCpuCoreSize()278 int CpuDataPlugin::GetCpuCoreSize()
279 {
280     int coreSize = 0;
281     DIR* procDir = nullptr;
282     procDir = OpenDestDir(freqPath_);
283     CHECK_NOTNULL(procDir, -1, "procDir is nullptr");
284 
285     while (struct dirent* dirEnt = readdir(procDir)) {
286         if (dirEnt->d_type != DT_DIR) {
287             continue;
288         }
289         if (strncmp(dirEnt->d_name, "cpu", strlen("cpu")) == 0) {
290             coreSize++;
291         }
292     }
293     closedir(procDir);
294     return coreSize;
295 }
296 
GetMaxCpuFrequencyIndex()297 int32_t CpuDataPlugin::GetMaxCpuFrequencyIndex()
298 {
299     int coreSize = GetCpuCoreSize();
300     int index = -1;
301     int32_t maxFreq = -1;
302     maxFrequencyVec_.clear();
303     minFrequencyVec_.clear();
304     for (int i = 0; i < coreSize; i++) {
305         std::string fileName = freqPath_ + "/cpu" + std::to_string(i) + FREQUENCY_MAX_PATH;
306         int32_t maxFrequency = GetCpuFrequency(fileName);
307         maxFrequencyVec_.push_back(maxFrequency);
308         fileName = freqPath_ + "/cpu" + std::to_string(i) + FREQUENCY_MIN_PATH;
309         int32_t minFrequency = GetCpuFrequency(fileName);
310         minFrequencyVec_.push_back(minFrequency);
311 
312         if (maxFreq < maxFrequency) {
313             maxFreq = maxFrequency;
314             index = i;
315         }
316     }
317 
318     // 单核或所有核最大频率相同,默认小核
319     if (coreSize == 1 || (coreSize > 1 && index == 0 && maxFreq == maxFrequencyVec_[1])) {
320         index = -1;
321     }
322 
323     return index;
324 }
325 
SetCpuFrequency(CpuCoreUsageInfo & cpuCore,int32_t coreNum)326 void CpuDataPlugin::SetCpuFrequency(CpuCoreUsageInfo& cpuCore, int32_t coreNum)
327 {
328     // 第一次获取最大频率核位置,并保存各核最大最小频率到vector
329     if (maxFrequencyVec_.empty() || minFrequencyVec_.empty()) {
330         maxFreqIndex_ = GetMaxCpuFrequencyIndex();
331     }
332     std::string fileName = freqPath_ + "/cpu" + std::to_string(coreNum) + FREQUENCY_CUR_PATH;
333     int32_t curFrequency = GetCpuFrequency(fileName);
334     int32_t maxFrequency = maxFrequencyVec_[coreNum];
335     int32_t minFrequency = minFrequencyVec_[coreNum];
336 
337     if (coreNum == maxFreqIndex_) {
338         cpuCore.set_is_little_core(false);
339     } else {
340         cpuCore.set_is_little_core(true);
341     }
342     CpuCoreFrequency* frequency = cpuCore.mutable_frequency();
343     frequency->set_min_frequency_khz(minFrequency);
344     frequency->set_max_frequency_khz(maxFrequency);
345     frequency->set_cur_frequency_khz(curFrequency);
346 }
347 
GetSystemCpuTime(std::vector<std::string> & cpuUsageVec,CpuTimeData & cpuTimeData)348 bool CpuDataPlugin::GetSystemCpuTime(std::vector<std::string>& cpuUsageVec, CpuTimeData& cpuTimeData)
349 {
350     // 获取到的数据不包含user, nice, system, idle, iowait, irq, softirq, steal八个数值时返回
351     CHECK_TRUE(cpuUsageVec.size() == SYSTEM_UNSPECIFIED, false,
352                "%s:failed to get system cpu usage, size=%zu", __func__, cpuUsageVec.size());
353 
354     int64_t user = 0;
355     int64_t nice = 0;
356     int64_t system = 0;
357     int64_t idle = 0;
358     int64_t iowait = 0;
359     int64_t irq = 0;
360     int64_t softirq = 0;
361     int64_t steal = 0;
362     user = atoi(cpuUsageVec[SYSTEM_USER].c_str());
363     nice = atoi(cpuUsageVec[SYSTEM_NICE].c_str());
364     system = atoi(cpuUsageVec[SYSTEM_SYSTEM].c_str());
365     idle = atoi(cpuUsageVec[SYSTEM_IDLE].c_str());
366     iowait = atoi(cpuUsageVec[SYSTEM_IOWAIT].c_str());
367     irq = atoi(cpuUsageVec[SYSTEM_IRQ].c_str());
368     softirq = atoi(cpuUsageVec[SYSTEM_SOFTIRQ].c_str());
369     steal = atoi(cpuUsageVec[SYSTEM_STEAL].c_str());
370 
371     cpuTimeData.userModeUsageTime = user * GetUserHz();
372     cpuTimeData.systemModeUsageTime = system * GetUserHz();
373     cpuTimeData.systemUsageTime = (user + nice + system + irq + softirq + steal) * GetUserHz();
374     cpuTimeData.systemBootTime = cpuTimeData.systemUsageTime + (idle + iowait) * GetUserHz();
375     return true;
376 }
377 
WriteSystemCpuUsage(CpuData & cpuData,const char * pFile,uint32_t fileLen)378 void CpuDataPlugin::WriteSystemCpuUsage(CpuData& cpuData, const char* pFile, uint32_t fileLen)
379 {
380     auto* cpuUsageInfo = cpuData.mutable_cpu_usage_info();
381     BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
382     std::vector<std::string> cpuUsageVec;
383     size_t cpuLength = strlen("cpu");
384 
385     do {
386         totalbuffer.NextWord(' ');
387         if (!totalbuffer.CurWord() || strncmp(totalbuffer.CurWord(), "cpu", cpuLength) != 0) {
388             return;
389         }
390 
391         for (int i = 0; i < SYSTEM_STAT_COUNT; i++) {
392             if (!totalbuffer.CurWord()) {
393                 return;
394             }
395             std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
396             cpuUsageVec.push_back(curWord);
397             totalbuffer.NextWord(' ');
398         }
399 
400         // 获取数据失败返回
401         CpuTimeData cpuTimeData;
402         if (!GetSystemCpuTime(cpuUsageVec, cpuTimeData)) {
403             return;
404         }
405 
406         if (strcmp(cpuUsageVec[0].c_str(), "cpu") == 0) {
407             cpuUsageInfo->set_prev_system_cpu_time_ms(prevCpuTimeData_.systemUsageTime);
408             cpuUsageInfo->set_prev_system_boot_time_ms(prevCpuTimeData_.systemBootTime);
409             cpuUsageInfo->set_system_cpu_time_ms(cpuTimeData.systemUsageTime);
410             cpuUsageInfo->set_system_boot_time_ms(cpuTimeData.systemBootTime);
411             bool isTest = false;
412             if (strncmp(path_.c_str(), "/proc/", strlen("/proc/")) != 0) {
413                 isTest = true; // UT needs report load data for the first time
414             }
415             if ((protoConfig_.report_process_info() && prevCpuTimeData_.systemBootTime != 0) || isTest) {
416                 double userLoad = static_cast<double>(cpuTimeData.userModeUsageTime -
417                     prevCpuTimeData_.userModeUsageTime) /
418                     static_cast<double>(cpuTimeData.systemBootTime -
419                     prevCpuTimeData_.systemBootTime) * PERCENT;
420                 double sysLoad = static_cast<double>(cpuTimeData.systemModeUsageTime -
421                     prevCpuTimeData_.systemModeUsageTime) /
422                     static_cast<double>(cpuTimeData.systemBootTime -
423                     prevCpuTimeData_.systemBootTime) * PERCENT;
424                 double totalLoad = static_cast<double>(cpuTimeData.systemUsageTime -
425                     prevCpuTimeData_.systemUsageTime) /
426                     static_cast<double>(cpuTimeData.systemBootTime -
427                     prevCpuTimeData_.systemBootTime) * PERCENT;
428                 cpuData.set_user_load(userLoad);
429                 cpuData.set_sys_load(sysLoad);
430                 cpuData.set_total_load(totalLoad);
431             }
432             prevCpuTimeData_ = cpuTimeData;
433             if (pid_ < 0 && protoConfig_.report_process_info()) {
434                 return;
435             }
436         } else {
437             std::string core = std::string(cpuUsageVec[0].c_str() + cpuLength, cpuUsageVec[0].size() - cpuLength);
438             int32_t coreNum = atoi(core.c_str());
439             // 第一次获取数据时需要将前一个数据置为0
440             if (prevCoreSystemCpuTimeMap_.size() == static_cast<size_t>(coreNum)) {
441                 prevCoreSystemCpuTimeMap_[coreNum] = 0;
442                 prevCoreSystemBootTimeMap_[coreNum] = 0;
443             }
444             CpuCoreUsageInfo* cpuCore = cpuUsageInfo->add_cores();
445             cpuCore->set_cpu_core(coreNum);
446             cpuCore->set_prev_system_cpu_time_ms(prevCoreSystemCpuTimeMap_[coreNum]);
447             cpuCore->set_prev_system_boot_time_ms(prevCoreSystemBootTimeMap_[coreNum]);
448             cpuCore->set_system_cpu_time_ms(cpuTimeData.systemUsageTime);
449             cpuCore->set_system_boot_time_ms(cpuTimeData.systemBootTime);
450 
451             SetCpuFrequency(*cpuCore, coreNum);
452             prevCoreSystemCpuTimeMap_[coreNum] = cpuTimeData.systemUsageTime;
453             prevCoreSystemBootTimeMap_[coreNum] = cpuTimeData.systemBootTime;
454         }
455 
456         cpuUsageVec.clear();
457     } while (totalbuffer.NextLine());
458 }
459 
WriteCpuUsageInfo(CpuData & data)460 void CpuDataPlugin::WriteCpuUsageInfo(CpuData& data)
461 {
462     // write process info
463     if (pid_ > 0) {
464         std::string fileName = path_ + std::to_string(pid_) + "/stat";
465         int32_t ret = ReadFile(fileName);
466         if (ret == RET_FAIL) {
467             return;
468         }
469         if ((buffer_ == nullptr) || (ret == 0)) {
470             return;
471         }
472 
473         auto* cpuUsageInfo = data.mutable_cpu_usage_info();
474         WriteProcessCpuUsage(*cpuUsageInfo, (char*)buffer_, ret);
475     }
476 
477     // write system info
478     std::string fileName = path_ + "stat";
479     int32_t ret = ReadFile(fileName);
480     if (ret == RET_FAIL) {
481         return;
482     }
483     if ((buffer_ == nullptr) || (ret == 0)) {
484         return;
485     }
486     WriteSystemCpuUsage(data, (char*)buffer_, ret);
487 
488     auto* timestamp = data.mutable_cpu_usage_info()->mutable_timestamp();
489     SetTimestamp(*timestamp);
490 }
491 
addTidBySort(int32_t tid)492 bool CpuDataPlugin::addTidBySort(int32_t tid)
493 {
494     auto tidsEnd = tidVec_.end();
495     auto it = std::lower_bound(tidVec_.begin(), tidsEnd, tid);
496     CHECK_TRUE(!(it != tidsEnd && *it == tid), false, "addTidBySort failed");
497     it = tidVec_.insert(it, std::move(tid));
498     return true;
499 }
500 
OpenDestDir(std::string & dirPath)501 DIR* CpuDataPlugin::OpenDestDir(std::string& dirPath)
502 {
503     DIR* destDir = nullptr;
504 
505     destDir = opendir(dirPath.c_str());
506     CHECK_NOTNULL(destDir, nullptr, "%s:failed to opendir(%s), errno=%d", __func__, dirPath.c_str(), errno);
507 
508     return destDir;
509 }
510 
GetValidTid(DIR * dirp)511 int32_t CpuDataPlugin::GetValidTid(DIR* dirp)
512 {
513     CHECK_TRUE(dirp, 0, "dirp is nullptr");
514     while (struct dirent* dirEnt = readdir(dirp)) {
515         if (dirEnt->d_type != DT_DIR) {
516             continue;
517         }
518 
519         int32_t tid = atoi(dirEnt->d_name);
520         if (tid) {
521             return tid;
522         }
523     }
524     return 0;
525 }
526 
GetThreadState(const char threadState)527 ThreadState CpuDataPlugin::GetThreadState(const char threadState)
528 {
529     ThreadState state = THREAD_UNSPECIFIED;
530     switch (threadState) {
531         case 'R':
532             state = THREAD_RUNNING;
533             break;
534         case 'S':
535             state = THREAD_SLEEPING;
536             break;
537         case 'T':
538             state = THREAD_STOPPED;
539             break;
540         case 'D':
541             state = THREAD_WAITING;
542             break;
543         default:
544             break;
545     }
546 
547     return state;
548 }
549 
WriteThread(ThreadInfo & threadInfo,const char * pFile,uint32_t fileLen,int32_t tid)550 void CpuDataPlugin::WriteThread(ThreadInfo& threadInfo, const char* pFile, uint32_t fileLen, int32_t tid)
551 {
552     BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
553     std::vector<std::string> cpuUsageVec;
554     for (int i = 0; i < STAT_COUNT; i++) {
555         if (i == THREAD_NAME_POS) { // 线程名是')'作为结束符
556             totalbuffer.NextWord(')');
557         } else {
558             totalbuffer.NextWord(' ');
559         }
560 
561         if (!totalbuffer.CurWord()) {
562             return;
563         }
564 
565         if (i == THREAD_NAME_POS) {
566             std::string curWord = std::string(totalbuffer.CurWord() + 1, totalbuffer.CurWordSize() - 1);
567             threadInfo.set_thread_name(curWord);
568         } else if (i == THREAD_STATE_POS) {
569             std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
570             ThreadState state = GetThreadState(curWord[0]);
571             threadInfo.set_thread_state(state);
572         } else if (i >= STAT_START) {
573             std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
574             cpuUsageVec.push_back(curWord);
575         }
576     }
577 
578     // 获取到的数据不包含utime、stime、cutime、cstime四个数值时返回
579     if (cpuUsageVec.size() != PROCESS_UNSPECIFIED) {
580         HILOG_ERROR(LOG_CORE, "%s:failed to get thread cpu usage, size=%zu", __func__, cpuUsageVec.size());
581         return;
582     }
583 
584     // 第一次获取该线程数据时需要将前一个数据置为0
585     if (prevThreadCpuTimeMap_.find(tid) == prevThreadCpuTimeMap_.end()) {
586         prevThreadCpuTimeMap_[tid] = 0;
587     }
588 
589     int64_t usageTime = GetCpuUsageTime(cpuUsageVec);
590     threadInfo.set_prev_thread_cpu_time_ms(prevThreadCpuTimeMap_[tid]);
591     threadInfo.set_thread_cpu_time_ms(usageTime);
592     prevThreadCpuTimeMap_[tid] = usageTime;
593     threadInfo.set_tid(tid);
594 
595     auto* timestamp = threadInfo.mutable_timestamp();
596     SetTimestamp(*timestamp);
597 }
598 
WriteSingleThreadInfo(CpuData & data,int32_t tid)599 void CpuDataPlugin::WriteSingleThreadInfo(CpuData& data, int32_t tid)
600 {
601     std::string fileName = path_ + std::to_string(pid_) + "/task/" + std::to_string(tid) + "/stat";
602     int32_t ret = ReadFile(fileName);
603     if (ret == RET_FAIL) {
604         return;
605     }
606     if ((buffer_ == nullptr) || (ret == 0)) {
607         return;
608     }
609     auto* threadInfo = data.add_thread_info();
610     WriteThread(*threadInfo, (char*)buffer_, ret, tid);
611 }
612 
WriteThreadInfo(CpuData & data)613 void CpuDataPlugin::WriteThreadInfo(CpuData& data)
614 {
615     DIR* procDir = nullptr;
616     std::string path = path_ + std::to_string(pid_) + "/task";
617     procDir = OpenDestDir(path);
618     if (procDir == nullptr) {
619         return;
620     }
621 
622     tidVec_.clear();
623     while (int32_t tid = GetValidTid(procDir)) {
624         addTidBySort(tid);
625     }
626 
627     for (unsigned int i = 0; i < tidVec_.size(); i++) {
628         WriteSingleThreadInfo(data, tidVec_[i]);
629     }
630     closedir(procDir);
631 }
632 
633 // for UT
SetFreqPath(std::string path)634 void CpuDataPlugin::SetFreqPath(std::string path)
635 {
636     freqPath_ = path + FREQUENCY_PATH;
637 }
638