1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci 16cc290419Sopenharmony_ci#include "circle_buffer.h" 17cc290419Sopenharmony_ci#include "base.h" 18cc290419Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INIF 19cc290419Sopenharmony_ci#include <malloc.h> 20cc290419Sopenharmony_ci#endif 21cc290419Sopenharmony_ci 22cc290419Sopenharmony_cinamespace Hdc { 23cc290419Sopenharmony_ciCircleBuffer::CircleBuffer() 24cc290419Sopenharmony_ci{ 25cc290419Sopenharmony_ci run_ = false; 26cc290419Sopenharmony_ci TimerStart(); 27cc290419Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INIF 28cc290419Sopenharmony_ci mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); 29cc290419Sopenharmony_ci mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); 30cc290419Sopenharmony_ci#endif 31cc290419Sopenharmony_ci} 32cc290419Sopenharmony_ci 33cc290419Sopenharmony_ciCircleBuffer::~CircleBuffer() 34cc290419Sopenharmony_ci{ 35cc290419Sopenharmony_ci TimerStop(); 36cc290419Sopenharmony_ci for (auto iter = buffers_.begin(); iter != buffers_.end();) { 37cc290419Sopenharmony_ci Data *data = iter->second; 38cc290419Sopenharmony_ci delete[] data->buf; 39cc290419Sopenharmony_ci delete data; 40cc290419Sopenharmony_ci iter = buffers_.erase(iter); 41cc290419Sopenharmony_ci } 42cc290419Sopenharmony_ci} 43cc290419Sopenharmony_ci 44cc290419Sopenharmony_ciuint8_t *CircleBuffer::Malloc() 45cc290419Sopenharmony_ci{ 46cc290419Sopenharmony_ci const size_t bufSize = static_cast<size_t>(Base::GetUsbffsBulkSize()); 47cc290419Sopenharmony_ci uint8_t *buf = nullptr; 48cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 49cc290419Sopenharmony_ci for (auto iter = buffers_.begin(); iter != buffers_.end(); ++iter) { 50cc290419Sopenharmony_ci Data *data = iter->second; 51cc290419Sopenharmony_ci if (data->used == false) { 52cc290419Sopenharmony_ci data->used = true; 53cc290419Sopenharmony_ci data->begin = std::chrono::steady_clock::now(); 54cc290419Sopenharmony_ci buf = data->buf; 55cc290419Sopenharmony_ci break; 56cc290419Sopenharmony_ci } 57cc290419Sopenharmony_ci } 58cc290419Sopenharmony_ci if (buf == nullptr) { 59cc290419Sopenharmony_ci Data *data = new(std::nothrow) Data(); 60cc290419Sopenharmony_ci if (data == nullptr) { 61cc290419Sopenharmony_ci return nullptr; 62cc290419Sopenharmony_ci } 63cc290419Sopenharmony_ci data->used = true; 64cc290419Sopenharmony_ci data->begin = std::chrono::steady_clock::now(); 65cc290419Sopenharmony_ci data->buf = new(std::nothrow) uint8_t[bufSize]; 66cc290419Sopenharmony_ci if (data->buf == nullptr) { 67cc290419Sopenharmony_ci delete data; 68cc290419Sopenharmony_ci return nullptr; 69cc290419Sopenharmony_ci } 70cc290419Sopenharmony_ci uint64_t key = reinterpret_cast<uint64_t>(data->buf); 71cc290419Sopenharmony_ci buffers_[key] = data; 72cc290419Sopenharmony_ci buf = data->buf; 73cc290419Sopenharmony_ci } 74cc290419Sopenharmony_ci (void)memset_s(buf, bufSize, 0, bufSize); 75cc290419Sopenharmony_ci return buf; 76cc290419Sopenharmony_ci} 77cc290419Sopenharmony_ci 78cc290419Sopenharmony_civoid CircleBuffer::Free(const uint8_t *buf) 79cc290419Sopenharmony_ci{ 80cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 81cc290419Sopenharmony_ci uint64_t key = reinterpret_cast<uint64_t>(buf); 82cc290419Sopenharmony_ci Data *data = buffers_[key]; 83cc290419Sopenharmony_ci if (data != nullptr) { 84cc290419Sopenharmony_ci data->used = false; 85cc290419Sopenharmony_ci data->begin = std::chrono::steady_clock::now(); 86cc290419Sopenharmony_ci } else { 87cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Free data is nullptr."); 88cc290419Sopenharmony_ci } 89cc290419Sopenharmony_ci} 90cc290419Sopenharmony_ci 91cc290419Sopenharmony_civoid CircleBuffer::FreeMemory() 92cc290419Sopenharmony_ci{ 93cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 94cc290419Sopenharmony_ci constexpr int64_t decreaseTime = 5; // 5s 95cc290419Sopenharmony_ci auto end = std::chrono::steady_clock::now(); 96cc290419Sopenharmony_ci for (auto iter = buffers_.begin(); iter != buffers_.end();) { 97cc290419Sopenharmony_ci bool remove = false; 98cc290419Sopenharmony_ci Data *data = iter->second; 99cc290419Sopenharmony_ci if (data->used == false) { 100cc290419Sopenharmony_ci auto begin = data->begin; 101cc290419Sopenharmony_ci auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - begin); 102cc290419Sopenharmony_ci if (duration.count() > decreaseTime) { 103cc290419Sopenharmony_ci remove = true; 104cc290419Sopenharmony_ci } 105cc290419Sopenharmony_ci } 106cc290419Sopenharmony_ci if (remove) { 107cc290419Sopenharmony_ci delete[] data->buf; 108cc290419Sopenharmony_ci delete data; 109cc290419Sopenharmony_ci iter = buffers_.erase(iter); 110cc290419Sopenharmony_ci } else { 111cc290419Sopenharmony_ci ++iter; 112cc290419Sopenharmony_ci } 113cc290419Sopenharmony_ci } 114cc290419Sopenharmony_ci} 115cc290419Sopenharmony_ci 116cc290419Sopenharmony_civoid CircleBuffer::Timer(void *object) 117cc290419Sopenharmony_ci{ 118cc290419Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INIF 119cc290419Sopenharmony_ci mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); 120cc290419Sopenharmony_ci mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); 121cc290419Sopenharmony_ci#endif 122cc290419Sopenharmony_ci CircleBuffer *cirbuf = reinterpret_cast<CircleBuffer *>(object); 123cc290419Sopenharmony_ci while (cirbuf->run_) { 124cc290419Sopenharmony_ci cirbuf->FreeMemory(); 125cc290419Sopenharmony_ci cirbuf->TimerSleep(); 126cc290419Sopenharmony_ci } 127cc290419Sopenharmony_ci} 128cc290419Sopenharmony_ci 129cc290419Sopenharmony_civoid CircleBuffer::TimerStart() 130cc290419Sopenharmony_ci{ 131cc290419Sopenharmony_ci#ifndef HDC_HOST 132cc290419Sopenharmony_ci if (!run_) { 133cc290419Sopenharmony_ci run_ = true; 134cc290419Sopenharmony_ci thread_ = std::thread([this]() { Timer(this); }); 135cc290419Sopenharmony_ci } 136cc290419Sopenharmony_ci#endif 137cc290419Sopenharmony_ci} 138cc290419Sopenharmony_ci 139cc290419Sopenharmony_civoid CircleBuffer::TimerStop() 140cc290419Sopenharmony_ci{ 141cc290419Sopenharmony_ci#ifndef HDC_HOST 142cc290419Sopenharmony_ci if (run_) { 143cc290419Sopenharmony_ci run_ = false; 144cc290419Sopenharmony_ci TimerNotify(); 145cc290419Sopenharmony_ci thread_.join(); 146cc290419Sopenharmony_ci } 147cc290419Sopenharmony_ci#endif 148cc290419Sopenharmony_ci} 149cc290419Sopenharmony_ci 150cc290419Sopenharmony_civoid CircleBuffer::TimerSleep() 151cc290419Sopenharmony_ci{ 152cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(timerMutex_); 153cc290419Sopenharmony_ci timerCv_.wait_for(lock, std::chrono::seconds(1)); 154cc290419Sopenharmony_ci} 155cc290419Sopenharmony_ci 156cc290419Sopenharmony_civoid CircleBuffer::TimerNotify() 157cc290419Sopenharmony_ci{ 158cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(timerMutex_); 159cc290419Sopenharmony_ci timerCv_.notify_one(); 160cc290419Sopenharmony_ci} 161cc290419Sopenharmony_ci} 162