1 /*
2  * Copyright (c) 2024 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 #include "memory/rs_memory_snapshot.h"
16 
17 namespace OHOS {
18 namespace Rosen {
19 
Instance()20 MemorySnapshot& MemorySnapshot::Instance()
21 {
22     static MemorySnapshot instance;
23     return instance;
24 }
25 
AddCpuMemory(const pid_t pid,const size_t size)26 void MemorySnapshot::AddCpuMemory(const pid_t pid, const size_t size)
27 {
28     bool shouldReport = false;
29     size_t cpuMemory = 0;
30     {
31         std::lock_guard<std::mutex> lock(mutex_);
32         MemorySnapshotInfo& mInfo = appMemorySnapshots_[pid];
33         mInfo.cpuMemory += size;
34         totalMemory_ += size;
35         if (mInfo.cpuMemory > singleCpuMemoryLimit_ && mInfo.cpuMemory - size < singleCpuMemoryLimit_) {
36             shouldReport = true;
37             cpuMemory = mInfo.cpuMemory;
38         }
39     }
40     if (shouldReport && callback_) {
41         callback_(pid, cpuMemory, false);
42     }
43 }
44 
RemoveCpuMemory(const pid_t pid,const size_t size)45 void MemorySnapshot::RemoveCpuMemory(const pid_t pid, const size_t size)
46 {
47     std::lock_guard<std::mutex> lock(mutex_);
48     auto it = appMemorySnapshots_.find(pid);
49     if (it != appMemorySnapshots_.end()) {
50         it->second.cpuMemory -= size;
51         totalMemory_ -= size;
52     }
53 }
54 
GetMemorySnapshotInfoByPid(const pid_t pid,MemorySnapshotInfo & info)55 bool MemorySnapshot::GetMemorySnapshotInfoByPid(const pid_t pid, MemorySnapshotInfo& info)
56 {
57     std::lock_guard<std::mutex> lock(mutex_);
58     auto it = appMemorySnapshots_.find(pid);
59     if (it == appMemorySnapshots_.end()) {
60         return false;
61     }
62     info = it->second;
63     return true;
64 }
65 
UpdateGpuMemoryInfo(const std::unordered_map<pid_t,size_t> & gpuInfo,std::unordered_map<pid_t,MemorySnapshotInfo> & pidForReport,bool & isTotalOver)66 void MemorySnapshot::UpdateGpuMemoryInfo(const std::unordered_map<pid_t, size_t>& gpuInfo,
67     std::unordered_map<pid_t, MemorySnapshotInfo>& pidForReport, bool& isTotalOver)
68 {
69     std::lock_guard<std::mutex> lock(mutex_);
70     for (auto& [pid, info] : appMemorySnapshots_) {
71         auto it = gpuInfo.find(pid);
72         if (it != gpuInfo.end()) {
73             totalMemory_ = totalMemory_ - info.gpuMemory + it->second;
74             info.gpuMemory = it->second;
75         }
76         if (info.TotalMemory() > singleMemoryWarning_) {
77             pidForReport.emplace(pid, info);
78         }
79     }
80     if (totalMemory_ > totalMemoryLimit_) {
81         pidForReport = appMemorySnapshots_;
82         isTotalOver = true;
83     }
84 }
85 
EraseSnapshotInfoByPid(const std::set<pid_t> & exitedPidSet)86 void MemorySnapshot::EraseSnapshotInfoByPid(const std::set<pid_t>& exitedPidSet)
87 {
88     std::lock_guard<std::mutex> lock(mutex_);
89     for (auto pid : exitedPidSet) {
90         auto it = appMemorySnapshots_.find(pid);
91         if (it != appMemorySnapshots_.end()) {
92             totalMemory_ -= it->second.TotalMemory();
93             appMemorySnapshots_.erase(it);
94         }
95     }
96 }
97 
InitMemoryLimit(MemoryOverflowCalllback callback,uint64_t warning,uint64_t overflow,uint64_t totalSize)98 void MemorySnapshot::InitMemoryLimit(MemoryOverflowCalllback callback,
99     uint64_t warning, uint64_t overflow, uint64_t totalSize)
100 {
101     if (callback_ == nullptr) {
102         callback_ = callback;
103         singleMemoryWarning_ = warning;
104         singleCpuMemoryLimit_ = overflow;
105         totalMemoryLimit_ = totalSize;
106     }
107 }
108 
GetMemorySnapshot(std::unordered_map<pid_t,MemorySnapshotInfo> & map)109 void MemorySnapshot::GetMemorySnapshot(std::unordered_map<pid_t, MemorySnapshotInfo>& map)
110 {
111     std::lock_guard<std::mutex> lock(mutex_);
112     map = appMemorySnapshots_;
113 }
114 }
115 } // namespace OHOS::Rosen