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