1fa7767c5Sopenharmony_ci/* 2fa7767c5Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3fa7767c5Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fa7767c5Sopenharmony_ci * you may not use this file except in compliance with the License. 5fa7767c5Sopenharmony_ci * You may obtain a copy of the License at 6fa7767c5Sopenharmony_ci * 7fa7767c5Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fa7767c5Sopenharmony_ci * 9fa7767c5Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fa7767c5Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fa7767c5Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fa7767c5Sopenharmony_ci * See the License for the specific language governing permissions and 13fa7767c5Sopenharmony_ci * limitations under the License. 14fa7767c5Sopenharmony_ci */ 15fa7767c5Sopenharmony_ci 16fa7767c5Sopenharmony_ci#include "buffer/avsharedmemorybase.h" 17fa7767c5Sopenharmony_ci#include "common/avsharedmemorypool.h" 18fa7767c5Sopenharmony_ci#include "common/log.h" 19fa7767c5Sopenharmony_ci#include "scope_guard.h" 20fa7767c5Sopenharmony_ci 21fa7767c5Sopenharmony_cinamespace { 22fa7767c5Sopenharmony_ciconstexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "AVSharedMemoryPool" }; 23fa7767c5Sopenharmony_ci} 24fa7767c5Sopenharmony_ci 25fa7767c5Sopenharmony_cinamespace { 26fa7767c5Sopenharmony_ci constexpr int32_t MAX_MEM_SIZE = 100 * 1024 * 1024; 27fa7767c5Sopenharmony_ci} 28fa7767c5Sopenharmony_ci 29fa7767c5Sopenharmony_cinamespace OHOS { 30fa7767c5Sopenharmony_cinamespace Media { 31fa7767c5Sopenharmony_ciAVSharedMemoryPool::AVSharedMemoryPool(const std::string &name) : name_(name) 32fa7767c5Sopenharmony_ci{ 33fa7767c5Sopenharmony_ci MEDIA_LOG_D("enter ctor, 0x%{public}06" PRIXPTR ", name: %{public}s", FAKE_POINTER(this), name_.c_str()); 34fa7767c5Sopenharmony_ci} 35fa7767c5Sopenharmony_ci 36fa7767c5Sopenharmony_ciAVSharedMemoryPool::~AVSharedMemoryPool() 37fa7767c5Sopenharmony_ci{ 38fa7767c5Sopenharmony_ci MEDIA_LOG_D("enter dtor, 0x%{public}06" PRIXPTR ", name: %{public}s", FAKE_POINTER(this), name_.c_str()); 39fa7767c5Sopenharmony_ci Reset(); 40fa7767c5Sopenharmony_ci} 41fa7767c5Sopenharmony_ci 42fa7767c5Sopenharmony_ciint32_t AVSharedMemoryPool::Init(const InitializeOption &option) 43fa7767c5Sopenharmony_ci{ 44fa7767c5Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 45fa7767c5Sopenharmony_ci 46fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(!inited_, -1, "memory pool has inited."); 47fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(option.memSize < MAX_MEM_SIZE, -1, "memSize is larger than MAX_MEM_SIZE."); 48fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(option.maxMemCnt != 0, -1, "maxMemCnt is equal to zero."); 49fa7767c5Sopenharmony_ci 50fa7767c5Sopenharmony_ci option_ = option; 51fa7767c5Sopenharmony_ci option_.preAllocMemCnt = std::min(option.preAllocMemCnt, option.maxMemCnt); 52fa7767c5Sopenharmony_ci 53fa7767c5Sopenharmony_ci MEDIA_LOG_I("name: %{public}s, init option: preAllocMemCnt = %{public}u, memSize = %{public}d, " 54fa7767c5Sopenharmony_ci "maxMemCnt = %{public}u, enableFixedSize = %{public}d", 55fa7767c5Sopenharmony_ci name_.c_str(), option_.preAllocMemCnt, option_.memSize, option_.maxMemCnt, 56fa7767c5Sopenharmony_ci option_.enableFixedSize); 57fa7767c5Sopenharmony_ci for (uint32_t i = 0; i < option_.preAllocMemCnt; ++i) { 58fa7767c5Sopenharmony_ci auto memory = AllocMemory(option_.memSize); 59fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(memory != nullptr, -1, "failed to AllocMemory"); 60fa7767c5Sopenharmony_ci idleList_.push_back(memory); 61fa7767c5Sopenharmony_ci } 62fa7767c5Sopenharmony_ci 63fa7767c5Sopenharmony_ci inited_ = true; 64fa7767c5Sopenharmony_ci notifier_ = option.notifier; 65fa7767c5Sopenharmony_ci return 0; 66fa7767c5Sopenharmony_ci} 67fa7767c5Sopenharmony_ci 68fa7767c5Sopenharmony_ciAVSharedMemory *AVSharedMemoryPool::AllocMemory(int32_t size) 69fa7767c5Sopenharmony_ci{ 70fa7767c5Sopenharmony_ci AVSharedMemoryBase *memory = new (std::nothrow) AVSharedMemoryBase(size, option_.flags, name_); 71fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(memory != nullptr, nullptr, "create object failed"); 72fa7767c5Sopenharmony_ci ON_SCOPE_EXIT(0) { delete memory; }; 73fa7767c5Sopenharmony_ci memory->Init(); 74fa7767c5Sopenharmony_ci int32_t ret = memory->Init(); 75fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(ret == 0, nullptr, "init avsharedmemorybase failed"); 76fa7767c5Sopenharmony_ci 77fa7767c5Sopenharmony_ci CANCEL_SCOPE_EXIT_GUARD(0); 78fa7767c5Sopenharmony_ci return memory; 79fa7767c5Sopenharmony_ci} 80fa7767c5Sopenharmony_ci 81fa7767c5Sopenharmony_civoid AVSharedMemoryPool::ReleaseMemory(AVSharedMemory *memory) 82fa7767c5Sopenharmony_ci{ 83fa7767c5Sopenharmony_ci FALSE_LOG_MSG(memory != nullptr, "memory is nullptr"); 84fa7767c5Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 85fa7767c5Sopenharmony_ci 86fa7767c5Sopenharmony_ci for (auto iter = busyList_.begin(); iter != busyList_.end(); ++iter) { 87fa7767c5Sopenharmony_ci if (*iter != memory) { 88fa7767c5Sopenharmony_ci continue; 89fa7767c5Sopenharmony_ci } 90fa7767c5Sopenharmony_ci 91fa7767c5Sopenharmony_ci busyList_.erase(iter); 92fa7767c5Sopenharmony_ci idleList_.push_back(memory); 93fa7767c5Sopenharmony_ci cond_.notify_all(); 94fa7767c5Sopenharmony_ci MEDIA_LOG_D("0x%{public}06" PRIXPTR " released back to pool %{public}s", 95fa7767c5Sopenharmony_ci FAKE_POINTER(memory), name_.c_str()); 96fa7767c5Sopenharmony_ci 97fa7767c5Sopenharmony_ci lock.unlock(); 98fa7767c5Sopenharmony_ci if (notifier_ != nullptr) { 99fa7767c5Sopenharmony_ci notifier_(); 100fa7767c5Sopenharmony_ci } 101fa7767c5Sopenharmony_ci return; 102fa7767c5Sopenharmony_ci } 103fa7767c5Sopenharmony_ci 104fa7767c5Sopenharmony_ci MEDIA_LOG_E("0x%{public}06" PRIXPTR " is no longer managed by this pool", FAKE_POINTER(memory)); 105fa7767c5Sopenharmony_ci delete memory; 106fa7767c5Sopenharmony_ci} 107fa7767c5Sopenharmony_ci 108fa7767c5Sopenharmony_cibool AVSharedMemoryPool::DoAcquireMemory(int32_t size, AVSharedMemory **outMemory) 109fa7767c5Sopenharmony_ci{ 110fa7767c5Sopenharmony_ci MEDIA_LOG_D("busylist size " PUBLIC_LOG_ZU ", idlelist size " PUBLIC_LOG_ZU, busyList_.size(), idleList_.size()); 111fa7767c5Sopenharmony_ci 112fa7767c5Sopenharmony_ci AVSharedMemory *result = nullptr; 113fa7767c5Sopenharmony_ci std::list<AVSharedMemory *>::iterator minSizeIdleMem = idleList_.end(); 114fa7767c5Sopenharmony_ci int32_t minIdleSize = std::numeric_limits<int32_t>::max(); 115fa7767c5Sopenharmony_ci 116fa7767c5Sopenharmony_ci for (auto iter = idleList_.begin(); iter != idleList_.end(); ++iter) { 117fa7767c5Sopenharmony_ci if ((*iter)->GetSize() >= size) { 118fa7767c5Sopenharmony_ci result = *iter; 119fa7767c5Sopenharmony_ci idleList_.erase(iter); 120fa7767c5Sopenharmony_ci break; 121fa7767c5Sopenharmony_ci } 122fa7767c5Sopenharmony_ci 123fa7767c5Sopenharmony_ci if ((*iter)->GetSize() < minIdleSize) { 124fa7767c5Sopenharmony_ci minIdleSize = (*iter)->GetSize(); 125fa7767c5Sopenharmony_ci minSizeIdleMem = iter; 126fa7767c5Sopenharmony_ci } 127fa7767c5Sopenharmony_ci } 128fa7767c5Sopenharmony_ci 129fa7767c5Sopenharmony_ci if (result == nullptr) { 130fa7767c5Sopenharmony_ci auto totalCnt = busyList_.size() + idleList_.size(); 131fa7767c5Sopenharmony_ci if (totalCnt < option_.maxMemCnt) { 132fa7767c5Sopenharmony_ci result = AllocMemory(size); 133fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(result != nullptr, false, "result is nullptr"); 134fa7767c5Sopenharmony_ci FALSE_RETURN_V(result != nullptr, false); 135fa7767c5Sopenharmony_ci } 136fa7767c5Sopenharmony_ci 137fa7767c5Sopenharmony_ci if (!option_.enableFixedSize && minSizeIdleMem != idleList_.end()) { 138fa7767c5Sopenharmony_ci delete *minSizeIdleMem; 139fa7767c5Sopenharmony_ci *minSizeIdleMem = nullptr; 140fa7767c5Sopenharmony_ci idleList_.erase(minSizeIdleMem); 141fa7767c5Sopenharmony_ci result = AllocMemory(size); 142fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(result != nullptr, false, "result is nullptr"); 143fa7767c5Sopenharmony_ci FALSE_RETURN_V(result != nullptr, false); 144fa7767c5Sopenharmony_ci } 145fa7767c5Sopenharmony_ci } 146fa7767c5Sopenharmony_ci 147fa7767c5Sopenharmony_ci *outMemory = result; 148fa7767c5Sopenharmony_ci return true; 149fa7767c5Sopenharmony_ci} 150fa7767c5Sopenharmony_ci 151fa7767c5Sopenharmony_cibool AVSharedMemoryPool::CheckSize(int32_t size) 152fa7767c5Sopenharmony_ci{ 153fa7767c5Sopenharmony_ci if (size <= 0 && size != -1) { 154fa7767c5Sopenharmony_ci return false; 155fa7767c5Sopenharmony_ci } 156fa7767c5Sopenharmony_ci 157fa7767c5Sopenharmony_ci if (!option_.enableFixedSize && size == -1) { 158fa7767c5Sopenharmony_ci return false; 159fa7767c5Sopenharmony_ci } 160fa7767c5Sopenharmony_ci 161fa7767c5Sopenharmony_ci if (option_.enableFixedSize) { 162fa7767c5Sopenharmony_ci if (size > option_.memSize) { 163fa7767c5Sopenharmony_ci return false; 164fa7767c5Sopenharmony_ci } 165fa7767c5Sopenharmony_ci 166fa7767c5Sopenharmony_ci if (size <= 0 && size != -1) { 167fa7767c5Sopenharmony_ci return false; 168fa7767c5Sopenharmony_ci } 169fa7767c5Sopenharmony_ci } 170fa7767c5Sopenharmony_ci 171fa7767c5Sopenharmony_ci return true; 172fa7767c5Sopenharmony_ci} 173fa7767c5Sopenharmony_ci 174fa7767c5Sopenharmony_cistd::shared_ptr<AVSharedMemory> AVSharedMemoryPool::AcquireMemory(int32_t size, bool blocking) 175fa7767c5Sopenharmony_ci{ 176fa7767c5Sopenharmony_ci MEDIA_LOG_D("acquire memory for size: %{public}d from pool %{public}s, blocking: %{public}d", 177fa7767c5Sopenharmony_ci size, name_.c_str(), blocking); 178fa7767c5Sopenharmony_ci 179fa7767c5Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 180fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(CheckSize(size), nullptr, "invalid size: %{public}d", size); 181fa7767c5Sopenharmony_ci 182fa7767c5Sopenharmony_ci if (option_.enableFixedSize) { 183fa7767c5Sopenharmony_ci size = option_.memSize; 184fa7767c5Sopenharmony_ci } 185fa7767c5Sopenharmony_ci 186fa7767c5Sopenharmony_ci AVSharedMemory *memory = nullptr; 187fa7767c5Sopenharmony_ci do { 188fa7767c5Sopenharmony_ci if (!DoAcquireMemory(size, &memory) || memory != nullptr) { 189fa7767c5Sopenharmony_ci break; 190fa7767c5Sopenharmony_ci } 191fa7767c5Sopenharmony_ci 192fa7767c5Sopenharmony_ci if (!blocking || forceNonBlocking_) { 193fa7767c5Sopenharmony_ci break; 194fa7767c5Sopenharmony_ci } 195fa7767c5Sopenharmony_ci 196fa7767c5Sopenharmony_ci cond_.wait(lock); 197fa7767c5Sopenharmony_ci } while (inited_ && !forceNonBlocking_); 198fa7767c5Sopenharmony_ci 199fa7767c5Sopenharmony_ci FALSE_RETURN_V_MSG_E(memory != nullptr, nullptr, "acquire memory failed for size: %{public}d", size); 200fa7767c5Sopenharmony_ci busyList_.push_back(memory); 201fa7767c5Sopenharmony_ci 202fa7767c5Sopenharmony_ci auto result = std::shared_ptr<AVSharedMemory>(memory, [weakPool = weak_from_this()](AVSharedMemory *memory) { 203fa7767c5Sopenharmony_ci std::shared_ptr<AVSharedMemoryPool> pool = weakPool.lock(); 204fa7767c5Sopenharmony_ci if (pool != nullptr) { 205fa7767c5Sopenharmony_ci pool->ReleaseMemory(memory); 206fa7767c5Sopenharmony_ci } else { 207fa7767c5Sopenharmony_ci MEDIA_LOG_I("release memory 0x%{public}06" PRIXPTR ", but the pool is destroyed", FAKE_POINTER(memory)); 208fa7767c5Sopenharmony_ci delete memory; 209fa7767c5Sopenharmony_ci } 210fa7767c5Sopenharmony_ci }); 211fa7767c5Sopenharmony_ci 212fa7767c5Sopenharmony_ci MEDIA_LOG_D("0x%{public}06" PRIXPTR " acquired from pool", FAKE_POINTER(memory)); 213fa7767c5Sopenharmony_ci return result; 214fa7767c5Sopenharmony_ci} 215fa7767c5Sopenharmony_ci 216fa7767c5Sopenharmony_civoid AVSharedMemoryPool::SetNonBlocking(bool enable) 217fa7767c5Sopenharmony_ci{ 218fa7767c5Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 219fa7767c5Sopenharmony_ci MEDIA_LOG_D("SetNonBlocking: %{public}d", enable); 220fa7767c5Sopenharmony_ci forceNonBlocking_ = enable; 221fa7767c5Sopenharmony_ci if (forceNonBlocking_) { 222fa7767c5Sopenharmony_ci cond_.notify_all(); 223fa7767c5Sopenharmony_ci } 224fa7767c5Sopenharmony_ci} 225fa7767c5Sopenharmony_ci 226fa7767c5Sopenharmony_civoid AVSharedMemoryPool::Reset() 227fa7767c5Sopenharmony_ci{ 228fa7767c5Sopenharmony_ci MEDIA_LOG_D("Reset"); 229fa7767c5Sopenharmony_ci 230fa7767c5Sopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 231fa7767c5Sopenharmony_ci for (auto &memory : idleList_) { 232fa7767c5Sopenharmony_ci delete memory; 233fa7767c5Sopenharmony_ci memory = nullptr; 234fa7767c5Sopenharmony_ci } 235fa7767c5Sopenharmony_ci idleList_.clear(); 236fa7767c5Sopenharmony_ci inited_ = false; 237fa7767c5Sopenharmony_ci forceNonBlocking_ = false; 238fa7767c5Sopenharmony_ci notifier_ = nullptr; 239fa7767c5Sopenharmony_ci cond_.notify_all(); 240fa7767c5Sopenharmony_ci // for busylist, the memory will be released when the refcount of shared_ptr is zero. 241fa7767c5Sopenharmony_ci} 242fa7767c5Sopenharmony_ci} // namespace Media 243fa7767c5Sopenharmony_ci} // namespace OHOS