• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */