• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 
16 #include "circle_buffer.h"
17 #include "base.h"
18 #ifdef CONFIG_USE_JEMALLOC_DFX_INIF
19 #include <malloc.h>
20 #endif
21 
22 namespace Hdc {
CircleBuffer()23 CircleBuffer::CircleBuffer()
24 {
25     run_ = false;
26     TimerStart();
27 #ifdef CONFIG_USE_JEMALLOC_DFX_INIF
28     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
29     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
30 #endif
31 }
32 
~CircleBuffer()33 CircleBuffer::~CircleBuffer()
34 {
35     TimerStop();
36     for (auto iter = buffers_.begin(); iter != buffers_.end();) {
37         Data *data = iter->second;
38         delete[] data->buf;
39         delete data;
40         iter = buffers_.erase(iter);
41     }
42 }
43 
Malloc()44 uint8_t *CircleBuffer::Malloc()
45 {
46     const size_t bufSize = static_cast<size_t>(Base::GetUsbffsBulkSize());
47     uint8_t *buf = nullptr;
48     std::unique_lock<std::mutex> lock(mutex_);
49     for (auto iter = buffers_.begin(); iter != buffers_.end(); ++iter) {
50         Data *data = iter->second;
51         if (data->used == false) {
52             data->used = true;
53             data->begin = std::chrono::steady_clock::now();
54             buf = data->buf;
55             break;
56         }
57     }
58     if (buf == nullptr) {
59         Data *data = new(std::nothrow) Data();
60         if (data == nullptr) {
61             return nullptr;
62         }
63         data->used = true;
64         data->begin = std::chrono::steady_clock::now();
65         data->buf = new(std::nothrow) uint8_t[bufSize];
66         if (data->buf == nullptr) {
67             delete data;
68             return nullptr;
69         }
70         uint64_t key = reinterpret_cast<uint64_t>(data->buf);
71         buffers_[key] = data;
72         buf = data->buf;
73     }
74     (void)memset_s(buf, bufSize, 0, bufSize);
75     return buf;
76 }
77 
Free(const uint8_t * buf)78 void CircleBuffer::Free(const uint8_t *buf)
79 {
80     std::unique_lock<std::mutex> lock(mutex_);
81     uint64_t key = reinterpret_cast<uint64_t>(buf);
82     auto findData = buffers_.find(key);
83     if (findData == buffers_.end()) {
84         WRITE_LOG(LOG_FATAL, "Free data not found.");
85         return;
86     }
87     Data *data = findData->second;
88     if (data != nullptr) {
89         data->used = false;
90         data->begin = std::chrono::steady_clock::now();
91     } else {
92         WRITE_LOG(LOG_FATAL, "Free data is nullptr.");
93     }
94 }
95 
FreeMemory()96 void CircleBuffer::FreeMemory()
97 {
98     std::unique_lock<std::mutex> lock(mutex_);
99     constexpr int64_t decreaseTime = 5; // 5s
100     auto end = std::chrono::steady_clock::now();
101     for (auto iter = buffers_.begin(); iter != buffers_.end();) {
102         bool remove = false;
103         Data *data = iter->second;
104         if (data->used == false) {
105             auto begin = data->begin;
106             auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - begin);
107             if (duration.count() > decreaseTime) {
108                 remove = true;
109             }
110         }
111         if (remove) {
112             delete[] data->buf;
113             delete data;
114             iter = buffers_.erase(iter);
115         } else {
116             ++iter;
117         }
118     }
119 }
120 
Timer(void * object)121 void CircleBuffer::Timer(void *object)
122 {
123 #ifdef CONFIG_USE_JEMALLOC_DFX_INIF
124     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
125     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
126 #endif
127     CircleBuffer *cirbuf = reinterpret_cast<CircleBuffer *>(object);
128     while (cirbuf->run_) {
129         cirbuf->FreeMemory();
130         cirbuf->TimerSleep();
131     }
132 }
133 
TimerStart()134 void CircleBuffer::TimerStart()
135 {
136 #ifndef HDC_HOST
137     if (!run_) {
138         run_ = true;
139         thread_ = std::thread([this]() { Timer(this); });
140     }
141 #endif
142 }
143 
TimerStop()144 void CircleBuffer::TimerStop()
145 {
146 #ifndef HDC_HOST
147     if (run_) {
148         run_ = false;
149         TimerNotify();
150         thread_.join();
151     }
152 #endif
153 }
154 
TimerSleep()155 void CircleBuffer::TimerSleep()
156 {
157     std::unique_lock<std::mutex> lock(timerMutex_);
158     timerCv_.wait_for(lock, std::chrono::seconds(1));
159 }
160 
TimerNotify()161 void CircleBuffer::TimerNotify()
162 {
163     std::unique_lock<std::mutex> lock(timerMutex_);
164     timerCv_.notify_one();
165 }
166 }
167