diff --git a/include/callstack.h b/include/callstack.h index c401fd488b1ef9e481ec90993524b2bc8383c0ca..0bcb6ba79c4c99fd43d82efce962a20794315ccd 100644 --- a/include/callstack.h +++ b/include/callstack.h @@ -53,6 +53,7 @@ public: size_t ExpandCallStack(pid_t tid, std::vector &callFrames, size_t expandLimit = 1u); private: + mutable std::mutex cacheMutex_; pid_t lastPid_ = -1; ADDR_TYPE lastAddr_ = 0; ADDR_TYPE lastData_ = 0; diff --git a/include/perf_events.h b/include/perf_events.h index c99325ab1d1eb801f6c89cb95da20752898d14ff..387d92ce66b5c231a969096bbfdd9e8da27f810f 100644 --- a/include/perf_events.h +++ b/include/perf_events.h @@ -331,6 +331,8 @@ struct read_format_no_group { __u64 id; /* if PERF_FORMAT_ID */ }; +u32 GetSpeType(); + class PerfEvents { public: static constexpr uint64_t DEFAULT_SAMPLE_FREQUNCY = 4000; diff --git a/include/subcommand_record.h b/include/subcommand_record.h index 5f265f955de7c3a3dd467c122757b37da4710c39..41a148b8de1345ba929c03e2d13adf9790791fab 100644 --- a/include/subcommand_record.h +++ b/include/subcommand_record.h @@ -316,7 +316,7 @@ private: int nullFd_ = -1; std::thread clientCommandHandle_; std::thread replyCommandHandle_; - bool clientRunning_ = true; + std::atomic_bool clientRunning_ = true; bool isHiperfClient_ = false; struct ControlCommandHandler { std::function preProcess = []() -> bool { diff --git a/include/subcommand_stat.h b/include/subcommand_stat.h index 466479ae8d37fbfb041d5ede82c4b5858d5d7caa..6adfc88ef97bba1e10a453ceb07b0d6b1641b14b 100644 --- a/include/subcommand_stat.h +++ b/include/subcommand_stat.h @@ -185,7 +185,7 @@ private: int nullFd_ = -1; FILE* filePtr_ = nullptr; std::thread clientCommandHandle_; - bool clientRunning_ = true; + std::atomic_bool clientRunning_ = true; struct ControlCommandHandler { std::function preProcess = []() -> bool { return false; diff --git a/src/callstack.cpp b/src/callstack.cpp index 3e9fe7ba4af8723e5a9a7ed02e66a7badff0f298..7b9ee4b0d7f667287f46f3bc0d5c3f45bdcd6af4 100644 --- a/src/callstack.cpp +++ b/src/callstack.cpp @@ -215,6 +215,8 @@ size_t CallStack::ExpandCallStack(pid_t tid, std::vector &callFrames, HLOGM("new callstack is too small, skip it"); return expand; } + + std::lock_guard lock(cacheMutex_); if (!cachedCallFramesMap_.count(tid)) { cachedCallFramesMap_[tid].reserve(MAX_CALL_FRAME_EXPAND_CACHE_SIZE); } @@ -273,14 +275,14 @@ bool CallStack::DoUnwind2(const VirtualThread &thread, std::vector &ca auto unwinder = pidUnwinder_[thread.pid_]; #ifdef target_cpu_arm - static std::shared_ptr regs = std::make_shared(); + thread_local std::shared_ptr regs = std::make_shared(); std::vector tempRegs; for (u64 i = 0; i < regsNum_; ++i) { tempRegs.push_back(static_cast(regs_[i])); } regs->SetRegsData(tempRegs); #else - static std::shared_ptr regs = std::make_shared(); + thread_local std::shared_ptr regs = std::make_shared(); regs->SetRegsData(reinterpret_cast(regs_), regsNum_); #endif CHECK_TRUE(unwinder != nullptr, false, 0, ""); @@ -396,7 +398,10 @@ int CallStack::AccessMem2(uintptr_t addr, uintptr_t *val, void *arg) } } else { size_t stackOffset = addr - unwindInfoPtr->callStack.stackPoint_; - *val = *(uintptr_t *)&unwindInfoPtr->callStack.stack_[stackOffset]; + if (memcpy_s(val, sizeof(uintptr_t), &unwindInfoPtr->callStack.stack_[stackOffset], sizeof(uintptr_t)) != 0) { + HLOGE("memcpy_s failed for stack offset %zu", stackOffset); + return -1; + } HLOGM("access_mem addr val %" UNW_WORD_PFLAG ", from stack offset %zu", *val, stackOffset); } @@ -432,6 +437,7 @@ CallStack::CallStack() void CallStack::ClearCache() { + std::lock_guard lock(cacheMutex_); cachedCallFramesMap_.clear(); lastPid_ = -1; lastAddr_ = 0; diff --git a/src/perf_events.cpp b/src/perf_events.cpp index e12f968f92cb0125ecc62670dd62a3eb92e8db45..2b0be44f5b5936a309d0d5ad309b8f6ef6ab1bf0 100644 --- a/src/perf_events.cpp +++ b/src/perf_events.cpp @@ -156,12 +156,12 @@ u32 GetSpeType() fd = fopen("/sys/devices/arm_spe_0/type", "r"); if (fd == nullptr) { HLOGV("open sysfs file failed"); - return -1; + return UINT_MAX; } if (fscanf_s(fd, "%u", &speType) <= 0) { HLOGV("fscanf_s file failed"); (void)fclose(fd); - return -1; + return UINT_MAX; } (void)fclose(fd); @@ -367,6 +367,10 @@ bool PerfEvents::AddEvent(const std::string &eventString, bool followGroup) } else { if (eventName == "arm_spe_0") { u32 speType = GetSpeType(); + if (speType == UINT_MAX) { + HLOGE("Failed to get SPE type."); + return false; + } return AddSpeEvent(speType); } if (StringStartsWith(eventName, "0x") diff --git a/src/spe_decoder.cpp b/src/spe_decoder.cpp index 992709ac42fe353fe6f33b042dbb9699bc9515e7..a271d2e0427573afb336fc76ca3341cf7a0b497b 100644 --- a/src/spe_decoder.cpp +++ b/src/spe_decoder.cpp @@ -546,14 +546,14 @@ int SpePktDesc(const struct SpePkt *packet, char *buf, break; case PERF_SPE_DATA_SOURCE: case PERF_SPE_TIMESTAMP: - SpePktOutString(&err, &buf, &blen, "%s %lld", name.c_str(), payload); + SpePktOutString(&err, &buf, &blen, "%s %llu", name.c_str(), payload); break; case PERF_SPE_ADDRESS: err = SpePktDescAddr(packet, buf, bufLen); break; case PERF_SPE_CONTEXT: - SpePktOutString(&err, &buf, &blen, "%s 0x%lx el%d", - name.c_str(), (unsigned long)payload, idx + 1); + SpePktOutString(&err, &buf, &blen, "%s 0x%llx el%d", + name.c_str(), payload, idx + 1); break; case PERF_SPE_COUNTER: err = SpePktDesCont(packet, buf, bufLen); diff --git a/src/subcommand_record.cpp b/src/subcommand_record.cpp index aa24d52cf75321c1b03664b9b8125b68970098d8..dcef269f692b5bab6bf96747dda07f5817c4f939 100644 --- a/src/subcommand_record.cpp +++ b/src/subcommand_record.cpp @@ -1418,7 +1418,7 @@ void SubCommandRecord::ClientCommandHandle() InitControlCommandHandlerMap(); bool hasRead = true; - while (clientRunning_) { + while (clientRunning_.load()) { if (isFifoServer_ && hasRead) { if (clientPipeInput_ != -1) { // after read(), block is disabled, the poll will be waked neven if no data @@ -1738,7 +1738,7 @@ HiperfError SubCommandRecord::OnSubCommand(std::vector& args) void SubCommandRecord::CloseClientThread() { if (clientCommandHandle_.joinable()) { - clientRunning_ = false; + clientRunning_.store(false); HLOGI("CloseClientThread"); if (nullFd_ != -1) { close(nullFd_); @@ -1755,7 +1755,7 @@ void SubCommandRecord::CloseClientThread() void SubCommandRecord::CloseReplyThread() { if (replyCommandHandle_.joinable()) { - clientRunning_ = false; + clientRunning_.store(false); HLOGI("CloseReplyThread"); replyCommandHandle_.join(); } diff --git a/src/subcommand_stat.cpp b/src/subcommand_stat.cpp index ce00f4a0a41adbe66ca8373ba9317e59525e5434..decdae8665a46d2671aa17cf0308b26c7bb7854c 100644 --- a/src/subcommand_stat.cpp +++ b/src/subcommand_stat.cpp @@ -839,7 +839,7 @@ void SubCommandStat::ClientCommandHandle() InitControlCommandHandlerMap(); bool hasRead = true; - while (clientRunning_) { + while (clientRunning_.load()) { if (isFifoServer_ && hasRead) { if (clientPipeInput_ != -1) { // after read(), block is disabled, the poll will be waked neven if no data @@ -996,7 +996,7 @@ HiperfError SubCommandStat::OnSubCommand(std::vector& args) void SubCommandStat::CloseClientThread() { if (clientCommandHandle_.joinable()) { - clientRunning_ = false; + clientRunning_.store(false); HLOGI("CloseClientThread"); if (nullFd_ != -1) { close(nullFd_); diff --git a/test/unittest/common/native/spe_decoder_test.cpp b/test/unittest/common/native/spe_decoder_test.cpp index b31f3b46a36ec685b4f84d2f9eaac1ff73a6b759..bd47d3f79935f0928cde0e2722d2ef9fd1e29ec4 100644 --- a/test/unittest/common/native/spe_decoder_test.cpp +++ b/test/unittest/common/native/spe_decoder_test.cpp @@ -15,6 +15,7 @@ #include "spe_decoder_test.h" #include "command.h" +#include "perf_events.h" #include "subcommand_dump.h" #include "subcommand_record.h" #include "test_utilities.h" @@ -100,7 +101,6 @@ HWTEST_F(SpeDecoderTest, TestRecord, TestSize.Level0) std::string cmdString = "record -e arm_spe_0/load_filter=1,min_latency=100/ -d 10 --app "; cmdString += " " + testProcesses; printf("command : %s\n", cmdString.c_str()); - // it need load some symbols and much more log stdoutRecord.Start(); const auto startTime = std::chrono::steady_clock::now(); @@ -109,7 +109,11 @@ HWTEST_F(SpeDecoderTest, TestRecord, TestSize.Level0) std::chrono::steady_clock::now() - startTime); std::string stringOut = stdoutRecord.Stop(); printf("run %" PRId64 " ms return %d\n", (uint64_t)costMs.count(), static_cast(ret)); - EXPECT_EQ(true, ret); + if (GetSpeType() == UINT_MAX) { + EXPECT_EQ(false, ret); + } else { + EXPECT_EQ(true, ret); + } } /**