1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
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 #include "stack_data_repeater.h"
16 #include "hook_common.h"
17
18 using namespace OHOS::Developtools::NativeDaemon;
19
StackDataRepeater(size_t maxSize)20 StackDataRepeater::StackDataRepeater(size_t maxSize)
21 {
22 maxSize_ = maxSize;
23 closed_ = false;
24 reducedStackCount_ = 0;
25 }
26
~StackDataRepeater()27 StackDataRepeater::~StackDataRepeater()
28 {
29 Close();
30 }
31
Size()32 size_t StackDataRepeater::Size()
33 {
34 std::unique_lock<std::mutex> lock(mutex_);
35 return rawDataQueue_.size();
36 }
37
Reset()38 void StackDataRepeater::Reset()
39 {
40 std::unique_lock<std::mutex> lock(mutex_);
41 closed_ = false;
42 }
43
Close()44 void StackDataRepeater::Close()
45 {
46 {
47 std::unique_lock<std::mutex> lock(mutex_);
48 rawDataQueue_.clear();
49 closed_ = true;
50 }
51 PROFILER_LOG_INFO(LOG_CORE, "StackDataRepeater Close, reducedStackCount_ : %" PRIx64 " ", reducedStackCount_);
52 slotCondVar_.notify_all();
53 itemCondVar_.notify_all();
54 }
55
PutRawStack(const RawStackPtr & rawData,bool isRecordAccurately)56 bool StackDataRepeater::PutRawStack(const RawStackPtr& rawData, bool isRecordAccurately)
57 {
58 bool needInsert = true;
59 std::unique_lock<std::mutex> lock(mutex_);
60
61 if ((rawData == nullptr) && (rawDataQueue_.size() > 0)) {
62 PROFILER_LOG_INFO(LOG_CORE, "no need put nullptr if queue has data, rawDataQueue_.size() = %zu",
63 rawDataQueue_.size());
64 return true;
65 }
66 while (rawDataQueue_.size() >= maxSize_ && !closed_) {
67 slotCondVar_.wait(lock);
68 }
69 if (closed_) {
70 return false;
71 }
72
73 if (__builtin_expect((rawData != nullptr) && !isRecordAccurately, true)) {
74 if (rawData->stackConext->type == FREE_MSG) {
75 auto temp = mallocMap_.find(rawData->stackConext->addr);
76 // true : pair of malloc and free matched, both malloc and free will be ignored
77 // false : can not match, send free's data anyway
78 if (temp != mallocMap_.end()) {
79 temp->second->reportFlag = false; // will be ignore later
80 mallocMap_.erase(rawData->stackConext->addr);
81 needInsert = false;
82 }
83 } else if (rawData->stackConext->type == MALLOC_MSG) {
84 mallocMap_.insert(std::pair<void*, std::shared_ptr<RawStack>>(rawData->stackConext->addr, rawData));
85 }
86 if (needInsert) {
87 rawDataQueue_.push_back(rawData);
88 }
89 } else {
90 rawDataQueue_.push_back(rawData);
91 }
92
93 lock.unlock();
94 itemCondVar_.notify_one();
95 return true;
96 }
97
TakeRawData(uint32_t during,clockid_t clockId,uint32_t batchCount,RawStackPtr batchRawStack[])98 RawStackPtr StackDataRepeater::TakeRawData(uint32_t during, clockid_t clockId, uint32_t batchCount,
99 RawStackPtr batchRawStack[])
100 {
101 uint32_t rawDataQueueSize = 0;
102 std::unique_lock<std::mutex> lock(mutex_);
103 while (rawDataQueue_.empty() && !closed_) {
104 itemCondVar_.wait(lock);
105 }
106 if (closed_) {
107 return nullptr;
108 }
109 RawStackPtr result = nullptr;
110 rawDataQueueSize = rawDataQueue_.size();
111 int resultSize = rawDataQueueSize > batchCount ? batchCount : rawDataQueueSize;
112 bool needReduceStack = rawDataQueueSize >= SPEED_UP_THRESHOLD;
113 for (int i = 0; i < resultSize; i++) {
114 result = rawDataQueue_.front();
115 rawDataQueue_.pop_front();
116 batchRawStack[i] = result;
117 if ((result != nullptr) && (result->stackConext->type == MALLOC_MSG)) {
118 mallocMap_.erase(result->stackConext->addr);
119 if (needReduceStack) {
120 result->reduceStackFlag = true;
121 reducedStackCount_++;
122 }
123 }
124 }
125
126 lock.unlock();
127 slotCondVar_.notify_one();
128 return result;
129 }