From 7b80df65ed3cdf180875b53677fb7fb11189041e Mon Sep 17 00:00:00 2001 From: x00678224 Date: Wed, 26 Apr 2023 15:32:52 +0800 Subject: [PATCH] make pixelmap to be purgeable Signed-off-by: x00678224 Change-Id: Iceb83f5631ebd3c9bc2b1c4cbd37f472147cdf53 --- bundle.json | 10 +- libpurgeablemem/BUILD.gn | 6 +- .../cpp/include/purgeable_ashmem.h | 2 +- .../cpp/include/purgeable_mem_builder.h | 7 + .../include/purgeable_resource_interface.h | 75 ++++++++ .../cpp/include/purgeable_resource_manager.h | 161 ++++++++++++++++++ libpurgeablemem/cpp/src/purgeable_ashmem.cpp | 4 +- .../cpp/src/purgeable_resource_manager.cpp | 145 ++++++++++++++++ libpurgeablemem/test/purgeable_cpp_test.cpp | 15 ++ libpurgeablemem/test/purgeableashmem_test.cpp | 15 ++ purgeable_mem_config.gni | 16 ++ 11 files changed, 451 insertions(+), 5 deletions(-) create mode 100644 libpurgeablemem/cpp/include/purgeable_resource_interface.h create mode 100644 libpurgeablemem/cpp/include/purgeable_resource_manager.h create mode 100644 libpurgeablemem/cpp/src/purgeable_resource_manager.cpp create mode 100644 purgeable_mem_config.gni diff --git a/bundle.json b/bundle.json index e56631a..319b595 100644 --- a/bundle.json +++ b/bundle.json @@ -40,9 +40,15 @@ "name": "//commonlibrary/memory_utils/libpurgeablemem:libpurgeablemem", "header": { "header_files": [ - "purgeable_mem_c.h" + "pm_log.h", + "pm_smartptr_util.h", + "purgeable_ashmem.h", + "purgeable_mem.h", + "purgeable_mem_base.h", + "purgeable_mem_builder.h", + "ux_page_table.h" ], - "header_base": "//commonlibrary/memory_utils/libpurgeablemem/c/include" + "header_base": "//commonlibrary/memory_utils/libpurgeablemem/cpp/include" } } ], diff --git a/libpurgeablemem/BUILD.gn b/libpurgeablemem/BUILD.gn index bec592f..424b766 100644 --- a/libpurgeablemem/BUILD.gn +++ b/libpurgeablemem/BUILD.gn @@ -32,12 +32,16 @@ ohos_shared_library("libpurgeablemem") { "cpp/src/purgeable_mem.cpp", "cpp/src/purgeable_mem_base.cpp", "cpp/src/purgeable_mem_builder.cpp", + "cpp/src/purgeable_resource_manager.cpp", "cpp/src/ux_page_table.cpp", ] - include_dirs = [ "include" ] + include_dirs = [ "cpp/include" ] external_deps = [ "c_utils:utils", + "hitrace_native:hitrace_meter", "hiviewdfx_hilog_native:libhilog", + "init:libbegetutil", + "ipc:ipc_core", ] public_configs = [ ":libpurgeable_config" ] subsystem_name = "commonlibrary" diff --git a/libpurgeablemem/cpp/include/purgeable_ashmem.h b/libpurgeablemem/cpp/include/purgeable_ashmem.h index bf5f78e..5f18ca4 100644 --- a/libpurgeablemem/cpp/include/purgeable_ashmem.h +++ b/libpurgeablemem/cpp/include/purgeable_ashmem.h @@ -50,7 +50,7 @@ public: ~PurgeableAshMem() override; int GetAshmemFd(); void ResizeData(size_t newSize) override; - void ChangeAshmemData(size_t size, int fd, void *data); + bool ChangeAshmemData(size_t size, int fd, void *data); protected: int ashmemFd_; int isSupport_; diff --git a/libpurgeablemem/cpp/include/purgeable_mem_builder.h b/libpurgeablemem/cpp/include/purgeable_mem_builder.h index 9a3fbf0..7a4956a 100644 --- a/libpurgeablemem/cpp/include/purgeable_mem_builder.h +++ b/libpurgeablemem/cpp/include/purgeable_mem_builder.h @@ -37,6 +37,13 @@ public: */ virtual bool Build(void *data, size_t size) = 0; + /* + * User should define how to get the metaDataSize of a PurgeableMem obj in this func. + * MetaData is used to rebuild purgeableMem. + * Return: the meta data size. + */ + virtual size_t GetMetaDataSize() = 0; + private: std::unique_ptr nextBuilder_ = nullptr; diff --git a/libpurgeablemem/cpp/include/purgeable_resource_interface.h b/libpurgeablemem/cpp/include/purgeable_resource_interface.h new file mode 100644 index 0000000..18ff5a4 --- /dev/null +++ b/libpurgeablemem/cpp/include/purgeable_resource_interface.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_INTERFACE_H +#define OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_INTERFACE_H + +#include "hitrace_meter.h" +#include "pm_log.h" +#include "purgeable_ashmem.h" +#include "purgeable_mem_builder.h" + +namespace OHOS { +namespace PurgeableMem { +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "PurgeableResourceInterface" + +class PurgeableResourceInterface { +public: + /* + * BeginVisitPurgeableMem: begin visit the PurgeableMem obj. + * if the obj is present, this method will start accessing it by + * calling the obj's BeginRead() function. + */ + virtual uint32_t BeginVisitPurgeableMem() + { + return 0; + } + + /* + * EndVisitPurgeableMem: end visit the PurgeableMem obj. + * if the obj is present, this method will end accessing it by + * calling the obj's EndRead() function. + */ + virtual uint32_t EndVisitPurgeableMem() + { + return 0; + } + + /* + * SetPurgeable: set purgeable state of the PurgeableMem obj. + * Input: @flag: boolean type parameter, it's used to mark the purgeable state of the current obj. + */ + virtual void SetPurgeable(bool flag) + { + isPurgeable_ = flag; + } + + /* + * IsPurgeable: get purgeable state of the PurgeableMem obj. + * Return: boolean type parameter, it's used to mark the purgeable state of the current obj. + */ + virtual bool IsPurgeable() + { + return isPurgeable_; + } +protected: + bool isPurgeable_ = {false}; +}; +} /* namespace PurgeableMem */ +} /* namespace OHOS */ +#endif /* OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_INTERFACE_H */ diff --git a/libpurgeablemem/cpp/include/purgeable_resource_manager.h b/libpurgeablemem/cpp/include/purgeable_resource_manager.h new file mode 100644 index 0000000..e1e879a --- /dev/null +++ b/libpurgeablemem/cpp/include/purgeable_resource_manager.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_MANAGER_H +#define OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_MANAGER_H + +#include +#include +#include +#include + +#include "purgeable_resource_interface.h" +#include "thread_pool.h" + +namespace OHOS { +namespace PurgeableMem { +/* System parameter name */ +const std::string THREAD_POOL_TASK_NUMBER_SYS_NAME = "persist.commonlibrary.purgeable.threadpooltasknum"; +const std::string LRU_CACHE_CAPACITY_SYS_NAME = "persist.commonlibrary.purgeable.lrucachecapacity"; +/* Threadpool task number and lrucache capacity */ +constexpr int32_t THREAD_POOL_TASK_NUMBER = 5; +constexpr int32_t MIN_THREAD_POOL_TASK_NUMBER = 1; +constexpr int32_t MAX_THREAD_POOL_TASK_NUMBER = 20; +constexpr int32_t LRU_CACHE_CAPACITY = 50; +constexpr int32_t MIN_LRU_CACHE_CAPACITY = 1; +constexpr int32_t MAX_LRU_CACHE_CAPACITY = 100; + +class LruCache { +public: + int32_t lruCacheCapacity; + std::list resourcePtrList; + std::unordered_map::iterator> positionMap; + + /* + * Visited: visit the cache entry with the given key. + * If the entry is found, it will be move to the most-recent position in the cache. + */ + void Visited(PurgeableResourceInterface *key) + { + if (key == nullptr) { + return; + } + + auto resourcePtrIndex = positionMap.find((long) key); + if(resourcePtrIndex != positionMap.end()) { + resourcePtrList.splice(resourcePtrList.begin(), resourcePtrList, resourcePtrIndex->second); + return; + } + + return; + } + + /* + * Put: put the PurgeableResourceInterface key in the lrucache. + * Input: @key: ptr of PurgeableResourceInterface. + */ + void Put(PurgeableResourceInterface *key) + { + if (key == nullptr) { + return; + } + + auto resourcePtrIndex = positionMap.find((long) key); + if(resourcePtrIndex != positionMap.end()) { + resourcePtrList.splice(resourcePtrList.begin(), resourcePtrList, resourcePtrIndex->second); + return; + } + + resourcePtrList.emplace_front(key); + positionMap.emplace((long) key, resourcePtrList.begin()); + + if (static_cast(resourcePtrList.size()) > lruCacheCapacity) { + positionMap.erase((long) resourcePtrList.back()); + resourcePtrList.pop_back(); + } + return; + } + + /* + * Erase: erase the PurgeableResourceInterface key in the lrucache. + * Input: @key: ptr of PurgeableResourceInterface. + */ + void Erase(PurgeableResourceInterface *key) + { + if (key == nullptr) { + return; + } + + auto resourcePtrIndex = positionMap.find((long) key); + if(resourcePtrIndex == positionMap.end()) { + return; + } + + resourcePtrList.erase(resourcePtrIndex->second); + positionMap.erase((long) key); + return; + } + + /* + * SetCapacity: set the capacity of the lrucache. + * Input: the capacity of lrucache. + */ + void SetCapacity(int32_t capacity) + { + lruCacheCapacity = capacity; + } + + /* + * Clear: clear the resourcePtrList and positionMap of the lrucache. + */ + void Clear() + { + positionMap.clear(); + resourcePtrList.clear(); + } +}; + +class PurgeableResourceManager { +public: + PurgeableResourceManager() + { + GetParaFromConfiguration(); + } + + ~PurgeableResourceManager() + { + threadPool_.Stop(); + lruCache_.Clear(); + } + + static PurgeableResourceManager &GetInstance(); + void ExecBeginVisitPurgeableMem(); + void ExecEndVisitPurgeableMem(); + void AddResource(PurgeableResourceInterface *); + void RemoveResource(PurgeableResourceInterface *); + void SetRecentUsedResource(PurgeableResourceInterface *); + int32_t GetThreadPoolTaskNumFromSysPara(); + int32_t GetLruCacheCapacityFromSysPara(); + void GetParaFromConfiguration(); + +private: + std::mutex mutex_; + LruCache lruCache_; + ThreadPool threadPool_; +}; + +} /* namespace PurgeableMem */ +} /* namespace OHOS */ +#endif /* OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_MANAGER_H */ diff --git a/libpurgeablemem/cpp/src/purgeable_ashmem.cpp b/libpurgeablemem/cpp/src/purgeable_ashmem.cpp index 8462ce2..ea607fe 100644 --- a/libpurgeablemem/cpp/src/purgeable_ashmem.cpp +++ b/libpurgeablemem/cpp/src/purgeable_ashmem.cpp @@ -187,11 +187,12 @@ void PurgeableAshMem::ResizeData(size_t newSize) CreatePurgeableData_(); } -void PurgeableAshMem::ChangeAshmemData(size_t size, int fd, void *data) +bool PurgeableAshMem::ChangeAshmemData(size_t size, int fd, void *data) { if (dataPtr_) { if (munmap(dataPtr_, RoundUp_(dataSizeInput_, PAGE_SIZE)) != 0) { PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr fail", __func__); + return false; } else { dataPtr_ = nullptr; if (ashmemFd_ > 0) { @@ -208,6 +209,7 @@ void PurgeableAshMem::ChangeAshmemData(size_t size, int fd, void *data) isSupport_ = true; } Unpin_(); + return true; } inline std::string PurgeableAshMem::ToString_() const diff --git a/libpurgeablemem/cpp/src/purgeable_resource_manager.cpp b/libpurgeablemem/cpp/src/purgeable_resource_manager.cpp new file mode 100644 index 0000000..fb2233d --- /dev/null +++ b/libpurgeablemem/cpp/src/purgeable_resource_manager.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "hitrace_meter.h" +#include "parameters.h" +#include "pm_log.h" +#include "purgeable_resource_manager.h" + + +namespace OHOS { +namespace PurgeableMem { + +PurgeableResourceManager &PurgeableResourceManager::GetInstance() +{ + static PurgeableResourceManager instance; + return instance; +} + +void PurgeableResourceManager::ExecBeginVisitPurgeableMem() +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "PurgeableResourceManager::ExecBeginVisitPurgeableMem"); + for (auto &resourcePtr : lruCache_.resourcePtrList) { + if (resourcePtr == nullptr) { + continue; + } + + auto task = std::bind(&PurgeableResourceInterface::BeginVisitPurgeableMem, (PurgeableResourceInterface *) resourcePtr); + threadPool_.AddTask(task); + } + + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] ExecBeginVisitPurgeableMem list size: %{public}zu", + lruCache_.resourcePtrList.size()); + return; +} + +void PurgeableResourceManager::ExecEndVisitPurgeableMem() +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "PurgeableResourceManager::ExecUnPin"); + for (auto &resourcePtr : lruCache_.resourcePtrList) { + if (resourcePtr == nullptr) { + continue; + } + + auto task = std::bind(&PurgeableResourceInterface::EndVisitPurgeableMem, (PurgeableResourceInterface *) resourcePtr); + threadPool_.AddTask(task); + } + + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] ExecUnPin list size: %{public}zu", + lruCache_.resourcePtrList.size()); + return; +} + +void PurgeableResourceManager::AddResource(PurgeableResourceInterface *resourcePtr) +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "PurgeableResourceManager::AddResource"); + if (resourcePtr == nullptr) { + return; + } + + lruCache_.Put(resourcePtr); + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] AddResource list size: %{public}zu", + lruCache_.resourcePtrList.size()); +} + +void PurgeableResourceManager::RemoveResource(PurgeableResourceInterface *resourcePtr) +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "PurgeableResourceManager::RemoveResource"); + if (resourcePtr == nullptr) { + return; + } + + lruCache_.Erase(resourcePtr); + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] RemoveResource list size: %{public}zu", + lruCache_.resourcePtrList.size()); +} + +void PurgeableResourceManager::SetRecentUsedResource(PurgeableResourceInterface *resourcePtr) +{ + std::lock_guard lock(mutex_); + if (resourcePtr == nullptr) { + return; + } + + lruCache_.Visited(resourcePtr); +} + +int32_t PurgeableResourceManager::GetThreadPoolTaskNumFromSysPara() +{ + return system::GetIntParameter(THREAD_POOL_TASK_NUMBER_SYS_NAME, THREAD_POOL_TASK_NUMBER); +} + +int32_t PurgeableResourceManager::GetLruCacheCapacityFromSysPara() +{ + return system::GetIntParameter(LRU_CACHE_CAPACITY_SYS_NAME, LRU_CACHE_CAPACITY); +} + +void PurgeableResourceManager::GetParaFromConfiguration() +{ + int32_t threadPoolTaskNum = GetThreadPoolTaskNumFromSysPara(); + int32_t lruCacheCapacity = GetLruCacheCapacityFromSysPara(); + if (threadPoolTaskNum < MIN_THREAD_POOL_TASK_NUMBER || threadPoolTaskNum > MAX_THREAD_POOL_TASK_NUMBER) { + PM_HILOG_ERROR(LOG_CORE, "[PurgeableResourceManager] Get error threadpool task number from system parameter."); + return; + } + + if (lruCacheCapacity < MIN_LRU_CACHE_CAPACITY || lruCacheCapacity > MAX_LRU_CACHE_CAPACITY) { + PM_HILOG_ERROR(LOG_CORE, "[PurgeableResourceManager] Get error lrucache capacity from system parameter."); + return; + } + + lruCache_.SetCapacity(lruCacheCapacity); + if (threadPool_.GetThreadsNum() == 0) { + threadPool_.Start(threadPoolTaskNum); + } + + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] lruCacheCapacity is: %{public}zu", + lruCache_.resourcePtrList.size()); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] threadPool threadsNum is: %{public}zu", + threadPool_.GetThreadsNum()); +} +} /* namespace PurgeableMem */ +} /* namespace OHOS */ diff --git a/libpurgeablemem/test/purgeable_cpp_test.cpp b/libpurgeablemem/test/purgeable_cpp_test.cpp index c23f675..8c5c112 100644 --- a/libpurgeablemem/test/purgeable_cpp_test.cpp +++ b/libpurgeablemem/test/purgeable_cpp_test.cpp @@ -57,6 +57,11 @@ public: return true; } + size_t GetMetaDataSize() + { + return 0; + } + ~TestDataBuilder() { std::cout << "~TestDataBuilder" << std::endl; @@ -85,6 +90,11 @@ public: return true; } + size_t GetMetaDataSize() + { + return 0; + } + ~TestDataModifier() { std::cout << "~TestDataModifier" << std::endl; @@ -115,6 +125,11 @@ public: return true; } + size_t GetMetaDataSize() + { + return 0; + } + ~TestBigDataBuilder() { std::cout << "~TestBigDataBuilder" << std::endl; diff --git a/libpurgeablemem/test/purgeableashmem_test.cpp b/libpurgeablemem/test/purgeableashmem_test.cpp index 1340ed1..2471154 100644 --- a/libpurgeablemem/test/purgeableashmem_test.cpp +++ b/libpurgeablemem/test/purgeableashmem_test.cpp @@ -63,6 +63,11 @@ public: return true; } + size_t GetMetaDataSize() + { + return 0; + } + ~TestDataBuilder() { std::cout << "~TestDataBuilder" << std::endl; @@ -91,6 +96,11 @@ public: return true; } + size_t GetMetaDataSize() + { + return 0; + } + ~TestDataModifier() { std::cout << "~TestDataModifier" << std::endl; @@ -121,6 +131,11 @@ public: return true; } + size_t GetMetaDataSize() + { + return 0; + } + ~TestBigDataBuilder() { std::cout << "~TestBigDataBuilder" << std::endl; diff --git a/purgeable_mem_config.gni b/purgeable_mem_config.gni new file mode 100644 index 0000000..388025d --- /dev/null +++ b/purgeable_mem_config.gni @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +declare_args() { + purgeable_ashmem_enable = false +} -- Gitee