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