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 "hitrace_meter.h"
17 #include "parameters.h"
18 #include "pm_log.h"
19 #include "purgeable_mem_base.h"
20 #include "purgeable_resource_manager.h"
21
22 namespace OHOS {
23 namespace PurgeableMem {
24 namespace {
25 /* System parameter name */
26 const std::string LRU_CACHE_CAPACITY_SYS_NAME = "persist.commonlibrary.purgeable.lrucachecapacity";
27 constexpr int32_t LRU_CACHE_CAPACITY = 200;
28 constexpr int32_t MIN_LRU_CACHE_CAPACITY = 1;
29 constexpr int32_t MAX_LRU_CACHE_CAPACITY = 2000;
30 }
31
Visited(std::shared_ptr<PurgeableMemBase> key)32 void PurgeableResourceManager::LruCache::Visited(std::shared_ptr<PurgeableMemBase> key)
33 {
34 if (key == nullptr) {
35 return;
36 }
37
38 auto resourcePtrIter = positionMap_.find(key);
39 if (resourcePtrIter != positionMap_.end()) {
40 resourcePtrList_.splice(resourcePtrList_.begin(), resourcePtrList_, resourcePtrIter->second);
41 resourcePtrIter->second = resourcePtrList_.begin();
42 }
43 }
44
Insert(std::shared_ptr<PurgeableMemBase> key)45 void PurgeableResourceManager::LruCache::Insert(std::shared_ptr<PurgeableMemBase> key)
46 {
47 if (key == nullptr) {
48 return;
49 }
50
51 auto resourcePtrIter = positionMap_.find(key);
52 if (resourcePtrIter != positionMap_.end()) {
53 resourcePtrList_.splice(resourcePtrList_.begin(), resourcePtrList_, resourcePtrIter->second);
54 resourcePtrIter->second = resourcePtrList_.begin();
55 return;
56 }
57
58 resourcePtrList_.emplace_front(key);
59 positionMap_.emplace(key, resourcePtrList_.begin());
60 if (static_cast<int32_t>(resourcePtrList_.size()) > lruCacheCapacity_) {
61 auto popResource = resourcePtrList_.back();
62 if (popResource->GetPinStatus() == 0) {
63 popResource->Pin();
64 }
65 positionMap_.erase(resourcePtrList_.back());
66 resourcePtrList_.pop_back();
67 }
68 }
69
Erase(std::shared_ptr<PurgeableMemBase> key)70 void PurgeableResourceManager::LruCache::Erase(std::shared_ptr<PurgeableMemBase> key)
71 {
72 if (key == nullptr) {
73 return;
74 }
75
76 auto resourcePtrIter = positionMap_.find(key);
77 if (resourcePtrIter == positionMap_.end()) {
78 return;
79 }
80
81 resourcePtrList_.erase(resourcePtrIter->second);
82 positionMap_.erase(key);
83 }
84
SetCapacity(int32_t capacity)85 void PurgeableResourceManager::LruCache::SetCapacity(int32_t capacity)
86 {
87 if (capacity < 0 || capacity > MAX_LRU_CACHE_CAPACITY) {
88 PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] SetCapacity FAILED: capacity value is invalid!");
89 return;
90 }
91
92 lruCacheCapacity_ = capacity;
93 while (lruCacheCapacity_ < static_cast<int32_t>(Size())) {
94 Erase(resourcePtrList_.back());
95 }
96 }
97
Clear()98 void PurgeableResourceManager::LruCache::Clear()
99 {
100 positionMap_.clear();
101 resourcePtrList_.clear();
102 }
103
GetResourcePtrList() const104 std::list<std::shared_ptr<PurgeableMemBase>> PurgeableResourceManager::LruCache::GetResourcePtrList() const
105 {
106 return resourcePtrList_;
107 }
108
GetLastResourcePtr() const109 std::shared_ptr<PurgeableMemBase> PurgeableResourceManager::LruCache::GetLastResourcePtr() const
110 {
111 return resourcePtrList_.back();
112 }
113
Size() const114 size_t PurgeableResourceManager::LruCache::Size() const
115 {
116 return positionMap_.size();
117 }
118
PurgeableResourceManager()119 PurgeableResourceManager::PurgeableResourceManager()
120 {
121 int32_t lruCacheCapacity = GetLruCacheCapacityFromSysPara();
122 if (lruCacheCapacity < MIN_LRU_CACHE_CAPACITY || lruCacheCapacity > MAX_LRU_CACHE_CAPACITY) {
123 PM_HILOG_ERROR(LOG_CORE, "[PurgeableResourceManager] Get error lrucache capacity from system parameter.");
124 lruCacheCapacity = LRU_CACHE_CAPACITY;
125 }
126 lruCache_.SetCapacity(lruCacheCapacity);
127 PM_HILOG_DEBUG(LOG_CORE, "PurgeableResourceManager init. lruCacheCapacity is: %{public}d", lruCacheCapacity);
128 }
129
~PurgeableResourceManager()130 PurgeableResourceManager::~PurgeableResourceManager()
131 {
132 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
133 lruCache_.Clear();
134 }
135
GetInstance()136 PurgeableResourceManager &PurgeableResourceManager::GetInstance()
137 {
138 static PurgeableResourceManager instance;
139 return instance;
140 }
141
BeginAccessPurgeableMem()142 void PurgeableResourceManager::BeginAccessPurgeableMem()
143 {
144 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableMem::PurgeableResourceManager::BeginAccessPurgeableMem");
145 std::list<std::shared_ptr<PurgeableMemBase>> resourcePtrList = lruCache_.GetResourcePtrList();
146
147 if (resourcePtrList.size() == 0) {
148 FinishTrace(HITRACE_TAG_ZIMAGE);
149 return;
150 }
151
152 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
153 if (resourcePtrList.size() == 0) {
154 FinishTrace(HITRACE_TAG_ZIMAGE);
155 return;
156 }
157
158 for (auto &resourcePtr : resourcePtrList) {
159 ffrt::submit([this, resourcePtr] {
160 if (resourcePtr == nullptr) {
161 return;
162 }
163 resourcePtr->BeginReadWithDataLock();
164 });
165 }
166
167 FinishTrace(HITRACE_TAG_ZIMAGE);
168 PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] BeginAccessPurgeableMem list size: %{public}zu",
169 lruCache_.Size());
170 }
171
EndAccessPurgeableMem()172 void PurgeableResourceManager::EndAccessPurgeableMem()
173 {
174 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableMem::PurgeableResourceManager::EndAccessPurgeableMem");
175 std::list<std::shared_ptr<PurgeableMemBase>> resourcePtrList = lruCache_.GetResourcePtrList();
176
177 if (resourcePtrList.size() == 0) {
178 FinishTrace(HITRACE_TAG_ZIMAGE);
179 return;
180 }
181
182 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
183 if (resourcePtrList.size() == 0) {
184 FinishTrace(HITRACE_TAG_ZIMAGE);
185 return;
186 }
187
188 for (auto &resourcePtr : resourcePtrList) {
189 ffrt::submit([this, resourcePtr] {
190 if (resourcePtr == nullptr) {
191 return;
192 }
193 resourcePtr->EndReadWithDataLock();
194 });
195 }
196
197 FinishTrace(HITRACE_TAG_ZIMAGE);
198 PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] EndAccessPurgeableMem list size: %{public}zu",
199 lruCache_.Size());
200 }
201
ChangeDataValid(std::shared_ptr<PurgeableMemBase> resourcePtr,bool isVaild) const202 void PurgeableResourceManager::ChangeDataValid(std::shared_ptr<PurgeableMemBase> resourcePtr, bool isVaild) const
203 {
204 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableMem::PurgeableResourceManager::ChangeDataValid");
205 std::lock_guard<ffrt::mutex> dataLock(resourcePtr->dataLock_);
206 resourcePtr->SetDataValid(isVaild);
207 if (!isVaild && resourcePtr->GetPinStatus() == 0) {
208 resourcePtr->Pin();
209 }
210 FinishTrace(HITRACE_TAG_ZIMAGE);
211 }
212
AddResource(std::shared_ptr<PurgeableMemBase> resourcePtr)213 void PurgeableResourceManager::AddResource(std::shared_ptr<PurgeableMemBase> resourcePtr)
214 {
215 ffrt::submit([this, resourcePtr] {
216 if (resourcePtr == nullptr) {
217 return;
218 }
219 AddResourceInner(resourcePtr);
220 });
221 }
222
AddResourceInner(std::shared_ptr<PurgeableMemBase> resourcePtr)223 void PurgeableResourceManager::AddResourceInner(std::shared_ptr<PurgeableMemBase> resourcePtr)
224 {
225 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableMem::PurgeableResourceManager::AddResource");
226 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
227 if (resourcePtr == nullptr) {
228 FinishTrace(HITRACE_TAG_ZIMAGE);
229 return;
230 }
231
232 lruCache_.Insert(resourcePtr);
233 FinishTrace(HITRACE_TAG_ZIMAGE);
234 PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] AddResource resourcePtr: 0x%{public}lx, "
235 "list size: %{public}zu", (long)resourcePtr.get(), lruCache_.Size());
236 }
237
RemoveResource(std::shared_ptr<PurgeableMemBase> resourcePtr)238 void PurgeableResourceManager::RemoveResource(std::shared_ptr<PurgeableMemBase> resourcePtr)
239 {
240 ChangeDataValid(resourcePtr, false);
241 ffrt::submit([this, resourcePtr] {
242 if (resourcePtr == nullptr) {
243 return;
244 }
245 RemoveResourceInner(resourcePtr);
246 });
247 }
248
RemoveResourceInner(std::shared_ptr<PurgeableMemBase> resourcePtr)249 void PurgeableResourceManager::RemoveResourceInner(std::shared_ptr<PurgeableMemBase> resourcePtr)
250 {
251 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableMem::PurgeableResourceManager::RemoveResource");
252 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
253 if (resourcePtr == nullptr) {
254 FinishTrace(HITRACE_TAG_ZIMAGE);
255 return;
256 }
257
258 lruCache_.Erase(resourcePtr);
259 FinishTrace(HITRACE_TAG_ZIMAGE);
260 }
261
SetRecentUsedResource(std::shared_ptr<PurgeableMemBase> resourcePtr)262 void PurgeableResourceManager::SetRecentUsedResource(std::shared_ptr<PurgeableMemBase> resourcePtr)
263 {
264 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
265 if (resourcePtr == nullptr) {
266 return;
267 }
268
269 lruCache_.Visited(resourcePtr);
270 }
271
SetLruCacheCapacity(int32_t capacity)272 void PurgeableResourceManager::SetLruCacheCapacity(int32_t capacity)
273 {
274 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
275 lruCache_.SetCapacity(capacity);
276 }
277
Clear()278 void PurgeableResourceManager::Clear()
279 {
280 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
281 lruCache_.Clear();
282 }
283
RemoveLastResource()284 void PurgeableResourceManager::RemoveLastResource()
285 {
286 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
287 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableMem::PurgeableResourceManager::RemoveLastResource");
288 if (lruCache_.Size() == 0) {
289 FinishTrace(HITRACE_TAG_ZIMAGE);
290 return;
291 }
292
293 std::shared_ptr<PurgeableMemBase> resourcePtr = lruCache_.GetLastResourcePtr();
294 if (resourcePtr == nullptr) {
295 FinishTrace(HITRACE_TAG_ZIMAGE);
296 return;
297 }
298
299 lruCache_.Erase(resourcePtr);
300 FinishTrace(HITRACE_TAG_ZIMAGE);
301 PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] RemoveLastResource resourcePtr: 0x%{public}lx, "
302 "list size: %{public}zu", (long)resourcePtr.get(), lruCache_.Size());
303 }
304
ShowLruCache() const305 void PurgeableResourceManager::ShowLruCache() const
306 {
307 std::lock_guard<ffrt::mutex> lock(lruCacheMutex_);
308 std::list<std::shared_ptr<PurgeableMemBase>> resourcePtrList = lruCache_.GetResourcePtrList();
309 int cnt = 0;
310 for (auto &resourcePtr : resourcePtrList) {
311 cnt++;
312 PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] ShowLruCache (resourcePtr: 0x%{public}lx, "
313 "%{public}d th, list size: %{public}zu)", (long)resourcePtr.get(), cnt, lruCache_.Size());
314 }
315 }
316
GetLruCacheCapacityFromSysPara() const317 int32_t PurgeableResourceManager::GetLruCacheCapacityFromSysPara() const
318 {
319 return system::GetIntParameter<int32_t>(LRU_CACHE_CAPACITY_SYS_NAME, LRU_CACHE_CAPACITY);
320 }
321 } /* namespace PurgeableMem */
322 } /* namespace OHOS */