106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci *
1506f6ba60Sopenharmony_ci * Description: FlowController implements
1606f6ba60Sopenharmony_ci */
1706f6ba60Sopenharmony_ci#include "flow_controller.h"
1806f6ba60Sopenharmony_ci
1906f6ba60Sopenharmony_ci#include <algorithm>
2006f6ba60Sopenharmony_ci#include <cinttypes>
2106f6ba60Sopenharmony_ci#include <set>
2206f6ba60Sopenharmony_ci#include <sys/stat.h>
2306f6ba60Sopenharmony_ci#include <sys/types.h>
2406f6ba60Sopenharmony_ci#include <unistd.h>
2506f6ba60Sopenharmony_ci#include <regex>
2606f6ba60Sopenharmony_ci
2706f6ba60Sopenharmony_ci#include "file_utils.h"
2806f6ba60Sopenharmony_ci#include "ftrace_field_parser.h"
2906f6ba60Sopenharmony_ci#include "ftrace_fs_ops.h"
3006f6ba60Sopenharmony_ci#include "logging.h"
3106f6ba60Sopenharmony_ci#include "parameters.h"
3206f6ba60Sopenharmony_ci
3306f6ba60Sopenharmony_cinamespace {
3406f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
3506f6ba60Sopenharmony_ci#ifndef PAGE_SIZE
3606f6ba60Sopenharmony_ci    constexpr uint32_t PAGE_SIZE = 4096;
3706f6ba60Sopenharmony_ci#endif
3806f6ba60Sopenharmony_ci    constexpr int KB_PER_PAGE = PAGE_SIZE / 1024;
3906f6ba60Sopenharmony_ci    constexpr uint32_t BYTE_PER_KB = 1024;
4006f6ba60Sopenharmony_ci    constexpr uint32_t MAX_FLUSH_INTERVAL = 1800 * 1000;
4106f6ba60Sopenharmony_ci    constexpr uint32_t MAX_FLUSH_THRESHOLD = 128 * 1024 * 1024;
4206f6ba60Sopenharmony_ci    constexpr uint32_t MAX_TRACE_PERIOD_MS = 720 * 1000;
4306f6ba60Sopenharmony_ci    constexpr uint32_t MAX_BUFFER_SIZE_KB = 64 * 1024; // 64MB
4406f6ba60Sopenharmony_ci    constexpr uint32_t HM_MAX_BUFFER_SIZE_KB = 512 * 1024; // 512MB
4506f6ba60Sopenharmony_ci    constexpr uint32_t MIN_BUFFER_SIZE_KB = 1024;      // 1 MB
4606f6ba60Sopenharmony_ci    constexpr uint32_t DEFAULT_TRACE_PERIOD_MS = 250;  // 250 ms
4706f6ba60Sopenharmony_ci    constexpr uint32_t MAX_BLOCK_SIZE_PAGES = 4096;    // 16 MB
4806f6ba60Sopenharmony_ci    constexpr uint32_t MIN_BLOCK_SIZE_PAGES = 256;     // 1  MB
4906f6ba60Sopenharmony_ci    constexpr uint32_t PARSE_CMDLINE_COUNT = 1000;
5006f6ba60Sopenharmony_ci    const std::set<std::string> g_availableClocks = { "boot", "global", "local", "mono" };
5106f6ba60Sopenharmony_ci    constexpr uint32_t SAVED_CMDLINE_SIZE_SMALL = 1024; // save cmdline sizes for cpu num less than 8
5206f6ba60Sopenharmony_ci    constexpr uint32_t SAVED_CMDLINE_SIZE_LARGE = 4096; // save cmdline sizes for cpu num no less than 8
5306f6ba60Sopenharmony_ci    constexpr int OCTA_CORE_CPU = 8; // 8 core
5406f6ba60Sopenharmony_ci    constexpr unsigned int RMQ_ENTRY_ALIGN_MASK = (1U << 2) - 1;
5506f6ba60Sopenharmony_ci    const std::string TRACE_PROPERTY = "debug.hitrace.tags.enableflags";
5606f6ba60Sopenharmony_ci    const std::string BGSRV_PROPERTY = "5456538433239656448";
5706f6ba60Sopenharmony_ci} // namespace
5806f6ba60Sopenharmony_ci
5906f6ba60Sopenharmony_ciFTRACE_NS_BEGIN
6006f6ba60Sopenharmony_ciFlowController::FlowController()
6106f6ba60Sopenharmony_ci{
6206f6ba60Sopenharmony_ci    ftraceParser_ = std::make_unique<FtraceParser>();
6306f6ba60Sopenharmony_ci    ksymsParser_ = std::make_unique<KernelSymbolsParser>();
6406f6ba60Sopenharmony_ci    ftraceSupported_ = FtraceFsOps::GetInstance().GetFtraceRoot().size() > 0;
6506f6ba60Sopenharmony_ci    traceCollector_ = OHOS::HiviewDFX::UCollectClient::TraceCollector::Create();
6606f6ba60Sopenharmony_ci}
6706f6ba60Sopenharmony_ci
6806f6ba60Sopenharmony_ciFlowController::~FlowController(void)
6906f6ba60Sopenharmony_ci{
7006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "FlowController destroy!");
7106f6ba60Sopenharmony_ci}
7206f6ba60Sopenharmony_ci
7306f6ba60Sopenharmony_ciint FlowController::SetWriter(const WriterStructPtr& writer)
7406f6ba60Sopenharmony_ci{
7506f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
7606f6ba60Sopenharmony_ci    CHECK_TRUE(resultWriter_ == nullptr, 0, "writer already setted!");
7706f6ba60Sopenharmony_ci
7806f6ba60Sopenharmony_ci    CHECK_NOTNULL(writer, -1, "writer null!");
7906f6ba60Sopenharmony_ci    auto transmiter = std::make_unique<ResultTransporter>("Transporter", writer);
8006f6ba60Sopenharmony_ci    CHECK_NOTNULL(transmiter, -1, "create ResultTransporter FAILED!");
8106f6ba60Sopenharmony_ci
8206f6ba60Sopenharmony_ci    // get CPU core numbers
8306f6ba60Sopenharmony_ci    int nprocs = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
8406f6ba60Sopenharmony_ci    CHECK_TRUE(nprocs > 0, -1, "get processor number failed!");
8506f6ba60Sopenharmony_ci    platformCpuNum_ = nprocs;
8606f6ba60Sopenharmony_ci
8706f6ba60Sopenharmony_ci    // init FtraceParser
8806f6ba60Sopenharmony_ci    CHECK_NOTNULL(ftraceParser_, 0, "FtraceParser create FAILED!");
8906f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceParser_->Init(), -1, "ftrace parser init failed!");
9006f6ba60Sopenharmony_ci
9106f6ba60Sopenharmony_ci    // init KernelSymbolsParser
9206f6ba60Sopenharmony_ci    CHECK_NOTNULL(ksymsParser_, 0, "KernelSymbolsParser create FAILED!");
9306f6ba60Sopenharmony_ci    ksymsParser_->Parse(FtraceFsOps::GetInstance().GetKernelSymbols());
9406f6ba60Sopenharmony_ci
9506f6ba60Sopenharmony_ci    CHECK_TRUE(AddPlatformEventsToParser(), -1, "add platform events to parser failed!");
9606f6ba60Sopenharmony_ci    // disable all trace events
9706f6ba60Sopenharmony_ci    DisableAllCategories();
9806f6ba60Sopenharmony_ci
9906f6ba60Sopenharmony_ci    resultWriter_ = writer;
10006f6ba60Sopenharmony_ci    tansporter_ = std::move(transmiter);
10106f6ba60Sopenharmony_ci    return 0;
10206f6ba60Sopenharmony_ci}
10306f6ba60Sopenharmony_ci
10406f6ba60Sopenharmony_cibool FlowController::CreateRawDataReaders()
10506f6ba60Sopenharmony_ci{
10606f6ba60Sopenharmony_ci    if (FtraceFsOps::GetInstance().IsHmKernel()) {
10706f6ba60Sopenharmony_ci        auto reader = std::make_unique<FtraceDataReader>(FtraceFsOps::GetInstance().GetHmRawTracePath());
10806f6ba60Sopenharmony_ci        CHECK_NOTNULL(reader, false, "create hm raw trace reader FAILED!");
10906f6ba60Sopenharmony_ci        ftraceReaders_.emplace_back(std::move(reader));
11006f6ba60Sopenharmony_ci        return true;
11106f6ba60Sopenharmony_ci    }
11206f6ba60Sopenharmony_ci
11306f6ba60Sopenharmony_ci    for (int i = 0; i < platformCpuNum_; i++) {
11406f6ba60Sopenharmony_ci        auto rawPath = FtraceFsOps::GetInstance().GetRawTracePath(i);
11506f6ba60Sopenharmony_ci        if (fakePath_ != "") {
11606f6ba60Sopenharmony_ci            rawPath = fakePath_ + "test_raw_" + std::to_string(i);
11706f6ba60Sopenharmony_ci            CHECK_NOTNULL(ftraceParser_, false, "create FtraceParser FAILED!");
11806f6ba60Sopenharmony_ci            ftraceParser_->ParseSavedCmdlines(FileUtils::ReadFile(fakePath_ + "test_comm"));
11906f6ba60Sopenharmony_ci            ftraceParser_->ParseSavedTgid(FileUtils::ReadFile(fakePath_ + "test_tgid"));
12006f6ba60Sopenharmony_ci        }
12106f6ba60Sopenharmony_ci        auto reader = std::make_unique<FtraceDataReader>(rawPath);
12206f6ba60Sopenharmony_ci        CHECK_NOTNULL(reader, false, "create reader %d FAILED!", i);
12306f6ba60Sopenharmony_ci        ftraceReaders_.emplace_back(std::move(reader));
12406f6ba60Sopenharmony_ci    }
12506f6ba60Sopenharmony_ci    return true;
12606f6ba60Sopenharmony_ci}
12706f6ba60Sopenharmony_ci
12806f6ba60Sopenharmony_cibool FlowController::CreatePagedMemoryPool()
12906f6ba60Sopenharmony_ci{
13006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "create memory pool, buffer_size_kb = %u", bufferSizeKb_);
13106f6ba60Sopenharmony_ci    if (KB_PER_PAGE == 0 || platformCpuNum_ == 0) {
13206f6ba60Sopenharmony_ci        return false;
13306f6ba60Sopenharmony_ci    }
13406f6ba60Sopenharmony_ci    size_t bufferSizePages = bufferSizeKb_ / KB_PER_PAGE;
13506f6ba60Sopenharmony_ci    size_t pagesPerBlock = bufferSizePages / static_cast<size_t>(platformCpuNum_);
13606f6ba60Sopenharmony_ci    if (pagesPerBlock < MIN_BLOCK_SIZE_PAGES) {
13706f6ba60Sopenharmony_ci        pagesPerBlock = MIN_BLOCK_SIZE_PAGES;
13806f6ba60Sopenharmony_ci    }
13906f6ba60Sopenharmony_ci    if (pagesPerBlock > MAX_BLOCK_SIZE_PAGES) {
14006f6ba60Sopenharmony_ci        pagesPerBlock = MAX_BLOCK_SIZE_PAGES;
14106f6ba60Sopenharmony_ci    }
14206f6ba60Sopenharmony_ci
14306f6ba60Sopenharmony_ci    if (FtraceFsOps::GetInstance().IsHmKernel()) {
14406f6ba60Sopenharmony_ci        memPool_ = std::make_unique<PagedMemPool>(bufferSizePages, 1);
14506f6ba60Sopenharmony_ci    } else {
14606f6ba60Sopenharmony_ci        memPool_ = std::make_unique<PagedMemPool>(pagesPerBlock, platformCpuNum_);
14706f6ba60Sopenharmony_ci    }
14806f6ba60Sopenharmony_ci    CHECK_NOTNULL(memPool_, false, "create PagedMemPool FAILED!");
14906f6ba60Sopenharmony_ci    return true;
15006f6ba60Sopenharmony_ci}
15106f6ba60Sopenharmony_ci
15206f6ba60Sopenharmony_cibool FlowController::CreateRawDataBuffers()
15306f6ba60Sopenharmony_ci{
15406f6ba60Sopenharmony_ci    int num = platformCpuNum_;
15506f6ba60Sopenharmony_ci    if (FtraceFsOps::GetInstance().IsHmKernel()) {
15606f6ba60Sopenharmony_ci        num = 1;
15706f6ba60Sopenharmony_ci    }
15806f6ba60Sopenharmony_ci    for (int i = 0; i < num; i++) {
15906f6ba60Sopenharmony_ci        using u8ptr = std::unique_ptr<uint8_t>::pointer;
16006f6ba60Sopenharmony_ci        auto buffer = std::shared_ptr<uint8_t>(reinterpret_cast<u8ptr>(memPool_->Allocate()),
16106f6ba60Sopenharmony_ci            [&](u8ptr block) { this->memPool_->Recycle(block); });
16206f6ba60Sopenharmony_ci        CHECK_NOTNULL(buffer, false, "create buffer %d failed!", i);
16306f6ba60Sopenharmony_ci        ftraceBuffers_.push_back(buffer);
16406f6ba60Sopenharmony_ci    };
16506f6ba60Sopenharmony_ci    return true;
16606f6ba60Sopenharmony_ci}
16706f6ba60Sopenharmony_ci
16806f6ba60Sopenharmony_cibool FlowController::CreateRawDataCaches()
16906f6ba60Sopenharmony_ci{
17006f6ba60Sopenharmony_ci    char fileName[] = "/data/local/tmp/ftrace_rawdata.XXXXXX";
17106f6ba60Sopenharmony_ci    CHECK_TRUE(mkstemp(fileName) >= 0, false, "Create temp file failed!");
17206f6ba60Sopenharmony_ci    rawDataFile_ = std::shared_ptr<FILE>(fopen(fileName, "wb+"), [](FILE* fp) { fclose(fp); });
17306f6ba60Sopenharmony_ci    unlink(fileName);
17406f6ba60Sopenharmony_ci    return true;
17506f6ba60Sopenharmony_ci}
17606f6ba60Sopenharmony_ci
17706f6ba60Sopenharmony_cibool FlowController::ParseBasicData()
17806f6ba60Sopenharmony_ci{
17906f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_, false, "%s: resultWriter_ nullptr", __func__);
18006f6ba60Sopenharmony_ci    // get clock times
18106f6ba60Sopenharmony_ci    if (getClockTimes_) {
18206f6ba60Sopenharmony_ci        if (resultWriter_->isProtobufSerialize) {
18306f6ba60Sopenharmony_ci            auto traceResult = std::make_unique<TracePluginResult>();
18406f6ba60Sopenharmony_ci            CHECK_TRUE(ReportClockTimes(traceResult), false, "parse clock times FAILED!");
18506f6ba60Sopenharmony_ci            CHECK_TRUE(tansporter_->Submit(std::move(traceResult)), false, "report clock times FAILED!");
18606f6ba60Sopenharmony_ci        } else {
18706f6ba60Sopenharmony_ci            auto ctx = resultWriter_->startReport(resultWriter_);
18806f6ba60Sopenharmony_ci            CHECK_NOTNULL(ctx, false, "%s: get RandomWriteCtx FAILED!", __func__);
18906f6ba60Sopenharmony_ci            auto traceResult = std::make_unique<ProtoEncoder::TracePluginResult>(ctx);
19006f6ba60Sopenharmony_ci            CHECK_TRUE(ReportClockTimes(traceResult), false, "parse clock times FAILED!");
19106f6ba60Sopenharmony_ci            int32_t msgSize = traceResult->Finish();
19206f6ba60Sopenharmony_ci            resultWriter_->finishReport(resultWriter_, msgSize);
19306f6ba60Sopenharmony_ci            tansporter_->Report(static_cast<size_t>(msgSize));
19406f6ba60Sopenharmony_ci        }
19506f6ba60Sopenharmony_ci    }
19606f6ba60Sopenharmony_ci
19706f6ba60Sopenharmony_ci    // parse kernel symbols
19806f6ba60Sopenharmony_ci    if (parseKsyms_) {
19906f6ba60Sopenharmony_ci        if (resultWriter_->isProtobufSerialize) {
20006f6ba60Sopenharmony_ci            auto traceResult = std::make_unique<TracePluginResult>();
20106f6ba60Sopenharmony_ci            CHECK_TRUE(ParseKernelSymbols(traceResult), false, "parse kernel symbols FAILED!");
20206f6ba60Sopenharmony_ci            CHECK_TRUE(tansporter_->Submit(std::move(traceResult)), false, "report kernel symbols FAILED!");
20306f6ba60Sopenharmony_ci        } else {
20406f6ba60Sopenharmony_ci            auto ctx = resultWriter_->startReport(resultWriter_);
20506f6ba60Sopenharmony_ci            CHECK_NOTNULL(ctx, false, "%s: get RandomWriteCtx FAILED!", __func__);
20606f6ba60Sopenharmony_ci            auto traceResult = std::make_unique<ProtoEncoder::TracePluginResult>(ctx);
20706f6ba60Sopenharmony_ci            CHECK_TRUE(ParseKernelSymbols(traceResult), false, "parse kernel symbols FAILED!");
20806f6ba60Sopenharmony_ci            int32_t msgSize = traceResult->Finish();
20906f6ba60Sopenharmony_ci            resultWriter_->finishReport(resultWriter_, msgSize);
21006f6ba60Sopenharmony_ci            tansporter_->Report(static_cast<size_t>(msgSize));
21106f6ba60Sopenharmony_ci        }
21206f6ba60Sopenharmony_ci    }
21306f6ba60Sopenharmony_ci    if (resultWriter_->isProtobufSerialize) {
21406f6ba60Sopenharmony_ci        auto traceResult = std::make_unique<TracePluginResult>();
21506f6ba60Sopenharmony_ci        CHECK_TRUE(ParsePerCpuStatus(traceResult, TRACE_START), false, "parse TRACE_START stats failed!");
21606f6ba60Sopenharmony_ci        CHECK_TRUE(tansporter_->Submit(std::move(traceResult)), false, "report TRACE_START stats failed!");
21706f6ba60Sopenharmony_ci    } else {
21806f6ba60Sopenharmony_ci        auto ctx = resultWriter_->startReport(resultWriter_);
21906f6ba60Sopenharmony_ci        CHECK_NOTNULL(ctx, false, "%s: get RandomWriteCtx FAILED!", __func__);
22006f6ba60Sopenharmony_ci        auto traceResult = std::make_unique<ProtoEncoder::TracePluginResult>(ctx);
22106f6ba60Sopenharmony_ci        CHECK_TRUE(ParsePerCpuStatus(traceResult, TRACE_START), false, "parse TRACE_START stats failed!");
22206f6ba60Sopenharmony_ci        int32_t msgSize = traceResult->Finish();
22306f6ba60Sopenharmony_ci        resultWriter_->finishReport(resultWriter_, msgSize);
22406f6ba60Sopenharmony_ci        tansporter_->Report(static_cast<size_t>(msgSize));
22506f6ba60Sopenharmony_ci    }
22606f6ba60Sopenharmony_ci    return true;
22706f6ba60Sopenharmony_ci}
22806f6ba60Sopenharmony_ci
22906f6ba60Sopenharmony_cistd::string FlowController::ReloadTraceArgs()
23006f6ba60Sopenharmony_ci{
23106f6ba60Sopenharmony_ci    std::string args;
23206f6ba60Sopenharmony_ci    for (size_t i = 0; i < traceCategories_.size(); i++) {
23306f6ba60Sopenharmony_ci        if (i == 0) {
23406f6ba60Sopenharmony_ci            args += ("tags:" + traceCategories_[i]);
23506f6ba60Sopenharmony_ci        } else {
23606f6ba60Sopenharmony_ci            args += ("," + traceCategories_[i]);
23706f6ba60Sopenharmony_ci        }
23806f6ba60Sopenharmony_ci    }
23906f6ba60Sopenharmony_ci
24006f6ba60Sopenharmony_ci    if (traceClock_.size() > 0) {
24106f6ba60Sopenharmony_ci        args += (" clockType:" + traceClock_);
24206f6ba60Sopenharmony_ci    }
24306f6ba60Sopenharmony_ci
24406f6ba60Sopenharmony_ci    if (bufferSizeKb_ > 0) {
24506f6ba60Sopenharmony_ci        args += (" bufferSize:" + std::to_string(bufferSizeKb_));
24606f6ba60Sopenharmony_ci    }
24706f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "trace args: %s", args.c_str());
24806f6ba60Sopenharmony_ci    return args;
24906f6ba60Sopenharmony_ci}
25006f6ba60Sopenharmony_ci
25106f6ba60Sopenharmony_ciint FlowController::StartCapture(void)
25206f6ba60Sopenharmony_ci{
25306f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
25406f6ba60Sopenharmony_ci    CHECK_NOTNULL(ftraceParser_, -1, "create FtraceParser FAILED!");
25506f6ba60Sopenharmony_ci    CHECK_NOTNULL(ksymsParser_, -1, "create KernelSymbolsParser FAILED!");
25606f6ba60Sopenharmony_ci    CHECK_NOTNULL(tansporter_, -1, "create ResultTransporter FAILED!");
25706f6ba60Sopenharmony_ci    CHECK_NOTNULL(traceCollector_, -1, "create TraceCollector FAILED!");
25806f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_, -1, "%s: resultWriter_ nullptr", __func__);
25906f6ba60Sopenharmony_ci
26006f6ba60Sopenharmony_ci    CHECK_TRUE(ParseBasicData(), -1, "parse basic data failed!");
26106f6ba60Sopenharmony_ci
26206f6ba60Sopenharmony_ci    // create memory pool, and raw data readers, buffers, caches.
26306f6ba60Sopenharmony_ci    CHECK_TRUE(CreatePagedMemoryPool(), -1, "create paged memory pool failed!");
26406f6ba60Sopenharmony_ci    CHECK_TRUE(CreateRawDataReaders(), -1, "create raw data readers failed!");
26506f6ba60Sopenharmony_ci    CHECK_TRUE(CreateRawDataBuffers(), -1, "create raw data buffers failed!");
26606f6ba60Sopenharmony_ci
26706f6ba60Sopenharmony_ci    // clear old trace
26806f6ba60Sopenharmony_ci    FtraceFsOps::GetInstance().ClearTraceBuffer();
26906f6ba60Sopenharmony_ci    // recover the hitrace
27006f6ba60Sopenharmony_ci    std::string param = OHOS::system::GetParameter(TRACE_PROPERTY, "");
27106f6ba60Sopenharmony_ci    if (param != "0" && param != BGSRV_PROPERTY) {
27206f6ba60Sopenharmony_ci        traceCollector_->Recover();
27306f6ba60Sopenharmony_ci    }
27406f6ba60Sopenharmony_ci
27506f6ba60Sopenharmony_ci    uint32_t savedCmdlinesSize = platformCpuNum_ < OCTA_CORE_CPU ? SAVED_CMDLINE_SIZE_SMALL : SAVED_CMDLINE_SIZE_LARGE;
27606f6ba60Sopenharmony_ci    if (!FtraceFsOps::GetInstance().SetSavedCmdLinesSize(savedCmdlinesSize)) {
27706f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "SetSavedCmdLinesSize %u fail.", savedCmdlinesSize);
27806f6ba60Sopenharmony_ci    }
27906f6ba60Sopenharmony_ci
28006f6ba60Sopenharmony_ci    // enable additional record options
28106f6ba60Sopenharmony_ci    FtraceFsOps::GetInstance().SetRecordCmdOption(true);
28206f6ba60Sopenharmony_ci    FtraceFsOps::GetInstance().SetRecordTgidOption(true);
28306f6ba60Sopenharmony_ci
28406f6ba60Sopenharmony_ci    // start ftrace event data polling thread
28506f6ba60Sopenharmony_ci    keepRunning_ = true;
28606f6ba60Sopenharmony_ci
28706f6ba60Sopenharmony_ci    if (parseMode_ == TracePluginConfig_ParseMode_NORMAL) {
28806f6ba60Sopenharmony_ci        pollThread_ = std::thread([this] { this->CaptureWorkOnNomalMode(); });
28906f6ba60Sopenharmony_ci    } else if (parseMode_ == TracePluginConfig_ParseMode_DELAY_PARSE) {
29006f6ba60Sopenharmony_ci        CHECK_TRUE(CreateRawDataCaches(), -1, "create raw data caches failed!");
29106f6ba60Sopenharmony_ci        pollThread_ = std::thread([this] { this->CaptureWorkOnDelayMode(); });
29206f6ba60Sopenharmony_ci    } else {
29306f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "ParseMode is Illegal parameter!");
29406f6ba60Sopenharmony_ci        return -1;
29506f6ba60Sopenharmony_ci    }
29606f6ba60Sopenharmony_ci
29706f6ba60Sopenharmony_ci    // set trace_clock and enable all tag categories with hiview::TraceCollector
29806f6ba60Sopenharmony_ci    auto openRet = traceCollector_->OpenRecording(ReloadTraceArgs());
29906f6ba60Sopenharmony_ci    if (openRet.retCode != OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
30006f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "Enable tag categories failed, trace error code is %d!", openRet.retCode);
30106f6ba60Sopenharmony_ci        return -1;
30206f6ba60Sopenharmony_ci    }
30306f6ba60Sopenharmony_ci    EnableTraceEvents();
30406f6ba60Sopenharmony_ci    return 0;
30506f6ba60Sopenharmony_ci}
30606f6ba60Sopenharmony_ci
30706f6ba60Sopenharmony_civoid FlowController::CaptureWorkOnNomalModeInner()
30806f6ba60Sopenharmony_ci{
30906f6ba60Sopenharmony_ci    pthread_setname_np(pthread_self(), "TraceReader");
31006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "FlowController::CaptureWorkOnNomalMode start!");
31106f6ba60Sopenharmony_ci    auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
31206f6ba60Sopenharmony_ci    std::vector<long> rawDataBytes(platformCpuNum_, 0);
31306f6ba60Sopenharmony_ci    while (keepRunning_) {
31406f6ba60Sopenharmony_ci        std::this_thread::sleep_for(tracePeriod);
31506f6ba60Sopenharmony_ci        // read data from percpu trace_pipe_raw, consume kernel ring buffers
31606f6ba60Sopenharmony_ci        for (size_t i = 0; i < rawDataBytes.size(); i++) {
31706f6ba60Sopenharmony_ci            if (flushCacheData_ && !keepRunning_) {
31806f6ba60Sopenharmony_ci                PROFILER_LOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
31906f6ba60Sopenharmony_ci                return;
32006f6ba60Sopenharmony_ci            }
32106f6ba60Sopenharmony_ci            long nbytes = ReadEventData(i);
32206f6ba60Sopenharmony_ci            rawDataBytes[i] = nbytes;
32306f6ba60Sopenharmony_ci        }
32406f6ba60Sopenharmony_ci        // parse ftrace metadata
32506f6ba60Sopenharmony_ci        ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
32606f6ba60Sopenharmony_ci        // parse ftrace percpu event data
32706f6ba60Sopenharmony_ci        for (size_t i = 0; i < rawDataBytes.size(); i++) {
32806f6ba60Sopenharmony_ci            if (flushCacheData_ && !keepRunning_) {
32906f6ba60Sopenharmony_ci                PROFILER_LOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
33006f6ba60Sopenharmony_ci                return;
33106f6ba60Sopenharmony_ci            }
33206f6ba60Sopenharmony_ci            if (rawDataBytes[i] == 0) {
33306f6ba60Sopenharmony_ci                PROFILER_LOG_INFO(LOG_CORE, "Get raw data from CPU%zu is 0 bytes.", i);
33406f6ba60Sopenharmony_ci                continue;
33506f6ba60Sopenharmony_ci            }
33606f6ba60Sopenharmony_ci            if (!ParseEventDataOnNomalMode(i, rawDataBytes[i])) {
33706f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "%s:ParseEventData failed!", __func__);
33806f6ba60Sopenharmony_ci            }
33906f6ba60Sopenharmony_ci        }
34006f6ba60Sopenharmony_ci        if (isReportBasicData_.load()) {
34106f6ba60Sopenharmony_ci            ParseBasicData();
34206f6ba60Sopenharmony_ci            isReportBasicData_ = false;
34306f6ba60Sopenharmony_ci        }
34406f6ba60Sopenharmony_ci    }
34506f6ba60Sopenharmony_ci    tansporter_->Flush();
34606f6ba60Sopenharmony_ci    PROFILER_LOG_DEBUG(LOG_CORE, "FlowController::CaptureWorkOnNomalMode done!");
34706f6ba60Sopenharmony_ci}
34806f6ba60Sopenharmony_ci
34906f6ba60Sopenharmony_cilong FlowController::HmReadEventData()
35006f6ba60Sopenharmony_ci{
35106f6ba60Sopenharmony_ci    auto buffer = ftraceBuffers_[0].get();
35206f6ba60Sopenharmony_ci    auto reader = ftraceReaders_[0].get();
35306f6ba60Sopenharmony_ci    auto bufferSize = static_cast<long>(memPool_->GetBlockSize());
35406f6ba60Sopenharmony_ci
35506f6ba60Sopenharmony_ci    long nbytes = 0;
35606f6ba60Sopenharmony_ci    long used = 0;
35706f6ba60Sopenharmony_ci    long rest = bufferSize;
35806f6ba60Sopenharmony_ci    while ((nbytes = reader->Read(&buffer[used], rest)) > 0 && used < bufferSize) {
35906f6ba60Sopenharmony_ci        used += nbytes;
36006f6ba60Sopenharmony_ci        rest -= nbytes;
36106f6ba60Sopenharmony_ci    }
36206f6ba60Sopenharmony_ci    if (used == bufferSize) {
36306f6ba60Sopenharmony_ci        PROFILER_LOG_WARN(LOG_CORE, "hm trace raw data may overwrite. current buffer size = %u.",
36406f6ba60Sopenharmony_ci                          (unsigned int)bufferSize);
36506f6ba60Sopenharmony_ci    }
36606f6ba60Sopenharmony_ci    return used;
36706f6ba60Sopenharmony_ci}
36806f6ba60Sopenharmony_ci
36906f6ba60Sopenharmony_civoid FlowController::HmCaptureWorkOnNomalModeInner()
37006f6ba60Sopenharmony_ci{
37106f6ba60Sopenharmony_ci    pthread_setname_np(pthread_self(), "HmTraceReader");
37206f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "FlowController::HmCaptureWorkOnNomalMode start!");
37306f6ba60Sopenharmony_ci    auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
37406f6ba60Sopenharmony_ci    while (keepRunning_) {
37506f6ba60Sopenharmony_ci        std::this_thread::sleep_for(tracePeriod);
37606f6ba60Sopenharmony_ci        if (flushCacheData_ && !keepRunning_) {
37706f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
37806f6ba60Sopenharmony_ci            return;
37906f6ba60Sopenharmony_ci        }
38006f6ba60Sopenharmony_ci        long rawDataBytes = HmReadEventData();
38106f6ba60Sopenharmony_ci        ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
38206f6ba60Sopenharmony_ci        if (flushCacheData_ && !keepRunning_) {
38306f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
38406f6ba60Sopenharmony_ci            return;
38506f6ba60Sopenharmony_ci        }
38606f6ba60Sopenharmony_ci        if (rawDataBytes == 0) {
38706f6ba60Sopenharmony_ci            PROFILER_LOG_INFO(LOG_CORE, "Get hm raw data is 0 bytes.");
38806f6ba60Sopenharmony_ci            continue;
38906f6ba60Sopenharmony_ci        }
39006f6ba60Sopenharmony_ci        if (!HmParseEventDataOnNomalMode(rawDataBytes)) {
39106f6ba60Sopenharmony_ci            PROFILER_LOG_ERROR(LOG_CORE, "HmParseEventData failed!");
39206f6ba60Sopenharmony_ci        }
39306f6ba60Sopenharmony_ci    }
39406f6ba60Sopenharmony_ci    tansporter_->Flush();
39506f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "FlowController::HmCaptureWorkOnNomalMode done!");
39606f6ba60Sopenharmony_ci}
39706f6ba60Sopenharmony_ci
39806f6ba60Sopenharmony_civoid FlowController::CaptureWorkOnNomalMode()
39906f6ba60Sopenharmony_ci{
40006f6ba60Sopenharmony_ci    if (FtraceFsOps::GetInstance().IsHmKernel()) {
40106f6ba60Sopenharmony_ci        HmCaptureWorkOnNomalModeInner();
40206f6ba60Sopenharmony_ci    } else {
40306f6ba60Sopenharmony_ci        CaptureWorkOnNomalModeInner();
40406f6ba60Sopenharmony_ci    }
40506f6ba60Sopenharmony_ci}
40606f6ba60Sopenharmony_ci
40706f6ba60Sopenharmony_civoid FlowController::CaptureWorkOnDelayMode()
40806f6ba60Sopenharmony_ci{
40906f6ba60Sopenharmony_ci    pthread_setname_np(pthread_self(), "TraceReader");
41006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "FlowController::CaptureWorkOnDelayMode start!");
41106f6ba60Sopenharmony_ci
41206f6ba60Sopenharmony_ci    auto tracePeriod = std::chrono::milliseconds(tracePeriodMs_);
41306f6ba60Sopenharmony_ci    int writeDataCount = 0;
41406f6ba60Sopenharmony_ci    while (keepRunning_) {
41506f6ba60Sopenharmony_ci        std::this_thread::sleep_for(tracePeriod);
41606f6ba60Sopenharmony_ci
41706f6ba60Sopenharmony_ci        // read data from percpu trace_pipe_raw, consume kernel ring buffers
41806f6ba60Sopenharmony_ci        for (int cpuIdx = 0; cpuIdx < platformCpuNum_; cpuIdx++) {
41906f6ba60Sopenharmony_ci            if (flushCacheData_ && !keepRunning_) {
42006f6ba60Sopenharmony_ci                PROFILER_LOG_INFO(LOG_CORE, "flushCacheData_ is true, return");
42106f6ba60Sopenharmony_ci                return;
42206f6ba60Sopenharmony_ci            }
42306f6ba60Sopenharmony_ci            long nbytes = ReadEventData(cpuIdx);
42406f6ba60Sopenharmony_ci            if (nbytes == 0) {
42506f6ba60Sopenharmony_ci                PROFILER_LOG_INFO(LOG_CORE, "Get raw data from CPU%d is 0 bytes.", cpuIdx);
42606f6ba60Sopenharmony_ci                continue;
42706f6ba60Sopenharmony_ci            }
42806f6ba60Sopenharmony_ci            fwrite(&cpuIdx, sizeof(uint8_t), 1, rawDataFile_.get());
42906f6ba60Sopenharmony_ci            fwrite(&nbytes, sizeof(long), 1, rawDataFile_.get());
43006f6ba60Sopenharmony_ci            fwrite(ftraceBuffers_[cpuIdx].get(), sizeof(uint8_t), nbytes, rawDataFile_.get());
43106f6ba60Sopenharmony_ci        }
43206f6ba60Sopenharmony_ci        writeDataCount++;
43306f6ba60Sopenharmony_ci        if (writeDataCount == PARSE_CMDLINE_COUNT) {
43406f6ba60Sopenharmony_ci            // parse ftrace metadata
43506f6ba60Sopenharmony_ci            ftraceParser_->ParseSavedCmdlines(FtraceFsOps::GetInstance().GetSavedCmdLines());
43606f6ba60Sopenharmony_ci            writeDataCount = 0;
43706f6ba60Sopenharmony_ci        }
43806f6ba60Sopenharmony_ci    }
43906f6ba60Sopenharmony_ci
44006f6ba60Sopenharmony_ci    CHECK_TRUE(ParseEventDataOnDelayMode(), NO_RETVAL, "ParseEventData failed!");
44106f6ba60Sopenharmony_ci    tansporter_->Flush();
44206f6ba60Sopenharmony_ci    PROFILER_LOG_DEBUG(LOG_CORE, "FlowController::CaptureWorkOnDelayMode done!");
44306f6ba60Sopenharmony_ci}
44406f6ba60Sopenharmony_ci
44506f6ba60Sopenharmony_cistatic inline int RmqEntryTotalSize(unsigned int size)
44606f6ba60Sopenharmony_ci{
44706f6ba60Sopenharmony_ci    return sizeof(struct RmqEntry) + ((size + RMQ_ENTRY_ALIGN_MASK) & (~RMQ_ENTRY_ALIGN_MASK));
44806f6ba60Sopenharmony_ci}
44906f6ba60Sopenharmony_ci
45006f6ba60Sopenharmony_citemplate <typename T, typename E>
45106f6ba60Sopenharmony_cibool FlowController::HmParseEventData(T* traceResult, uint8_t*& data, E* ftraceEvent)
45206f6ba60Sopenharmony_ci{
45306f6ba60Sopenharmony_ci    struct RmqConsumerData* rmqData = reinterpret_cast<struct RmqConsumerData*>(data);
45406f6ba60Sopenharmony_ci    uint64_t timeStampBase = rmqData->timeStamp;
45506f6ba60Sopenharmony_ci    auto cpuDetailMsg = traceResult->add_ftrace_cpu_detail();
45606f6ba60Sopenharmony_ci    struct RmqEntry* event;
45706f6ba60Sopenharmony_ci    cpuDetailMsg->set_cpu(rmqData->coreId);
45806f6ba60Sopenharmony_ci    cpuDetailMsg->set_overwrite(0);
45906f6ba60Sopenharmony_ci    auto curPtr = rmqData->data;
46006f6ba60Sopenharmony_ci    auto endPtr = rmqData->data + rmqData->length;
46106f6ba60Sopenharmony_ci    while (curPtr < endPtr) {
46206f6ba60Sopenharmony_ci        event = reinterpret_cast<struct RmqEntry*>(curPtr);
46306f6ba60Sopenharmony_ci        unsigned int evtSize = event->size;
46406f6ba60Sopenharmony_ci        if (evtSize == 0U) {
46506f6ba60Sopenharmony_ci            break;
46606f6ba60Sopenharmony_ci        }
46706f6ba60Sopenharmony_ci        struct HmTraceHeader* header = reinterpret_cast<struct HmTraceHeader*>(event->data);
46806f6ba60Sopenharmony_ci        auto parseEventCtx = SubEventParser<E>::GetInstance().GetParseEventCtx(header->commonType);
46906f6ba60Sopenharmony_ci        if (parseEventCtx == NULL) {
47006f6ba60Sopenharmony_ci            curPtr += RmqEntryTotalSize(evtSize);
47106f6ba60Sopenharmony_ci            continue;
47206f6ba60Sopenharmony_ci        }
47306f6ba60Sopenharmony_ci        ftraceEvent = cpuDetailMsg->add_event();
47406f6ba60Sopenharmony_ci        ftraceEvent->set_timestamp(event->timeStampOffset + timeStampBase);
47506f6ba60Sopenharmony_ci        if (!ftraceParser_->HmParseFtraceEvent(*ftraceEvent, reinterpret_cast<uint8_t*>(header), evtSize,
47606f6ba60Sopenharmony_ci                                               parseEventCtx)) {
47706f6ba60Sopenharmony_ci            PROFILER_LOG_ERROR(LOG_CORE, "hm parse event failed!");
47806f6ba60Sopenharmony_ci        }
47906f6ba60Sopenharmony_ci        curPtr += RmqEntryTotalSize(evtSize);
48006f6ba60Sopenharmony_ci    }
48106f6ba60Sopenharmony_ci    data += PAGE_SIZE;
48206f6ba60Sopenharmony_ci    return true;
48306f6ba60Sopenharmony_ci}
48406f6ba60Sopenharmony_ci
48506f6ba60Sopenharmony_cibool FlowController::HmParseEventDataOnNomalMode(long dataSize)
48606f6ba60Sopenharmony_ci{
48706f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_, false, "%s: resultWriter_ nullptr", __func__);
48806f6ba60Sopenharmony_ci    auto buffer = ftraceBuffers_[0].get();
48906f6ba60Sopenharmony_ci    auto endPtr = buffer + dataSize;
49006f6ba60Sopenharmony_ci
49106f6ba60Sopenharmony_ci    for (auto data = buffer; data < endPtr;) {
49206f6ba60Sopenharmony_ci        if (resultWriter_->isProtobufSerialize) {
49306f6ba60Sopenharmony_ci            auto traceResult = std::make_unique<TracePluginResult>();
49406f6ba60Sopenharmony_ci            FtraceEvent* event = nullptr;
49506f6ba60Sopenharmony_ci            CHECK_TRUE(HmParseEventData(traceResult.get(), data, event), false, "hm parse raw data failed!");
49606f6ba60Sopenharmony_ci            CHECK_TRUE(tansporter_->Submit(std::move(traceResult)), false, "report hm raw event failed!");
49706f6ba60Sopenharmony_ci        } else {
49806f6ba60Sopenharmony_ci            auto ctx = resultWriter_->startReport(resultWriter_);
49906f6ba60Sopenharmony_ci            CHECK_NOTNULL(ctx, false, "%s: get RandomWriteCtx FAILED!", __func__);
50006f6ba60Sopenharmony_ci            static ProtoEncoder::MessagePool msgPool;
50106f6ba60Sopenharmony_ci            static ProtoEncoder::TracePluginResult traceResult;
50206f6ba60Sopenharmony_ci            msgPool.Reset();
50306f6ba60Sopenharmony_ci            traceResult.Reset(ctx, &msgPool);
50406f6ba60Sopenharmony_ci            ProtoEncoder::FtraceEvent* event = nullptr;
50506f6ba60Sopenharmony_ci            CHECK_TRUE(HmParseEventData(&traceResult, data, event), false, "hm parse raw data failed!");
50606f6ba60Sopenharmony_ci            int32_t msgSize = traceResult.Finish();
50706f6ba60Sopenharmony_ci            resultWriter_->finishReport(resultWriter_, msgSize);
50806f6ba60Sopenharmony_ci            tansporter_->Report(static_cast<size_t>(msgSize));
50906f6ba60Sopenharmony_ci        }
51006f6ba60Sopenharmony_ci    }
51106f6ba60Sopenharmony_ci
51206f6ba60Sopenharmony_ci    return true;
51306f6ba60Sopenharmony_ci}
51406f6ba60Sopenharmony_ci
51506f6ba60Sopenharmony_cilong FlowController::ReadEventData(int cpuid)
51606f6ba60Sopenharmony_ci{
51706f6ba60Sopenharmony_ci    auto buffer = ftraceBuffers_[cpuid].get();
51806f6ba60Sopenharmony_ci    auto reader = ftraceReaders_[cpuid].get();
51906f6ba60Sopenharmony_ci    auto bufferSize = static_cast<long>(memPool_->GetBlockSize());
52006f6ba60Sopenharmony_ci
52106f6ba60Sopenharmony_ci    long nbytes = 0;
52206f6ba60Sopenharmony_ci    long used = 0;
52306f6ba60Sopenharmony_ci    long rest = bufferSize;
52406f6ba60Sopenharmony_ci    while ((nbytes = reader->Read(&buffer[used], rest)) > 0 && used < bufferSize) {
52506f6ba60Sopenharmony_ci        CHECK_TRUE(used % PAGE_SIZE == 0, used, "used invalid!");
52606f6ba60Sopenharmony_ci        used += nbytes;
52706f6ba60Sopenharmony_ci        rest -= nbytes;
52806f6ba60Sopenharmony_ci    }
52906f6ba60Sopenharmony_ci
53006f6ba60Sopenharmony_ci    if (used == bufferSize) {
53106f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE,
53206f6ba60Sopenharmony_ci            "used(%ld) equals bufferSize(%ld), please expand buffer_size_kb, otherwise the kernel may lose data\n",
53306f6ba60Sopenharmony_ci            used, bufferSize);
53406f6ba60Sopenharmony_ci    }
53506f6ba60Sopenharmony_ci    return used;
53606f6ba60Sopenharmony_ci}
53706f6ba60Sopenharmony_ci
53806f6ba60Sopenharmony_cibool FlowController::ParseEventData(int cpuid, uint8_t* page)
53906f6ba60Sopenharmony_ci{
54006f6ba60Sopenharmony_ci    if (resultWriter_->isProtobufSerialize) {
54106f6ba60Sopenharmony_ci        auto traceResult = std::make_unique<TracePluginResult>();
54206f6ba60Sopenharmony_ci        FtraceEvent* event = nullptr;  // Used to distinguish between SubEventParser instance types.
54306f6ba60Sopenharmony_ci        CHECK_TRUE(ParseFtraceEvent(traceResult.get(), cpuid, page, event), false, "parse raw event for cpu-%d failed!",
54406f6ba60Sopenharmony_ci                   cpuid);
54506f6ba60Sopenharmony_ci        CHECK_TRUE(tansporter_->Submit(std::move(traceResult)), false, "report raw event for cpu-%d failed!", cpuid);
54606f6ba60Sopenharmony_ci    } else {
54706f6ba60Sopenharmony_ci        auto ctx = resultWriter_->startReport(resultWriter_);
54806f6ba60Sopenharmony_ci        CHECK_NOTNULL(ctx, false, "%s: get RandomWriteCtx FAILED!", __func__);
54906f6ba60Sopenharmony_ci        static ProtoEncoder::MessagePool msgPool;
55006f6ba60Sopenharmony_ci        static ProtoEncoder::TracePluginResult traceResult;
55106f6ba60Sopenharmony_ci        msgPool.Reset();
55206f6ba60Sopenharmony_ci        traceResult.Reset(ctx, &msgPool);
55306f6ba60Sopenharmony_ci        ProtoEncoder::FtraceEvent* event = nullptr;  // Used to distinguish between SubEventParser instance types.
55406f6ba60Sopenharmony_ci        CHECK_TRUE(ParseFtraceEvent(&traceResult, cpuid, page, event), false, "parse raw event for cpu-%d failed!",
55506f6ba60Sopenharmony_ci                   cpuid);
55606f6ba60Sopenharmony_ci        int32_t msgSize = traceResult.Finish();
55706f6ba60Sopenharmony_ci        resultWriter_->finishReport(resultWriter_, msgSize);
55806f6ba60Sopenharmony_ci        tansporter_->Report(static_cast<size_t>(msgSize));
55906f6ba60Sopenharmony_ci    }
56006f6ba60Sopenharmony_ci    return true;
56106f6ba60Sopenharmony_ci}
56206f6ba60Sopenharmony_ci
56306f6ba60Sopenharmony_cibool FlowController::ParseEventDataOnNomalMode(int cpuid, long dataSize)
56406f6ba60Sopenharmony_ci{
56506f6ba60Sopenharmony_ci    CHECK_NOTNULL(resultWriter_, false, "%s: resultWriter_ nullptr", __func__);
56606f6ba60Sopenharmony_ci    auto buffer = ftraceBuffers_[cpuid].get();
56706f6ba60Sopenharmony_ci    auto endPtr = buffer + dataSize;
56806f6ba60Sopenharmony_ci    for (auto page = buffer; page < endPtr; page += PAGE_SIZE) {
56906f6ba60Sopenharmony_ci        if (!ParseEventData(cpuid, page)) {
57006f6ba60Sopenharmony_ci            PROFILER_LOG_ERROR(LOG_CORE, "%s:ParseEventData for cpu-%d failed!", __func__, cpuid);
57106f6ba60Sopenharmony_ci        }
57206f6ba60Sopenharmony_ci    }
57306f6ba60Sopenharmony_ci    return true;
57406f6ba60Sopenharmony_ci}
57506f6ba60Sopenharmony_ci
57606f6ba60Sopenharmony_cibool FlowController::ParseEventDataOnDelayMode()
57706f6ba60Sopenharmony_ci{
57806f6ba60Sopenharmony_ci    CHECK_TRUE(fseek(rawDataFile_.get(), 0, SEEK_SET) == 0, false, "fseek failed!");
57906f6ba60Sopenharmony_ci    while (!feof(rawDataFile_.get())) {
58006f6ba60Sopenharmony_ci        uint8_t cpuId = 0;
58106f6ba60Sopenharmony_ci        long dataBytes = 0;
58206f6ba60Sopenharmony_ci        fread(&cpuId, sizeof(uint8_t), 1, rawDataFile_.get());
58306f6ba60Sopenharmony_ci        fread(&dataBytes, sizeof(long), 1, rawDataFile_.get());
58406f6ba60Sopenharmony_ci        for (long i = 0; i < dataBytes; i += PAGE_SIZE) {
58506f6ba60Sopenharmony_ci            uint8_t page[PAGE_SIZE] = {0};
58606f6ba60Sopenharmony_ci            fread(page, sizeof(uint8_t), PAGE_SIZE, rawDataFile_.get());
58706f6ba60Sopenharmony_ci            if (!ParseEventData(cpuId, page)) {
58806f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "%s:ParseEventData for cpu-%d failed!", __func__, cpuId);
58906f6ba60Sopenharmony_ci            }
59006f6ba60Sopenharmony_ci        }
59106f6ba60Sopenharmony_ci    }
59206f6ba60Sopenharmony_ci    return true;
59306f6ba60Sopenharmony_ci}
59406f6ba60Sopenharmony_ci
59506f6ba60Sopenharmony_ciint FlowController::StopCapture(void)
59606f6ba60Sopenharmony_ci{
59706f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
59806f6ba60Sopenharmony_ci    CHECK_NOTNULL(tansporter_, -1, "crate ResultTransporter FAILED!");
59906f6ba60Sopenharmony_ci
60006f6ba60Sopenharmony_ci    CHECK_TRUE(requestEvents_.size() != 0 || traceApps_.size() != 0 || traceCategories_.size() != 0, -1,
60106f6ba60Sopenharmony_ci               "StopCapture: ftrace event is not set, return false");
60206f6ba60Sopenharmony_ci
60306f6ba60Sopenharmony_ci    // disable ftrace event switches
60406f6ba60Sopenharmony_ci    DisableTraceEvents();
60506f6ba60Sopenharmony_ci
60606f6ba60Sopenharmony_ci    // stop ftrace event data polling thread
60706f6ba60Sopenharmony_ci    keepRunning_ = false;
60806f6ba60Sopenharmony_ci    if (pollThread_.joinable()) {
60906f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "join thread start!\n");
61006f6ba60Sopenharmony_ci        pollThread_.join();
61106f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "join thread  done!\n");
61206f6ba60Sopenharmony_ci    }
61306f6ba60Sopenharmony_ci    // parse per cpu stats
61406f6ba60Sopenharmony_ci    if (resultWriter_->isProtobufSerialize) {
61506f6ba60Sopenharmony_ci        auto traceResult = std::make_unique<TracePluginResult>();
61606f6ba60Sopenharmony_ci        CHECK_TRUE(ParsePerCpuStatus(traceResult, TRACE_END), -1, "parse TRACE_END stats FAILED!");
61706f6ba60Sopenharmony_ci        CHECK_TRUE(tansporter_->Submit(std::move(traceResult)), -1, "report TRACE_END stats FAILED!");
61806f6ba60Sopenharmony_ci    } else {
61906f6ba60Sopenharmony_ci        auto ctx = resultWriter_->startReport(resultWriter_);
62006f6ba60Sopenharmony_ci        CHECK_NOTNULL(ctx, -1, "%s: get RandomWriteCtx FAILED!", __func__);
62106f6ba60Sopenharmony_ci        auto traceResult = std::make_unique<ProtoEncoder::TracePluginResult>(ctx);
62206f6ba60Sopenharmony_ci        CHECK_TRUE(ParsePerCpuStatus(traceResult, TRACE_END), -1, "parse TRACE_END stats FAILED!");
62306f6ba60Sopenharmony_ci        int32_t msgSize = traceResult->Finish();
62406f6ba60Sopenharmony_ci        resultWriter_->finishReport(resultWriter_, msgSize);
62506f6ba60Sopenharmony_ci        tansporter_->Report(static_cast<size_t>(msgSize));
62606f6ba60Sopenharmony_ci    }
62706f6ba60Sopenharmony_ci
62806f6ba60Sopenharmony_ci    // disable userspace trace triggers
62906f6ba60Sopenharmony_ci    // because trace cmd will read trace buffer,
63006f6ba60Sopenharmony_ci    // so we to this action after polling thread exit.
63106f6ba60Sopenharmony_ci    traceCollector_->Recover();
63206f6ba60Sopenharmony_ci    tansporter_->Flush();
63306f6ba60Sopenharmony_ci
63406f6ba60Sopenharmony_ci    // release resources
63506f6ba60Sopenharmony_ci    ftraceReaders_.clear();   // release ftrace data readers
63606f6ba60Sopenharmony_ci    ftraceBuffers_.clear();   // release ftrace event read buffers
63706f6ba60Sopenharmony_ci    memPool_.reset();         // release memory pool
63806f6ba60Sopenharmony_ci    return 0;
63906f6ba60Sopenharmony_ci}
64006f6ba60Sopenharmony_ci
64106f6ba60Sopenharmony_citemplate <typename T> bool FlowController::ParsePerCpuStatus(T& tracePluginResult, int stage)
64206f6ba60Sopenharmony_ci{
64306f6ba60Sopenharmony_ci    CHECK_NOTNULL(tracePluginResult, false, "create TracePluginResult FAILED!");
64406f6ba60Sopenharmony_ci
64506f6ba60Sopenharmony_ci    auto cpuStatsMsg = tracePluginResult->add_ftrace_cpu_stats();
64606f6ba60Sopenharmony_ci    if (stage == TRACE_START) {
64706f6ba60Sopenharmony_ci        cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_START);
64806f6ba60Sopenharmony_ci    } else {
64906f6ba60Sopenharmony_ci        cpuStatsMsg->set_status(FtraceCpuStatsMsg_Status_TRACE_END);
65006f6ba60Sopenharmony_ci    }
65106f6ba60Sopenharmony_ci
65206f6ba60Sopenharmony_ci    std::string traceClock = FtraceFsOps::GetInstance().GetTraceClock();
65306f6ba60Sopenharmony_ci    if (traceClock.size() > 0) {
65406f6ba60Sopenharmony_ci        cpuStatsMsg->set_trace_clock(traceClock);
65506f6ba60Sopenharmony_ci    }
65606f6ba60Sopenharmony_ci
65706f6ba60Sopenharmony_ci    for (int i = 0; i < platformCpuNum_; i++) {
65806f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "[%d] ParsePerCpuStatus %d!", i, stage);
65906f6ba60Sopenharmony_ci        PerCpuStats stats = {};
66006f6ba60Sopenharmony_ci        stats.cpuIndex = i;
66106f6ba60Sopenharmony_ci        ftraceParser_->ParsePerCpuStatus(stats, FtraceFsOps::GetInstance().GetPerCpuStats(i));
66206f6ba60Sopenharmony_ci        auto perCpuMsg = cpuStatsMsg->add_per_cpu_stats();
66306f6ba60Sopenharmony_ci        perCpuMsg->set_cpu(stats.cpuIndex);
66406f6ba60Sopenharmony_ci        perCpuMsg->set_entries(stats.entries);
66506f6ba60Sopenharmony_ci        perCpuMsg->set_overrun(stats.overrun);
66606f6ba60Sopenharmony_ci        perCpuMsg->set_commit_overrun(stats.commitOverrun);
66706f6ba60Sopenharmony_ci        perCpuMsg->set_bytes(stats.bytes);
66806f6ba60Sopenharmony_ci        perCpuMsg->set_oldest_event_ts(stats.oldestEventTs);
66906f6ba60Sopenharmony_ci        perCpuMsg->set_now_ts(stats.nowTs);
67006f6ba60Sopenharmony_ci        perCpuMsg->set_dropped_events(stats.droppedEvents);
67106f6ba60Sopenharmony_ci        perCpuMsg->set_read_events(stats.readEvents);
67206f6ba60Sopenharmony_ci    }
67306f6ba60Sopenharmony_ci
67406f6ba60Sopenharmony_ci    return true;
67506f6ba60Sopenharmony_ci}
67606f6ba60Sopenharmony_ci
67706f6ba60Sopenharmony_citemplate <typename T> bool FlowController::ReportClockTimes(T& tracePluginResult)
67806f6ba60Sopenharmony_ci{
67906f6ba60Sopenharmony_ci    CHECK_NOTNULL(tracePluginResult, false, "create TracePluginResult FAILED!");
68006f6ba60Sopenharmony_ci
68106f6ba60Sopenharmony_ci    std::map<clockid_t, ClockDetailMsg::ClockId> clocksMap = {
68206f6ba60Sopenharmony_ci        {CLOCK_REALTIME, ClockDetailMsg::REALTIME},
68306f6ba60Sopenharmony_ci        {CLOCK_REALTIME_COARSE, ClockDetailMsg::REALTIME_COARSE},
68406f6ba60Sopenharmony_ci        {CLOCK_MONOTONIC, ClockDetailMsg::MONOTONIC},
68506f6ba60Sopenharmony_ci        {CLOCK_MONOTONIC_COARSE, ClockDetailMsg::MONOTONIC_COARSE},
68606f6ba60Sopenharmony_ci        {CLOCK_MONOTONIC_RAW, ClockDetailMsg::MONOTONIC_RAW},
68706f6ba60Sopenharmony_ci        {CLOCK_BOOTTIME, ClockDetailMsg::BOOTTIME},
68806f6ba60Sopenharmony_ci    };
68906f6ba60Sopenharmony_ci    for (auto& entry : clocksMap) {
69006f6ba60Sopenharmony_ci        struct timespec ts = {};
69106f6ba60Sopenharmony_ci        clock_gettime(entry.first, &ts);
69206f6ba60Sopenharmony_ci        auto clockMsg = tracePluginResult->add_clocks_detail();
69306f6ba60Sopenharmony_ci        CHECK_NOTNULL(clockMsg, false, "add clock_detail failed for %d!", entry.first);
69406f6ba60Sopenharmony_ci        clockMsg->set_id(entry.second);
69506f6ba60Sopenharmony_ci        auto timeMsg = clockMsg->mutable_time();
69606f6ba60Sopenharmony_ci        timeMsg->set_tv_sec(ts.tv_sec);
69706f6ba60Sopenharmony_ci        timeMsg->set_tv_nsec(ts.tv_nsec);
69806f6ba60Sopenharmony_ci
69906f6ba60Sopenharmony_ci        struct timespec tsResolution = {};
70006f6ba60Sopenharmony_ci        clock_getres(entry.first, &tsResolution);
70106f6ba60Sopenharmony_ci        auto resolutionMsg = clockMsg->mutable_resolution();
70206f6ba60Sopenharmony_ci        resolutionMsg->set_tv_sec(tsResolution.tv_sec);
70306f6ba60Sopenharmony_ci        resolutionMsg->set_tv_nsec(tsResolution.tv_nsec);
70406f6ba60Sopenharmony_ci    }
70506f6ba60Sopenharmony_ci    return true;
70606f6ba60Sopenharmony_ci}
70706f6ba60Sopenharmony_ci
70806f6ba60Sopenharmony_citemplate <typename T> bool FlowController::ParseKernelSymbols(T& tracePluginResult)
70906f6ba60Sopenharmony_ci{
71006f6ba60Sopenharmony_ci    CHECK_NOTNULL(tracePluginResult, false, "create TracePluginResult FAILED!");
71106f6ba60Sopenharmony_ci
71206f6ba60Sopenharmony_ci    ksymsParser_->Accept([&tracePluginResult](const KernelSymbol& symbol) {
71306f6ba60Sopenharmony_ci        auto symbolDetail = tracePluginResult->add_symbols_detail();
71406f6ba60Sopenharmony_ci        symbolDetail->set_symbol_addr(symbol.addr);
71506f6ba60Sopenharmony_ci        symbolDetail->set_symbol_name(symbol.name);
71606f6ba60Sopenharmony_ci    });
71706f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "parse kernel symbol message done!");
71806f6ba60Sopenharmony_ci    return true;
71906f6ba60Sopenharmony_ci}
72006f6ba60Sopenharmony_ci
72106f6ba60Sopenharmony_citemplate <typename T, typename E>
72206f6ba60Sopenharmony_cibool FlowController::ParseFtraceEvent(T* tracePluginResult, int cpuid, uint8_t page[], E* ftraceEvent)
72306f6ba60Sopenharmony_ci{
72406f6ba60Sopenharmony_ci    CHECK_NOTNULL(tracePluginResult, false, "create TracePluginResult FAILED!");
72506f6ba60Sopenharmony_ci
72606f6ba60Sopenharmony_ci    auto cpudetail = tracePluginResult->add_ftrace_cpu_detail();
72706f6ba60Sopenharmony_ci    cpudetail->set_cpu(static_cast<uint32_t>(cpuid));
72806f6ba60Sopenharmony_ci
72906f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceParser_->ParsePage(*cpudetail, page, PAGE_SIZE, ftraceEvent), false, "parse page failed!");
73006f6ba60Sopenharmony_ci    return true;
73106f6ba60Sopenharmony_ci}
73206f6ba60Sopenharmony_ci
73306f6ba60Sopenharmony_cibool FlowController::AddPlatformEventsToParser(void)
73406f6ba60Sopenharmony_ci{
73506f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceSupported_, false, "current kernel not support ftrace!");
73606f6ba60Sopenharmony_ci
73706f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "Add platform events to parser start!");
73806f6ba60Sopenharmony_ci    for (auto& typeName : FtraceFsOps::GetInstance().GetPlatformEvents()) {
73906f6ba60Sopenharmony_ci        std::string type = typeName.first;
74006f6ba60Sopenharmony_ci        std::string name = typeName.second;
74106f6ba60Sopenharmony_ci        if (ftraceParser_->SetupEvent(type, name)) {
74206f6ba60Sopenharmony_ci            supportedEvents_.push_back(typeName);
74306f6ba60Sopenharmony_ci        }
74406f6ba60Sopenharmony_ci    }
74506f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "Add platform events to parser done, events: %zu!", supportedEvents_.size());
74606f6ba60Sopenharmony_ci    return true;
74706f6ba60Sopenharmony_ci}
74806f6ba60Sopenharmony_ci
74906f6ba60Sopenharmony_ciint FlowController::LoadConfig(const uint8_t configData[], uint32_t size)
75006f6ba60Sopenharmony_ci{
75106f6ba60Sopenharmony_ci    CHECK_TRUE(size > 0, -1, "config data size is zero!");
75206f6ba60Sopenharmony_ci    CHECK_NOTNULL(configData, -1, "config data is null!");
75306f6ba60Sopenharmony_ci    CHECK_TRUE(ftraceSupported_, -1, "current kernel not support ftrace!");
75406f6ba60Sopenharmony_ci    CHECK_NOTNULL(tansporter_, -1, "ResultTransporter crated FAILED!");
75506f6ba60Sopenharmony_ci
75606f6ba60Sopenharmony_ci    TracePluginConfig traceConfig;
75706f6ba60Sopenharmony_ci    CHECK_TRUE(traceConfig.ParseFromArray(configData, size), -1, "parse %u bytes configData failed!", size);
75806f6ba60Sopenharmony_ci
75906f6ba60Sopenharmony_ci    // sort and save user requested trace events
76006f6ba60Sopenharmony_ci    std::set<std::string> events(traceConfig.ftrace_events().begin(), traceConfig.ftrace_events().end());
76106f6ba60Sopenharmony_ci    for (auto ftraceEvent : events) {
76206f6ba60Sopenharmony_ci        requestEvents_.push_back(ftraceEvent);
76306f6ba60Sopenharmony_ci    }
76406f6ba60Sopenharmony_ci
76506f6ba60Sopenharmony_ci    traceApps_.assign(traceConfig.hitrace_apps().begin(), traceConfig.hitrace_apps().end());
76606f6ba60Sopenharmony_ci    traceCategories_.assign(traceConfig.hitrace_categories().begin(), traceConfig.hitrace_categories().end());
76706f6ba60Sopenharmony_ci
76806f6ba60Sopenharmony_ci    CHECK_TRUE(requestEvents_.size() != 0 || traceApps_.size() != 0 || traceCategories_.size() != 0, -1,
76906f6ba60Sopenharmony_ci               "LoadConfig: ftrace event is not set, return false");
77006f6ba60Sopenharmony_ci
77106f6ba60Sopenharmony_ci    // setup trace clock
77206f6ba60Sopenharmony_ci    if (g_availableClocks.count(traceConfig.clock()) > 0) {
77306f6ba60Sopenharmony_ci        traceClock_ = traceConfig.clock();
77406f6ba60Sopenharmony_ci        FtraceFsOps::GetInstance().SetTraceClock(traceConfig.clock());
77506f6ba60Sopenharmony_ci    }
77606f6ba60Sopenharmony_ci
77706f6ba60Sopenharmony_ci    // setup parse kernel symbol option
77806f6ba60Sopenharmony_ci    parseKsyms_ = traceConfig.parse_ksyms();
77906f6ba60Sopenharmony_ci    parseMode_ = traceConfig.parse_mode();
78006f6ba60Sopenharmony_ci    // setup trace buffer size
78106f6ba60Sopenharmony_ci    SetupTraceBufferSize(traceConfig.buffer_size_kb());
78206f6ba60Sopenharmony_ci
78306f6ba60Sopenharmony_ci    // setup transporter flush params
78406f6ba60Sopenharmony_ci    SetupTransporterFlushParams(traceConfig.flush_interval_ms(), traceConfig.flush_threshold_kb());
78506f6ba60Sopenharmony_ci
78606f6ba60Sopenharmony_ci    // generate raw data file names
78706f6ba60Sopenharmony_ci    GenerateRawDataFileNames(traceConfig.raw_data_prefix());
78806f6ba60Sopenharmony_ci
78906f6ba60Sopenharmony_ci    // setup trace period param
79006f6ba60Sopenharmony_ci    SetupTraceReadPeriod(traceConfig.trace_period_ms());
79106f6ba60Sopenharmony_ci    flushCacheData_ = traceConfig.discard_cache_data();
79206f6ba60Sopenharmony_ci    hitraceTime_ = traceConfig.hitrace_time();
79306f6ba60Sopenharmony_ci    return 0;
79406f6ba60Sopenharmony_ci}
79506f6ba60Sopenharmony_ci
79606f6ba60Sopenharmony_civoid FlowController::SetupTraceBufferSize(uint32_t sizeKb)
79706f6ba60Sopenharmony_ci{
79806f6ba60Sopenharmony_ci    uint32_t maxBufferSizeKb = MAX_BUFFER_SIZE_KB;
79906f6ba60Sopenharmony_ci    if (FtraceFsOps::GetInstance().IsHmKernel()) {
80006f6ba60Sopenharmony_ci        maxBufferSizeKb = HM_MAX_BUFFER_SIZE_KB;
80106f6ba60Sopenharmony_ci    }
80206f6ba60Sopenharmony_ci    if (sizeKb < MIN_BUFFER_SIZE_KB) {
80306f6ba60Sopenharmony_ci        bufferSizeKb_ = MIN_BUFFER_SIZE_KB;
80406f6ba60Sopenharmony_ci    } else if (sizeKb > maxBufferSizeKb) {
80506f6ba60Sopenharmony_ci        bufferSizeKb_ = maxBufferSizeKb;
80606f6ba60Sopenharmony_ci    } else {
80706f6ba60Sopenharmony_ci        bufferSizeKb_ = sizeKb / KB_PER_PAGE * KB_PER_PAGE;
80806f6ba60Sopenharmony_ci    }
80906f6ba60Sopenharmony_ci}
81006f6ba60Sopenharmony_ci
81106f6ba60Sopenharmony_civoid FlowController::SetupTransporterFlushParams(uint32_t flushInterval, uint32_t flushThresholdKb)
81206f6ba60Sopenharmony_ci{
81306f6ba60Sopenharmony_ci    if (flushInterval > 0 && flushInterval <= MAX_FLUSH_INTERVAL) {
81406f6ba60Sopenharmony_ci        tansporter_->SetFlushInterval(flushInterval);
81506f6ba60Sopenharmony_ci    }
81606f6ba60Sopenharmony_ci    if (flushThresholdKb > 0 && flushThresholdKb <= MAX_FLUSH_THRESHOLD) {
81706f6ba60Sopenharmony_ci        tansporter_->SetFlushThreshold(flushThresholdKb * BYTE_PER_KB);
81806f6ba60Sopenharmony_ci    }
81906f6ba60Sopenharmony_ci}
82006f6ba60Sopenharmony_ci
82106f6ba60Sopenharmony_civoid FlowController::GenerateRawDataFileNames(const std::string& prefix)
82206f6ba60Sopenharmony_ci{
82306f6ba60Sopenharmony_ci    if (prefix.size() > 0) {
82406f6ba60Sopenharmony_ci        for (int i = 0; i < platformCpuNum_; i++) {
82506f6ba60Sopenharmony_ci            std::string path = prefix + std::to_string(i);
82606f6ba60Sopenharmony_ci            rawDataDumpPath_.push_back(path);
82706f6ba60Sopenharmony_ci        }
82806f6ba60Sopenharmony_ci    }
82906f6ba60Sopenharmony_ci}
83006f6ba60Sopenharmony_ci
83106f6ba60Sopenharmony_civoid FlowController::SetupTraceReadPeriod(uint32_t tracePeriod)
83206f6ba60Sopenharmony_ci{
83306f6ba60Sopenharmony_ci    if (tracePeriod > 0 && tracePeriod <= MAX_TRACE_PERIOD_MS) {
83406f6ba60Sopenharmony_ci        tracePeriodMs_ = tracePeriod;
83506f6ba60Sopenharmony_ci    } else {
83606f6ba60Sopenharmony_ci        tracePeriodMs_ = DEFAULT_TRACE_PERIOD_MS;
83706f6ba60Sopenharmony_ci    }
83806f6ba60Sopenharmony_ci}
83906f6ba60Sopenharmony_ci
84006f6ba60Sopenharmony_civoid FlowController::EnableTraceEvents(void)
84106f6ba60Sopenharmony_ci{
84206f6ba60Sopenharmony_ci    std::unordered_set<std::string> userEventSet(requestEvents_.begin(), requestEvents_.end());
84306f6ba60Sopenharmony_ci    for (auto& event : supportedEvents_) {
84406f6ba60Sopenharmony_ci        std::string type = event.first;
84506f6ba60Sopenharmony_ci        std::string name = event.second;
84606f6ba60Sopenharmony_ci        std::string fmtType = type;
84706f6ba60Sopenharmony_ci        if (type == "power_kernel") {
84806f6ba60Sopenharmony_ci            fmtType = "power";
84906f6ba60Sopenharmony_ci        }
85006f6ba60Sopenharmony_ci        if (userEventSet.count(fmtType + "/" + name)) { // user config format
85106f6ba60Sopenharmony_ci            if (FtraceFsOps::GetInstance().EnableEvent(type, name)) {
85206f6ba60Sopenharmony_ci                FtraceFsOps::GetInstance().AppendSetEvent(type, name);
85306f6ba60Sopenharmony_ci                enabledEvents_.push_back(event);
85406f6ba60Sopenharmony_ci            }
85506f6ba60Sopenharmony_ci        }
85606f6ba60Sopenharmony_ci    }
85706f6ba60Sopenharmony_ci    FtraceFsOps::GetInstance().EnableTracing();
85806f6ba60Sopenharmony_ci}
85906f6ba60Sopenharmony_ci
86006f6ba60Sopenharmony_civoid FlowController::DisableTraceEvents(void)
86106f6ba60Sopenharmony_ci{
86206f6ba60Sopenharmony_ci    FtraceFsOps::GetInstance().DisableTracing();
86306f6ba60Sopenharmony_ci    for (auto& event : enabledEvents_) {
86406f6ba60Sopenharmony_ci        std::string type = event.first;
86506f6ba60Sopenharmony_ci        std::string name = event.second;
86606f6ba60Sopenharmony_ci        FtraceFsOps::GetInstance().DisableEvent(type, name);
86706f6ba60Sopenharmony_ci    }
86806f6ba60Sopenharmony_ci    enabledEvents_.clear();
86906f6ba60Sopenharmony_ci}
87006f6ba60Sopenharmony_ci
87106f6ba60Sopenharmony_civoid FlowController::DisableAllCategories(void)
87206f6ba60Sopenharmony_ci{
87306f6ba60Sopenharmony_ci    for (auto& event : supportedEvents_) {
87406f6ba60Sopenharmony_ci        std::string type = event.first;
87506f6ba60Sopenharmony_ci        std::string name = event.second;
87606f6ba60Sopenharmony_ci        FtraceFsOps::GetInstance().DisableCategories(type);
87706f6ba60Sopenharmony_ci    }
87806f6ba60Sopenharmony_ci}
87906f6ba60Sopenharmony_ci
88006f6ba60Sopenharmony_civoid FlowController::SetReportBasicData(bool isReportBasicData)
88106f6ba60Sopenharmony_ci{
88206f6ba60Sopenharmony_ci    isReportBasicData_ = isReportBasicData;
88306f6ba60Sopenharmony_ci}
88406f6ba60Sopenharmony_ciFTRACE_NS_END
885