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