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 // set trace_clock
280 traceOps_->SetTraceClock(traceClock_);
281 // enable ftrace event switches
282 if (traceCategories_.size() > 0) {
283 traceOps_->EnableCategories(traceCategories_, hitraceTime_);
284 }
285
286 // hitrace will reset trace buffer size, so reset user config after hitrace
287 FtraceFsOps::GetInstance().SetBufferSizeKb(bufferSizeKb_);
288 EnableTraceEvents();
289 return 0;
290 }
291
CaptureWork()292 void FlowController::CaptureWork()
293 {
294 pthread_setname_np(pthread_self(), "TraceReader");
295 HILOG_INFO(LOG_CORE, "FlowController::CaptureWork start!");
296
297 auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
298 std::vector<long> rawDataBytes(platformCpuNum_, 0);
299
300 while (keepRunning_) {
301 std::this_thread::sleep_for(tracePeriod);
302
303 // read data from percpu trace_pipe_raw, consume kernel ring buffers
304 for (size_t i = 0; i < rawDataBytes.size(); i++) {
305 if (flushCacheData_ && !keepRunning_) {
306 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
307 return;
308 }
309 long nbytes = ReadEventData(i);
310 rawDataBytes[i] = nbytes;
311 }
312
313 // append buffer data to cache
314 for (size_t i = 0; i < rawDataDumpFile_.size(); i++) {
315 if (flushCacheData_ && !keepRunning_) {
316 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
317 return;
318 }
319 auto& file = rawDataDumpFile_[i];
320 size_t writen = fwrite(ftraceBuffers_[i].get(), sizeof(uint8_t), rawDataBytes[i], file.get());
321 if (rawDataBytes[i] == 0) {
322 HILOG_INFO(LOG_CORE, "Append raw data to cache[%zu]: %zu/%ld bytes", i, writen, rawDataBytes[i]);
323 }
324 }
325
326 // parse ftrace metadata
327 ftraceParser_->ParseSavedTgid(FtraceFsOps::GetInstance().GetSavedTgids());
328 ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
329
330 // parse ftrace percpu event data
331 for (size_t i = 0; i < rawDataBytes.size(); i++) {
332 if (flushCacheData_ && !keepRunning_) {
333 HILOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
334 return;
335 }
336 ParseEventData(i, rawDataBytes[i]);
337 if (rawDataBytes[i] == 0) {
338 HILOG_INFO(LOG_CORE, "Parse raw data for CPU%zu: %ld bytes...", i, rawDataBytes[i]);
339 }
340 }
341 }
342
343 tansporter_->Flush();
344 HILOG_DEBUG(LOG_CORE, "FlowController::CaptureWork done!");
345 }
346
ReadEventData(int cpuid)347 long FlowController::ReadEventData(int cpuid)
348 {
349 auto buffer = ftraceBuffers_[cpuid].get();
350 auto reader = ftraceReaders_[cpuid].get();
351 auto bufferSize = static_cast<long>(memPool_->GetBlockSize());
352 (void)memset_s(buffer, bufferSize, 0, bufferSize);
353
354 long nbytes = 0;
355 long used = 0;
356 long rest = bufferSize;
357 while ((nbytes = reader->Read(&buffer[used], rest)) > 0 && used < bufferSize) {
358 CHECK_TRUE(used % PAGE_SIZE == 0, used, "used invalid!");
359 used += nbytes;
360 rest -= nbytes;
361 }
362 return used;
363 }
364
ParseEventData(int cpuid,long dataSize)365 bool FlowController::ParseEventData(int cpuid, long dataSize)
366 {
367 auto buffer = ftraceBuffers_[cpuid].get();
368 auto endPtr = buffer + dataSize;
369
370 for (auto page = buffer; page < endPtr; page += PAGE_SIZE) {
371 CHECK_TRUE(ParseFtraceEvent(cpuid, page), false, "parse raw event for cpu-%d failed!", cpuid);
372 }
373 return true;
374 }
375
StopCapture(void)376 int FlowController::StopCapture(void)
377 {
378 CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
379 CHECK_NOTNULL(tansporter_, -1, "crate ResultTransporter FAILED!");
380 CHECK_NOTNULL(traceOps_, -1, "create TraceOps FAILED!");
381
382 if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
383 HILOG_INFO(LOG_CORE, "StopCapture: ftrace event is not set, return false");
384 return -1;
385 }
386
387 // disable ftrace event switches
388 DisableTraceEvents();
389
390 // stop ftrace event data polling thread
391 keepRunning_ = false;
392 if (pollThread_.joinable()) {
393 HILOG_INFO(LOG_CORE, "join thread start!\n");
394 pollThread_.join();
395 HILOG_INFO(LOG_CORE, "join thread done!\n");
396 }
397
398 // parse per cpu stats
399 CHECK_TRUE(ParsePerCpuStatus(TRACE_END), -1, "parse TRACE_END stats failed!");
400
401 // disable userspace trace triggers
402 // because trace cmd will read trace buffer,
403 // so we to this action after polling thread exit.
404 if (traceCategories_.size() > 0) {
405 traceOps_->DisableCategories();
406 }
407 tansporter_->Flush();
408
409 // release resources
410 rawDataDumpFile_.clear(); // close raw data dump files
411 ftraceReaders_.clear(); // release ftrace data readers
412 ftraceBuffers_.clear(); // release ftrace event read buffers
413 memPool_.reset(); // release memory pool
414 return 0;
415 }
416
ParsePerCpuStatus(int stage)417 bool FlowController::ParsePerCpuStatus(int stage)
418 {
419 auto tracePacket = std::make_unique<TracePluginResult>();
420 CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
421
422 auto cpuStatsMsg = tracePacket->add_ftrace_cpu_stats();
423 if (stage == TRACE_START) {
424 cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_START);
425 } else {
426 cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_END);
427 }
428
429 std::string traceClock = FtraceFsOps::GetInstance().GetTraceClock();
430 if (traceClock.size() > 0) {
431 cpuStatsMsg->set_trace_clock(traceClock);
432 }
433
434 for (int i = 0; i < platformCpuNum_; i++) {
435 HILOG_INFO(LOG_CORE, "[%d] ParsePerCpuStatus %d!", i, stage);
436 PerCpuStats stats = {};
437 stats.cpuIndex = i;
438 ftraceParser_->ParsePerCpuStatus(stats, FtraceFsOps::GetInstance().GetPerCpuStats(i));
439 auto perCpuMsg = cpuStatsMsg->add_per_cpu_stats();
440 perCpuMsg->set_cpu(stats.cpuIndex);
441 perCpuMsg->set_entries(stats.entries);
442 perCpuMsg->set_overrun(stats.overrun);
443 perCpuMsg->set_commit_overrun(stats.commitOverrun);
444 perCpuMsg->set_bytes(stats.bytes);
445 perCpuMsg->set_oldest_event_ts(stats.oldestEventTs);
446 perCpuMsg->set_now_ts(stats.nowTs);
447 perCpuMsg->set_dropped_events(stats.droppedEvents);
448 perCpuMsg->set_read_events(stats.readEvents);
449 }
450
451 return tansporter_->Submit(std::move(tracePacket));
452 }
453
ReportClockTimes()454 bool FlowController::ReportClockTimes()
455 {
456 auto traceResult = std::make_unique<TracePluginResult>();
457 CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
458
459 std::map<clockid_t, ClockDetailMsg::ClockId> clocksMap = {
460 {CLOCK_REALTIME, ClockDetailMsg::REALTIME},
461 {CLOCK_REALTIME_COARSE, ClockDetailMsg::REALTIME_COARSE},
462 {CLOCK_MONOTONIC, ClockDetailMsg::MONOTONIC},
463 {CLOCK_MONOTONIC_COARSE, ClockDetailMsg::MONOTONIC_COARSE},
464 {CLOCK_MONOTONIC_RAW, ClockDetailMsg::MONOTONIC_RAW},
465 {CLOCK_BOOTTIME, ClockDetailMsg::BOOTTIME},
466 };
467 for (auto& entry : clocksMap) {
468 struct timespec ts = {};
469 clock_gettime(entry.first, &ts);
470 auto clockMsg = traceResult->add_clocks_detail();
471 CHECK_NOTNULL(clockMsg, false, "add clock_detail failed for %d!", entry.first);
472 clockMsg->set_id(entry.second);
473 auto timeMsg = clockMsg->mutable_time();
474 timeMsg->set_tv_sec(ts.tv_sec);
475 timeMsg->set_tv_nsec(ts.tv_nsec);
476
477 struct timespec tsResolution = {};
478 clock_getres(entry.first, &tsResolution);
479 auto resolutionMsg = clockMsg->mutable_resolution();
480 resolutionMsg->set_tv_sec(tsResolution.tv_sec);
481 resolutionMsg->set_tv_nsec(tsResolution.tv_nsec);
482 }
483 return tansporter_->Submit(std::move(traceResult));
484 }
485
ParseKernelSymbols()486 bool FlowController::ParseKernelSymbols()
487 {
488 auto traceResult = std::make_unique<TracePluginResult>();
489 CHECK_NOTNULL(traceResult, false, "create TracePluginResult FAILED!");
490
491 ksymsParser_->Accept([&traceResult](const KernelSymbol& symbol) {
492 auto symbolDetail = traceResult->add_symbols_detail();
493 symbolDetail->set_symbol_addr(symbol.addr);
494 symbolDetail->set_symbol_name(symbol.name);
495 });
496 HILOG_INFO(LOG_CORE, "parse kernel symbol message done!");
497 return tansporter_->Submit(std::move(traceResult));
498 }
499
ParseFtraceEvent(int cpuid,uint8_t page[])500 bool FlowController::ParseFtraceEvent(int cpuid, uint8_t page[])
501 {
502 auto tracePacket = std::make_unique<TracePluginResult>();
503 CHECK_NOTNULL(tracePacket, false, "create TracePluginResult FAILED!");
504
505 auto cpudetail = tracePacket->add_ftrace_cpu_detail();
506 cpudetail->set_cpu(static_cast<uint32_t>(cpuid));
507
508 CHECK_TRUE(ftraceParser_->ParsePage(*cpudetail, page, PAGE_SIZE), false, "parse page failed!");
509
510 return tansporter_->Submit(std::move(tracePacket));
511 }
512
AddPlatformEventsToParser(void)513 bool FlowController::AddPlatformEventsToParser(void)
514 {
515 CHECK_TRUE(ftraceSupported_, false, "current kernel not support ftrace!");
516
517 HILOG_INFO(LOG_CORE, "Add platform events to parser start!");
518 for (auto& typeName : FtraceFsOps::GetInstance().GetPlatformEvents()) {
519 std::string type = typeName.first;
520 std::string name = typeName.second;
521 if (ftraceParser_->SetupEvent(type, name)) {
522 supportedEvents_.push_back(typeName);
523 }
524 }
525 HILOG_INFO(LOG_CORE, "Add platform events to parser done, events: %zu!", supportedEvents_.size());
526 return true;
527 }
528
LoadConfig(const uint8_t configData[],uint32_t size)529 int FlowController::LoadConfig(const uint8_t configData[], uint32_t size)
530 {
531 CHECK_TRUE(size > 0, -1, "config data size is zero!");
532 CHECK_NOTNULL(configData, -1, "config data is null!");
533 CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
534 CHECK_NOTNULL(tansporter_, -1, "ResultTransporter crated FAILED!");
535
536 TracePluginConfig traceConfig;
537 CHECK_TRUE(traceConfig.ParseFromArray(configData, size), -1, "parse %u bytes configData failed!", size);
538
539 // sort and save user requested trace events
540 std::set<std::string> events(traceConfig.ftrace_events().begin(), traceConfig.ftrace_events().end());
541 for (auto ftraceEvent : events) {
542 requestEvents_.push_back(ftraceEvent);
543 }
544
545 traceApps_.assign(traceConfig.hitrace_apps().begin(), traceConfig.hitrace_apps().end());
546 traceCategories_.assign(traceConfig.hitrace_categories().begin(), traceConfig.hitrace_categories().end());
547
548 if (requestEvents_.size() == 0 && traceApps_.size() == 0 && traceCategories_.size() == 0) {
549 HILOG_INFO(LOG_CORE, "LoadConfig: ftrace event is not set, return false");
550 return -1;
551 }
552
553 // setup trace clock
554 if (g_availableClocks.count(traceConfig.clock()) > 0) {
555 traceClock_ = traceConfig.clock();
556 FtraceFsOps::GetInstance().SetTraceClock(traceConfig.clock());
557 }
558
559 // setup parse kernel symbol option
560 parseKsyms_ = traceConfig.parse_ksyms();
561
562 // setup trace buffer size
563 SetupTraceBufferSize(traceConfig.buffer_size_kb());
564
565 // setup transporter flush params
566 SetupTransporterFlushParams(traceConfig.flush_interval_ms(), traceConfig.flush_threshold_kb());
567
568 // generate raw data file names
569 GenerateRawDataFileNames(traceConfig.raw_data_prefix());
570
571 // setup trace period param
572 SetupTraceReadPeriod(traceConfig.trace_period_ms());
573 flushCacheData_ = traceConfig.discard_cache_data();
574 hitraceTime_ = traceConfig.hitrace_time();
575 return 0;
576 }
577
SetupTraceBufferSize(uint32_t sizeKb)578 void FlowController::SetupTraceBufferSize(uint32_t sizeKb)
579 {
580 if (sizeKb < MIN_BUFFER_SIZE_KB) {
581 bufferSizeKb_ = MIN_BUFFER_SIZE_KB;
582 } else if (sizeKb > MAX_BUFFER_SIZE_KB) {
583 bufferSizeKb_ = MAX_BUFFER_SIZE_KB;
584 } else {
585 bufferSizeKb_ = sizeKb / KB_PER_PAGE * KB_PER_PAGE;
586 }
587 }
588
SetupTransporterFlushParams(uint32_t flushInterval,uint32_t flushThresholdKb)589 void FlowController::SetupTransporterFlushParams(uint32_t flushInterval, uint32_t flushThresholdKb)
590 {
591 if (flushInterval > 0 && flushInterval <= MAX_FLUSH_INTERVAL) {
592 tansporter_->SetFlushInterval(flushInterval);
593 }
594 if (flushThresholdKb > 0 && flushThresholdKb <= MAX_FLUSH_THRESHOLD) {
595 tansporter_->SetFlushThreshold(flushThresholdKb * BYTE_PER_KB);
596 }
597 }
598
GenerateRawDataFileNames(const std::string & prefix)599 void FlowController::GenerateRawDataFileNames(const std::string& prefix)
600 {
601 if (prefix.size() > 0) {
602 for (int i = 0; i < platformCpuNum_; i++) {
603 std::string path = prefix + std::to_string(i);
604 rawDataDumpPath_.push_back(path);
605 }
606 }
607 }
608
SetupTraceReadPeriod(uint32_t tracePeriod)609 void FlowController::SetupTraceReadPeriod(uint32_t tracePeriod)
610 {
611 if (tracePeriod > 0 && tracePeriod <= MAX_TRACE_PERIOD_MS) {
612 tracePeriodMs_ = tracePeriod;
613 } else {
614 tracePeriodMs_ = DEFAULT_TRACE_PERIOD_MS;
615 }
616 }
617
EnableTraceEvents(void)618 void FlowController::EnableTraceEvents(void)
619 {
620 std::unordered_set<std::string> userEventSet(requestEvents_.begin(), requestEvents_.end());
621 for (auto& event : supportedEvents_) {
622 std::string type = event.first;
623 std::string name = event.second;
624 if (userEventSet.count(type + "/" + name)) { // user config format
625 if (FtraceFsOps::GetInstance().EnableEvent(type, name)) {
626 FtraceFsOps::GetInstance().AppendSetEvent(type, name);
627 enabledEvents_.push_back(event);
628 }
629 }
630 }
631 FtraceFsOps::GetInstance().EnableTracing();
632 }
633
DisableTraceEvents(void)634 void FlowController::DisableTraceEvents(void)
635 {
636 FtraceFsOps::GetInstance().DisableTracing();
637 for (auto& event : enabledEvents_) {
638 std::string type = event.first;
639 std::string name = event.second;
640 FtraceFsOps::GetInstance().DisableEvent(type, name);
641 }
642 enabledEvents_.clear();
643 }
644
DisableAllCategories(void)645 void FlowController::DisableAllCategories(void)
646 {
647 for (auto& event : supportedEvents_) {
648 std::string type = event.first;
649 std::string name = event.second;
650 FtraceFsOps::GetInstance().DisableCategories(type);
651 }
652 }
653 FTRACE_NS_END
654