• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "stack_data_repeater.h"
16 #include "hook_common.h"
17 
18 constexpr static uint32_t DEFAULT_SLEEP_TIME_MS = 100; // milliseconds
19 constexpr static uint32_t DEFAULT_SLEEP_TIME_US = DEFAULT_SLEEP_TIME_MS * 1000;
20 using namespace OHOS::Developtools::NativeDaemon;
21 
StackDataRepeater(size_t maxSize)22 StackDataRepeater::StackDataRepeater(size_t maxSize)
23 {
24     maxSize_ = maxSize;
25     closed_ = false;
26     reducedStackCount_ = 0;
27 }
28 
~StackDataRepeater()29 StackDataRepeater::~StackDataRepeater()
30 {
31     Close();
32 }
33 
Size()34 size_t StackDataRepeater::Size()
35 {
36     std::unique_lock<std::mutex> lock(mutex_);
37     return rawDataQueue_.size();
38 }
39 
Reset()40 void StackDataRepeater::Reset()
41 {
42     std::unique_lock<std::mutex> lock(mutex_);
43     closed_ = false;
44 }
45 
Close()46 void StackDataRepeater::Close()
47 {
48     {
49         std::unique_lock<std::mutex> lock(mutex_);
50         rawDataQueue_.clear();
51         closed_ = true;
52     }
53     HILOG_INFO(LOG_CORE, "StackDataRepeater Close, reducedStackCount_ : %" PRIx64 " ", reducedStackCount_);
54     slotCondVar_.notify_all();
55     itemCondVar_.notify_all();
56 }
57 
PutRawStack(const RawStackPtr & rawData)58 bool StackDataRepeater::PutRawStack(const RawStackPtr& rawData)
59 {
60     bool needInsert = true;
61     std::unique_lock<std::mutex> lock(mutex_);
62 
63     if ((rawData == nullptr) && (rawDataQueue_.size() > 0)) {
64         HILOG_INFO(LOG_CORE, "no need put nullptr if queue has data, rawDataQueue_.size() = %zu", rawDataQueue_.size());
65         return true;
66     }
67     while (rawDataQueue_.size() >= maxSize_ && !closed_) {
68         slotCondVar_.wait(lock);
69     }
70     if (closed_) {
71         return false;
72     }
73 
74     if (__builtin_expect(rawData != nullptr, true)) {
75         if (rawData->stackConext.type == FREE_MSG) {
76             auto temp = mallocMap_.find(rawData->stackConext.addr);
77             // true  : pair of malloc and free matched, both malloc and free will be ignored
78             // false : can not match, send free's data anyway
79             if (temp != mallocMap_.end()) {
80                 temp->second->reportFlag = false; // will be ignore later
81                 mallocMap_.erase(rawData->stackConext.addr);
82                 needInsert = false;
83             }
84         } else if (rawData->stackConext.type == MALLOC_MSG) {
85             mallocMap_.insert(std::pair<void *, std::shared_ptr<RawStack>>(rawData->stackConext.addr, rawData));
86         }
87     }
88     if (needInsert) {
89         rawDataQueue_.push_back(rawData);
90     }
91     lock.unlock();
92     itemCondVar_.notify_one();
93     return true;
94 }
95 
TakeRawData(uint32_t during,uint32_t batchCount,RawStackPtr batchRawStack[])96 RawStackPtr StackDataRepeater::TakeRawData(uint32_t during, uint32_t batchCount, RawStackPtr batchRawStack[])
97 {
98     uint32_t rawDataQueueSize = 0;
99     std::unique_lock<std::mutex> lock(mutex_);
100     while (rawDataQueue_.empty() && !closed_) {
101         itemCondVar_.wait(lock);
102     }
103     if (closed_) {
104         return nullptr;
105     }
106     RawStackPtr result = nullptr;
107     rawDataQueueSize = rawDataQueue_.size();
108     int resultSize = rawDataQueueSize > batchCount ? batchCount : rawDataQueueSize;
109     bool needReduceStack = rawDataQueueSize >= SPEED_UP_THRESHOLD;
110     for (int i = 0; i < resultSize; i++) {
111         result = rawDataQueue_.front();
112         rawDataQueue_.pop_front();
113         batchRawStack[i] = result;
114         if ((result != nullptr) && (result->stackConext.type == MALLOC_MSG)) {
115             mallocMap_.erase(result->stackConext.addr);
116             if (needReduceStack) {
117                 result->reduceStackFlag = true;
118                 reducedStackCount_++;
119             }
120         }
121     }
122 
123     lock.unlock();
124     slotCondVar_.notify_one();
125     if (result != nullptr && during > 0 && rawDataQueueSize < SLOW_DOWN_THRESHOLD) {
126         struct timespec now = {};
127         clock_gettime(CLOCK_REALTIME, &now);
128         uint64_t curDuring = (now.tv_sec - result->stackConext.ts.tv_sec) * 1000;
129         int diff = during - curDuring;
130         if (diff > 0) {
131             HILOG_INFO(LOG_CORE, "TakeRawData sleep  diff %d, rawDataQueueSize %d", diff, rawDataQueueSize);
132             int cnt = diff / DEFAULT_SLEEP_TIME_MS;
133             while (!closed_ && cnt-- > 0) {
134                 usleep(DEFAULT_SLEEP_TIME_US);
135             }
136         }
137     }
138     return result;
139 }