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