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