• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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  * Description: FlowController implements
16  */
17 #include "flow_controller.h"
18 
19 #include <algorithm>
20 #include <cinttypes>
21 #include <set>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <regex>
26 
27 #include "hitrace_ops.h"
28 #include "file_utils.h"
29 #include "ftrace_field_parser.h"
30 #include "ftrace_fs_ops.h"
31 #include "logging.h"
32 
33 namespace {
34 #ifndef PAGE_SIZE
35     constexpr uint32_t PAGE_SIZE = 4096;
36 #endif
37     constexpr int KB_PER_PAGE = PAGE_SIZE / 1024;
38     constexpr uint32_t BYTE_PER_KB = 1024;
39     constexpr uint32_t MAX_FLUSH_INTERVAL = 1800 * 1000;
40     constexpr uint32_t MAX_FLUSH_THRESHOLD = 128 * 1024 * 1024;
41     constexpr uint32_t MAX_TRACE_PERIOD_MS = 720 * 1000;
42     constexpr uint32_t MAX_BUFFER_SIZE_KB = 64 * 1024; // 64MB
43     constexpr uint32_t MIN_BUFFER_SIZE_KB = 1024;      // 1 MB
44     constexpr uint32_t DEFAULT_TRACE_PERIOD_MS = 250;  // 250 ms
45     constexpr uint32_t MAX_BLOCK_SIZE_PAGES = 4096;    // 16 MB
46     constexpr uint32_t MIN_BLOCK_SIZE_PAGES = 256;     // 1  MB
47     constexpr uint32_t PARSE_CMDLINE_COUNT = 1000;
48     const std::set<std::string> g_availableClocks = { "boot", "global", "local", "mono" };
49     constexpr uint32_t SAVED_CMDLINE_SIZE_SMALL = 1024; // save cmdline sizes for cpu num less than 8
50     constexpr uint32_t SAVED_CMDLINE_SIZE_LARGE = 4096; // save cmdline sizes for cpu num no less than 8
51     constexpr int OCTA_CORE_CPU = 8; // 8 core
52 } // namespace
53 
54 FTRACE_NS_BEGIN
GetTraceOps()55 std::unique_ptr<TraceOps> FlowController::GetTraceOps()
56 {
57     std::vector<std::unique_ptr<TraceOps>> traceOps;
58     traceOps.emplace_back(std::make_unique<HitraceOps>());
59 
60     for (size_t i = 0; i < traceOps.size(); i++) {
61         auto& ops = traceOps[i];
62         CHECK_TRUE(ops != nullptr, nullptr, "traceOps[%zu] is null!", i);
63         if (ops->IsSupported()) {
64             return std::move(ops);
65         }
66     }
67     return nullptr;
68 }
69 
FlowController()70 FlowController::FlowController()
71 {
72     ftraceParser_ = std::make_unique<FtraceParser>();
73     ksymsParser_ = std::make_unique<KernelSymbolsParser>();
74     ftraceSupported_ = FtraceFsOps::GetInstance().GetFtraceRoot().size() > 0;
75 }
76 
~FlowController(void)77 FlowController::~FlowController(void)
78 {
79     HILOG_INFO(LOG_CORE, "FlowController destroy!");
80 }
81 
SetWriter(const WriterStructPtr & writer)82 int FlowController::SetWriter(const WriterStructPtr& writer)
83 {
84     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
85     CHECK_TRUE(resultWriter_ == nullptr, 0, "writer already setted!");
86 
87     CHECK_NOTNULL(writer, -1, "writer null!");
88     auto transmiter = std::make_unique<ResultTransporter>("Transporter", writer);
89     CHECK_NOTNULL(transmiter, -1, "create ResultTransporter FAILED!");
90 
91     // get CPU core numbers
92     int nprocs = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
93     CHECK_TRUE(nprocs > 0, -1, "get processor number failed!");
94     platformCpuNum_ = nprocs;
95 
96     auto traceOps = GetTraceOps();
97     CHECK_NOTNULL(traceOps, -1, "get trace ops failed!");
98 
99     // init FtraceParser
100     CHECK_NOTNULL(ftraceParser_, 0, "FtraceParser create FAILED!");
101     CHECK_TRUE(ftraceParser_->Init(), -1, "ftrace parser init failed!");
102 
103     // init KernelSymbolsParser
104     CHECK_NOTNULL(ksymsParser_, 0, "KernelSymbolsParser create FAILED!");
105     ksymsParser_->Parse(FtraceFsOps::GetInstance().GetKernelSymbols());
106 
107     CHECK_TRUE(AddPlatformEventsToParser(), -1, "add platform events to parser failed!");
108     // disable all trace events
109     DisableAllCategories();
110 
111     resultWriter_ = writer;
112     tansporter_ = std::move(transmiter);
113     traceOps_ = std::move(traceOps);
114     return 0;
115 }
116 
CreateRawDataReaders()117 bool FlowController::CreateRawDataReaders()
118 {
119     for (int i = 0; i < platformCpuNum_; i++) {
120         auto reader = std::make_unique<FtraceDataReader>(FtraceFsOps::GetInstance().GetRawTracePath(i));
121         CHECK_NOTNULL(reader, false, "create reader %d FAILED!", i);
122         ftraceReaders_.emplace_back(std::move(reader));
123     }
124     return true;
125 }
126 
CreatePagedMemoryPool()127 bool FlowController::CreatePagedMemoryPool()
128 {
129     HILOG_INFO(LOG_CORE, "create memory pool, buffer_size_kb = %u", bufferSizeKb_);
130     size_t bufferSizePages = bufferSizeKb_ / KB_PER_PAGE;
131     size_t pagesPerBlock = bufferSizePages / static_cast<size_t>(platformCpuNum_);
132     if (pagesPerBlock < MIN_BLOCK_SIZE_PAGES) {
133         pagesPerBlock = MIN_BLOCK_SIZE_PAGES;
134     }
135     if (pagesPerBlock > MAX_BLOCK_SIZE_PAGES) {
136         pagesPerBlock = MAX_BLOCK_SIZE_PAGES;
137     }
138     memPool_ = std::make_unique<PagedMemPool>(pagesPerBlock, platformCpuNum_);
139     CHECK_NOTNULL(memPool_, false, "create PagedMemPool FAILED!");
140     return true;
141 }
142 
CreateRawDataBuffers()143 bool FlowController::CreateRawDataBuffers()
144 {
145     for (int i = 0; i < platformCpuNum_; i++) {
146         using u8ptr = std::unique_ptr<uint8_t>::pointer;
147         auto buffer = std::shared_ptr<uint8_t>(reinterpret_cast<u8ptr>(memPool_->Allocate()),
148             [&](u8ptr block) { this->memPool_->Recycle(block); });
149         CHECK_NOTNULL(buffer, false, "create buffer %d failed!", i);
150         ftraceBuffers_.push_back(buffer);
151     };
152     return true;
153 }
154 
CreateRawDataCaches()155 bool FlowController::CreateRawDataCaches()
156 {
157     char fileName[] = "/data/local/tmp/ftrace_rawdata.XXXXXX";
158     CHECK_TRUE(mkstemp(fileName) >= 0, false, "Create temp file failed!");
159     rawDataFile_ = std::shared_ptr<FILE>(fopen(fileName, "wb+"), [](FILE* fp) { fclose(fp); });
160     unlink(fileName);
161     return true;
162 }
163 
ParseBasicData()164 bool FlowController::ParseBasicData()
165 {
166     // get clock times
167     if (getClockTimes_) {
168         CHECK_TRUE(ReportClockTimes(), -1, "report clock times FAILED!");
169     }
170 
171     // parse kernel symbols
172     if (parseKsyms_) {
173         CHECK_TRUE(ParseKernelSymbols(), -1, "parse kernel symbols FAILED!");
174     }
175 
176     // parse per cpu stats
177     CHECK_TRUE(ParsePerCpuStatus(TRACE_START), -1, "parse TRACE_START stats failed!");
178 
179     return 0;
180 }
181 
StartCapture(void)182 int FlowController::StartCapture(void)
183 {
184     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
185     CHECK_NOTNULL(ftraceParser_, -1, "create FtraceParser FAILED!");
186     CHECK_NOTNULL(ksymsParser_, -1, "create KernelSymbolsParser FAILED!");
187     CHECK_NOTNULL(tansporter_, -1, "crated ResultTransporter FAILED!");
188     CHECK_NOTNULL(traceOps_, -1, "create TraceOps FAILED!");
189 
190     CHECK_TRUE(ParseBasicData() == 0, -1, "parse basic data failed!");
191 
192     // create memory pool, and raw data readers, buffers, caches.
193     CHECK_TRUE(CreatePagedMemoryPool(), -1, "create paged memory pool failed!");
194     CHECK_TRUE(CreateRawDataReaders(), -1, "create raw data readers failed!");
195     CHECK_TRUE(CreateRawDataBuffers(), -1, "create raw data buffers failed!");
196 
197     // clear old trace
198     FtraceFsOps::GetInstance().ClearTraceBuffer();
199 
200     uint32_t savedCmdlinesSize = platformCpuNum_ < OCTA_CORE_CPU ? SAVED_CMDLINE_SIZE_SMALL : SAVED_CMDLINE_SIZE_LARGE;
201     if (!FtraceFsOps::GetInstance().SetSavedCmdLinesSize(savedCmdlinesSize)) {
202         HILOG_ERROR(LOG_CORE, "SetSavedCmdLinesSize %u fail.", savedCmdlinesSize);
203     }
204 
205     // enable additional record options
206     FtraceFsOps::GetInstance().SetRecordCmdOption(true);
207     FtraceFsOps::GetInstance().SetRecordTgidOption(true);
208 
209     // start ftrace event data polling thread
210     keepRunning_ = true;
211 
212     if (parseMode_ == TracePluginConfig_ParseMode_NORMAL) {
213         pollThread_ = std::thread(&FlowController::CaptureWorkOnNomalMode, this);
214     } else if (parseMode_ == TracePluginConfig_ParseMode_DELAY_PARSE) {
215         CHECK_TRUE(CreateRawDataCaches(), -1, "create raw data caches failed!");
216         pollThread_ = std::thread(&FlowController::CaptureWorkOnDelayMode, this);
217     } else {
218         HILOG_ERROR(LOG_CORE, "ParseMode is Illegal parameter!");
219         return -1;
220     }
221 
222     // set trace_clock
223     traceOps_->SetTraceClock(traceClock_);
224     // enable ftrace event switches
225     if (traceCategories_.size() > 0) {
226         traceOps_->EnableCategories(traceCategories_, hitraceTime_);
227     }
228 
229     // hitrace will reset trace buffer size, so reset user config after hitrace
230     FtraceFsOps::GetInstance().SetBufferSizeKb(bufferSizeKb_);
231     EnableTraceEvents();
232     return 0;
233 }
234 
CaptureWorkOnNomalMode()235 void FlowController::CaptureWorkOnNomalMode()
236 {
237     pthread_setname_np(pthread_self(), "TraceReader");
238     HILOG_INFO(LOG_CORE, "FlowController::CaptureWorkOnNomalMode start!");
239 
240     auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
241     std::vector<long> rawDataBytes(platformCpuNum_, 0);
242 
243     while (keepRunning_) {
244         std::this_thread::sleep_for(tracePeriod);
245 
246         // read data from percpu trace_pipe_raw, consume kernel ring buffers
247         for (size_t i = 0; i < rawDataBytes.size(); i++) {
248             if (flushCacheData_ && !keepRunning_) {
249                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
250                 return;
251             }
252             long nbytes = ReadEventData(i);
253             rawDataBytes[i] = nbytes;
254         }
255 
256         // parse ftrace metadata
257         ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
258 
259         // parse ftrace percpu event data
260         for (size_t i = 0; i < rawDataBytes.size(); i++) {
261             if (flushCacheData_ && !keepRunning_) {
262                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
263                 return;
264             }
265             if (rawDataBytes[i] == 0) {
266                 HILOG_INFO(LOG_CORE, "Get raw data from CPU%zu is 0 bytes.", i);
267                 continue;
268             }
269             CHECK_TRUE(ParseEventDataOnNomalMode(i, rawDataBytes[i]), NO_RETVAL, "ParseEventData failed!");
270         }
271     }
272 
273     tansporter_->Flush();
274     HILOG_DEBUG(LOG_CORE, "FlowController::CaptureWorkOnNomalMode done!");
275 }
276 
CaptureWorkOnDelayMode()277 void FlowController::CaptureWorkOnDelayMode()
278 {
279     pthread_setname_np(pthread_self(), "TraceReader");
280     HILOG_INFO(LOG_CORE, "FlowController::CaptureWorkOnDelayMode start!");
281 
282     auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
283     int writeDataCount = 0;
284     while (keepRunning_) {
285         std::this_thread::sleep_for(tracePeriod);
286 
287         // read data from percpu trace_pipe_raw, consume kernel ring buffers
288         for (int cpuIdx = 0; cpuIdx < platformCpuNum_; cpuIdx++) {
289             if (flushCacheData_ && !keepRunning_) {
290                 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
291                 return;
292             }
293             long nbytes = ReadEventData(cpuIdx);
294             if (nbytes == 0) {
295                 HILOG_INFO(LOG_CORE, "Get raw data from CPU%d is 0 bytes.", cpuIdx);
296                 continue;
297             }
298             fwrite(&cpuIdx, sizeof(uint8_t), 1, rawDataFile_.get());
299             fwrite(&nbytes, sizeof(long), 1, rawDataFile_.get());
300             fwrite(ftraceBuffers_[cpuIdx].get(), sizeof(uint8_t), nbytes, rawDataFile_.get());
301         }
302         writeDataCount++;
303         if (writeDataCount == PARSE_CMDLINE_COUNT) {
304             // parse ftrace metadata
305             ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
306             writeDataCount = 0;
307         }
308     }
309 
310     CHECK_TRUE(ParseEventDataOnDelayMode(), NO_RETVAL, "ParseEventData failed!");
311     tansporter_->Flush();
312     HILOG_DEBUG(LOG_CORE, "FlowController::CaptureWorkOnDelayMode done!");
313 }
314 
ReadEventData(int cpuid)315 long FlowController::ReadEventData(int cpuid)
316 {
317     auto buffer = ftraceBuffers_[cpuid].get();
318     auto reader = ftraceReaders_[cpuid].get();
319     auto bufferSize = static_cast<long>(memPool_->GetBlockSize());
320 
321     long nbytes = 0;
322     long used = 0;
323     long rest = bufferSize;
324     while ((nbytes = reader->Read(&buffer[used], rest)) > 0 && used < bufferSize) {
325         CHECK_TRUE(used % PAGE_SIZE == 0, used, "used invalid!");
326         used += nbytes;
327         rest -= nbytes;
328     }
329     return used;
330 }
331 
ParseEventDataOnNomalMode(int cpuid,long dataSize)332 bool FlowController::ParseEventDataOnNomalMode(int cpuid, long dataSize)
333 {
334     auto buffer = ftraceBuffers_[cpuid].get();
335     auto endPtr = buffer + dataSize;
336 
337     for (auto page = buffer; page < endPtr; page += PAGE_SIZE) {
338         CHECK_TRUE(ParseFtraceEvent(cpuid, page), false, "parse raw event for cpu-%d failed!", cpuid);
339     }
340     return true;
341 }
342 
ParseEventDataOnDelayMode()343 bool FlowController::ParseEventDataOnDelayMode()
344 {
345     CHECK_TRUE(fseek(rawDataFile_.get(), 0, SEEK_SET) == 0, false, "fseek failed!");
346     while (!feof(rawDataFile_.get())) {
347         uint8_t cpuId = 0;
348         long dataBytes = 0;
349         fread(&cpuId, sizeof(uint8_t), 1, rawDataFile_.get());
350         fread(&dataBytes, sizeof(long), 1, rawDataFile_.get());
351         for (long i = 0; i < dataBytes; i += PAGE_SIZE) {
352             uint8_t page[PAGE_SIZE] = {0};
353             fread(page, sizeof(uint8_t), PAGE_SIZE, rawDataFile_.get());
354             if (!ParseFtraceEvent(cpuId, page)) {
355                 HILOG_ERROR(LOG_CORE, "ParseFtraceEvent failed!");
356                 return false;
357             }
358         }
359     }
360     return true;
361 }
362 
StopCapture(void)363 int FlowController::StopCapture(void)
364 {
365     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
366     CHECK_NOTNULL(tansporter_, -1, "crate ResultTransporter FAILED!");
367     CHECK_NOTNULL(traceOps_, -1, "create TraceOps FAILED!");
368 
369     if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
370         HILOG_INFO(LOG_CORE, "StopCapture: ftrace event is not set, return false");
371         return -1;
372     }
373 
374     // disable ftrace event switches
375     DisableTraceEvents();
376 
377     // stop ftrace event data polling thread
378     keepRunning_ = false;
379     if (pollThread_.joinable()) {
380         HILOG_INFO(LOG_CORE, "join thread start!\n");
381         pollThread_.join();
382         HILOG_INFO(LOG_CORE, "join thread  done!\n");
383     }
384 
385     // parse per cpu stats
386     CHECK_TRUE(ParsePerCpuStatus(TRACE_END), -1, "parse TRACE_END stats failed!");
387 
388     // disable userspace trace triggers
389     // because trace cmd will read trace buffer,
390     // so we to this action after polling thread exit.
391     if (traceCategories_.size() > 0) {
392         traceOps_->DisableCategories();
393     }
394     tansporter_->Flush();
395 
396     // release resources
397     ftraceReaders_.clear();   // release ftrace data readers
398     ftraceBuffers_.clear();   // release ftrace event read buffers
399     memPool_.reset();         // release memory pool
400     return 0;
401 }
402 
ParsePerCpuStatus(int stage)403 bool FlowController::ParsePerCpuStatus(int stage)
404 {
405     auto tracePacket = std::make_unique<TracePluginResult>();
406     CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
407 
408     auto cpuStatsMsg = tracePacket->add_ftrace_cpu_stats();
409     if (stage == TRACE_START) {
410         cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_START);
411     } else {
412         cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_END);
413     }
414 
415     std::string traceClock = FtraceFsOps::GetInstance().GetTraceClock();
416     if (traceClock.size() > 0) {
417         cpuStatsMsg->set_trace_clock(traceClock);
418     }
419 
420     for (int i = 0; i < platformCpuNum_; i++) {
421         HILOG_INFO(LOG_CORE, "[%d] ParsePerCpuStatus %d!", i, stage);
422         PerCpuStats stats = {};
423         stats.cpuIndex = i;
424         ftraceParser_->ParsePerCpuStatus(stats, FtraceFsOps::GetInstance().GetPerCpuStats(i));
425         auto perCpuMsg = cpuStatsMsg->add_per_cpu_stats();
426         perCpuMsg->set_cpu(stats.cpuIndex);
427         perCpuMsg->set_entries(stats.entries);
428         perCpuMsg->set_overrun(stats.overrun);
429         perCpuMsg->set_commit_overrun(stats.commitOverrun);
430         perCpuMsg->set_bytes(stats.bytes);
431         perCpuMsg->set_oldest_event_ts(stats.oldestEventTs);
432         perCpuMsg->set_now_ts(stats.nowTs);
433         perCpuMsg->set_dropped_events(stats.droppedEvents);
434         perCpuMsg->set_read_events(stats.readEvents);
435     }
436 
437     return tansporter_->Submit(std::move(tracePacket));
438 }
439 
ReportClockTimes()440 bool FlowController::ReportClockTimes()
441 {
442     auto traceResult = std::make_unique<TracePluginResult>();
443     CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
444 
445     std::map<clockid_t, ClockDetailMsg::ClockId> clocksMap = {
446         {CLOCK_REALTIME, ClockDetailMsg::REALTIME},
447         {CLOCK_REALTIME_COARSE, ClockDetailMsg::REALTIME_COARSE},
448         {CLOCK_MONOTONIC, ClockDetailMsg::MONOTONIC},
449         {CLOCK_MONOTONIC_COARSE, ClockDetailMsg::MONOTONIC_COARSE},
450         {CLOCK_MONOTONIC_RAW, ClockDetailMsg::MONOTONIC_RAW},
451         {CLOCK_BOOTTIME, ClockDetailMsg::BOOTTIME},
452     };
453     for (auto& entry : clocksMap) {
454         struct timespec ts = {};
455         clock_gettime(entry.first, &ts);
456         auto clockMsg = traceResult->add_clocks_detail();
457         CHECK_NOTNULL(clockMsg, false, "add clock_detail failed for %d!", entry.first);
458         clockMsg->set_id(entry.second);
459         auto timeMsg = clockMsg->mutable_time();
460         timeMsg->set_tv_sec(ts.tv_sec);
461         timeMsg->set_tv_nsec(ts.tv_nsec);
462 
463         struct timespec tsResolution = {};
464         clock_getres(entry.first, &tsResolution);
465         auto resolutionMsg = clockMsg->mutable_resolution();
466         resolutionMsg->set_tv_sec(tsResolution.tv_sec);
467         resolutionMsg->set_tv_nsec(tsResolution.tv_nsec);
468     }
469     return tansporter_->Submit(std::move(traceResult));
470 }
471 
ParseKernelSymbols()472 bool FlowController::ParseKernelSymbols()
473 {
474     auto traceResult = std::make_unique<TracePluginResult>();
475     CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
476 
477     ksymsParser_->Accept([&traceResult](const KernelSymbol& symbol) {
478         auto symbolDetail = traceResult->add_symbols_detail();
479         symbolDetail->set_symbol_addr(symbol.addr);
480         symbolDetail->set_symbol_name(symbol.name);
481     });
482     HILOG_INFO(LOG_CORE, "parse kernel symbol message done!");
483     return tansporter_->Submit(std::move(traceResult));
484 }
485 
ParseFtraceEvent(int cpuid,uint8_t page[])486 bool FlowController::ParseFtraceEvent(int cpuid, uint8_t page[])
487 {
488     auto tracePacket = std::make_unique<TracePluginResult>();
489     CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
490 
491     auto cpudetail = tracePacket->add_ftrace_cpu_detail();
492     cpudetail->set_cpu(static_cast<uint32_t>(cpuid));
493 
494     CHECK_TRUE(ftraceParser_->ParsePage(*cpudetail, page, PAGE_SIZE), false, "parse page failed!");
495 
496     return tansporter_->Submit(std::move(tracePacket));
497 }
498 
AddPlatformEventsToParser(void)499 bool FlowController::AddPlatformEventsToParser(void)
500 {
501     CHECK_TRUE(ftraceSupported_, false, "current kernel not support ftrace!");
502 
503     HILOG_INFO(LOG_CORE, "Add platform events to parser start!");
504     for (auto& typeName : FtraceFsOps::GetInstance().GetPlatformEvents()) {
505         std::string type = typeName.first;
506         std::string name = typeName.second;
507         if (ftraceParser_->SetupEvent(type, name)) {
508             supportedEvents_.push_back(typeName);
509         }
510     }
511     HILOG_INFO(LOG_CORE, "Add platform events to parser done, events: %zu!", supportedEvents_.size());
512     return true;
513 }
514 
LoadConfig(const uint8_t configData[],uint32_t size)515 int FlowController::LoadConfig(const uint8_t configData[], uint32_t size)
516 {
517     CHECK_TRUE(size > 0, -1, "config data size is zero!");
518     CHECK_NOTNULL(configData, -1, "config data is null!");
519     CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
520     CHECK_NOTNULL(tansporter_, -1, "ResultTransporter crated FAILED!");
521 
522     TracePluginConfig traceConfig;
523     CHECK_TRUE(traceConfig.ParseFromArray(configData, size), -1, "parse %u bytes configData failed!", size);
524 
525     // sort and save user requested trace events
526     std::set<std::string> events(traceConfig.ftrace_events().begin(), traceConfig.ftrace_events().end());
527     for (auto ftraceEvent : events) {
528         requestEvents_.push_back(ftraceEvent);
529     }
530 
531     traceApps_.assign(traceConfig.hitrace_apps().begin(), traceConfig.hitrace_apps().end());
532     traceCategories_.assign(traceConfig.hitrace_categories().begin(), traceConfig.hitrace_categories().end());
533 
534     if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
535         HILOG_INFO(LOG_CORE, "LoadConfig: ftrace event is not set, return false");
536         return -1;
537     }
538 
539     // setup trace clock
540     if (g_availableClocks.count(traceConfig.clock()) > 0) {
541         traceClock_ = traceConfig.clock();
542         FtraceFsOps::GetInstance().SetTraceClock(traceConfig.clock());
543     }
544 
545     // setup parse kernel symbol option
546     parseKsyms_ = traceConfig.parse_ksyms();
547     parseMode_ = traceConfig.parse_mode();
548     // setup trace buffer size
549     SetupTraceBufferSize(traceConfig.buffer_size_kb());
550 
551     // setup transporter flush params
552     SetupTransporterFlushParams(traceConfig.flush_interval_ms(), traceConfig.flush_threshold_kb());
553 
554     // generate raw data file names
555     GenerateRawDataFileNames(traceConfig.raw_data_prefix());
556 
557     // setup trace period param
558     SetupTraceReadPeriod(traceConfig.trace_period_ms());
559     flushCacheData_ = traceConfig.discard_cache_data();
560     hitraceTime_ = traceConfig.hitrace_time();
561     return 0;
562 }
563 
SetupTraceBufferSize(uint32_t sizeKb)564 void FlowController::SetupTraceBufferSize(uint32_t sizeKb)
565 {
566     if (sizeKb < MIN_BUFFER_SIZE_KB) {
567         bufferSizeKb_ = MIN_BUFFER_SIZE_KB;
568     } else if (sizeKb > MAX_BUFFER_SIZE_KB) {
569         bufferSizeKb_ = MAX_BUFFER_SIZE_KB;
570     } else {
571         bufferSizeKb_ = sizeKb / KB_PER_PAGE * KB_PER_PAGE;
572     }
573 }
574 
SetupTransporterFlushParams(uint32_t flushInterval,uint32_t flushThresholdKb)575 void FlowController::SetupTransporterFlushParams(uint32_t flushInterval, uint32_t flushThresholdKb)
576 {
577     if (flushInterval > 0 && flushInterval <= MAX_FLUSH_INTERVAL) {
578         tansporter_->SetFlushInterval(flushInterval);
579     }
580     if (flushThresholdKb > 0 && flushThresholdKb <= MAX_FLUSH_THRESHOLD) {
581         tansporter_->SetFlushThreshold(flushThresholdKb * BYTE_PER_KB);
582     }
583 }
584 
GenerateRawDataFileNames(const std::string & prefix)585 void FlowController::GenerateRawDataFileNames(const std::string& prefix)
586 {
587     if (prefix.size() > 0) {
588         for (int i = 0; i < platformCpuNum_; i++) {
589             std::string path = prefix + std::to_string(i);
590             rawDataDumpPath_.push_back(path);
591         }
592     }
593 }
594 
SetupTraceReadPeriod(uint32_t tracePeriod)595 void FlowController::SetupTraceReadPeriod(uint32_t tracePeriod)
596 {
597     if (tracePeriod > 0 && tracePeriod <= MAX_TRACE_PERIOD_MS) {
598         tracePeriodMs_ = tracePeriod;
599     } else {
600         tracePeriodMs_ = DEFAULT_TRACE_PERIOD_MS;
601     }
602 }
603 
EnableTraceEvents(void)604 void FlowController::EnableTraceEvents(void)
605 {
606     std::unordered_set<std::string> userEventSet(requestEvents_.begin(), requestEvents_.end());
607     for (auto& event : supportedEvents_) {
608         std::string type = event.first;
609         std::string name = event.second;
610         if (userEventSet.count(type + "/" + name)) { // user config format
611             if (FtraceFsOps::GetInstance().EnableEvent(type, name)) {
612                 FtraceFsOps::GetInstance().AppendSetEvent(type, name);
613                 enabledEvents_.push_back(event);
614             }
615         }
616     }
617     FtraceFsOps::GetInstance().EnableTracing();
618 }
619 
DisableTraceEvents(void)620 void FlowController::DisableTraceEvents(void)
621 {
622     FtraceFsOps::GetInstance().DisableTracing();
623     for (auto& event : enabledEvents_) {
624         std::string type = event.first;
625         std::string name = event.second;
626         FtraceFsOps::GetInstance().DisableEvent(type, name);
627     }
628     enabledEvents_.clear();
629 }
630 
DisableAllCategories(void)631 void FlowController::DisableAllCategories(void)
632 {
633     for (auto& event : supportedEvents_) {
634         std::string type = event.first;
635         std::string name = event.second;
636         FtraceFsOps::GetInstance().DisableCategories(type);
637     }
638 }
639 FTRACE_NS_END
640