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