• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <regex>
17 
18 #include "memmgr_log.h"
19 #include "memmgr_ptr_util.h"
20 #include "kernel_interface.h"
21 #include "avail_buffer_manager.h"
22 
23 namespace OHOS {
24 namespace Memory {
25 namespace {
26 const std::string TAG = "AvailBufferManager";
27 const std::string BUFFER_PATH = KernelInterface::MEMCG_BASE_PATH;
28 }
29 IMPLEMENT_SINGLE_INSTANCE(AvailBufferManager);
30 
AvailBufferManager()31 AvailBufferManager::AvailBufferManager()
32 {
33 }
34 
~AvailBufferManager()35 AvailBufferManager::~AvailBufferManager()
36 {
37 }
38 
Init()39 bool AvailBufferManager::Init()
40 {
41     initialized_ = GetEventHandler();
42     UpdateMemTotalFromKernel();
43     InitAvailBuffer();
44     if (initialized_) {
45         HILOGI("init successed");
46     } else {
47         HILOGE("init failed");
48     }
49     return initialized_;
50 }
51 
GetEventHandler()52 bool AvailBufferManager::GetEventHandler()
53 {
54     if (!handler_) {
55         MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return false,
56             AppExecFwk::EventRunner::Create());
57     }
58     return true;
59 }
60 
LoadAvailBufferFromConfig()61 bool AvailBufferManager::LoadAvailBufferFromConfig()
62 {
63     std::shared_ptr<AvailBufferConfig> availBuffer =
64         std::make_shared<AvailBufferConfig>(MemmgrConfigManager::GetInstance().GetAvailBufferConfig());
65     SetAvailBuffer(availBuffer);
66     return true;
67 }
68 
CheckAvailBuffer(std::shared_ptr<AvailBufferConfig> availBuffer)69 bool AvailBufferManager::CheckAvailBuffer(std::shared_ptr<AvailBufferConfig> availBuffer)
70 {
71     if (availBuffer->GetAvailBuffer() > this->memTotal_ || availBuffer->GetMinAvailBuffer() > this->memTotal_ ||
72         availBuffer->GetHighAvailBuffer() > this->memTotal_ || availBuffer->GetSwapReserve() > this->memTotal_) {
73         return false;
74     }
75     if (availBuffer->GetAvailBuffer() < availBuffer->GetMinAvailBuffer() ||
76         availBuffer->GetAvailBuffer() > availBuffer->GetHighAvailBuffer()) {
77         return false;
78     }
79     return true;
80 }
81 
SetAvailBuffer(std::shared_ptr<AvailBufferConfig> availBuffer)82 bool AvailBufferManager::SetAvailBuffer(std::shared_ptr<AvailBufferConfig> availBuffer)
83 {
84     if (!CheckAvailBuffer(availBuffer)) {
85         HILOGI("size invalid, set failed");
86         return false;
87     }
88     this->availBuffer_ = availBuffer->GetAvailBuffer();
89     this->minAvailBuffer_ = availBuffer->GetMinAvailBuffer();
90     this->highAvailBuffer_ = availBuffer->GetHighAvailBuffer();
91     this->swapReserve_ = availBuffer->GetSwapReserve();
92     HILOGI("=%{public}d,minAvailBuffer = %{public}d,highAvailBuffer = %{public}d,swapReserve = %{public}d",
93            this->availBuffer_, this->minAvailBuffer_, this->highAvailBuffer_, this->swapReserve_);
94     return WriteAvailBufferToKernel();
95 }
96 
NumsToString()97 inline std::string AvailBufferManager::NumsToString()
98 {
99     std::string ret = std::to_string(this->availBuffer_) + " "
100         + std::to_string(this->minAvailBuffer_) + " "
101         + std::to_string(this->highAvailBuffer_) + " "
102         + std::to_string(this->swapReserve_);
103     return ret;
104 }
105 
WriteAvailBufferToKernel()106 bool AvailBufferManager::WriteAvailBufferToKernel()
107 {
108     std::string fullPath = KernelInterface::GetInstance().JoinPath(BUFFER_PATH, "memory.avail_buffers");
109     HILOGI("%{public}s", NumsToString().c_str());
110     return KernelInterface::GetInstance().WriteToFile(fullPath, NumsToString());
111 }
112 
CloseZswapd()113 void AvailBufferManager::CloseZswapd()
114 {
115     DECLARE_SHARED_POINTER(AvailBufferConfig, availBuffer);
116     MAKE_POINTER(availBuffer, shared, AvailBufferConfig, "make shared failed", return, 0, 0, 0, 0);
117     HILOGI("Zswapd close now");
118     SetAvailBuffer(availBuffer);
119 }
120 
InitAvailBuffer()121 void AvailBufferManager::InitAvailBuffer()
122 {
123     UpdateZramEnableFromKernel();
124     if (this->zramEnable_) {
125         LoadAvailBufferFromConfig();
126     } else {
127         CloseZswapd();
128     }
129 }
130 
UpdateZramEnableFromKernel()131 void AvailBufferManager::UpdateZramEnableFromKernel()
132 {
133     std::string content;
134     unsigned int swapTotal = 0;
135     if (!KernelInterface::GetInstance().ReadFromFile("/proc/meminfo", content)) {
136         return;
137     }
138     content = std::regex_replace(content, std::regex("\n+"), " "); // replace \n with space
139     std::regex re("SwapTotal:[[:s:]]*([[:d:]]+) kB[[:s:]]*");
140     std::smatch res;
141     if (std::regex_search(content, res, re)) {
142         try {
143         swapTotal = (unsigned int) std::stoi(res.str(1)); // 1: swapTotal index
144         } catch (std::out_of_range&) {
145             HILOGE("stoi() failed: out_of_range");
146         }
147         HILOGI(" : %{public}d", swapTotal);
148     }
149 
150     if (swapTotal != 0) {
151         this->zramEnable_ = true;
152     } else {
153         this->zramEnable_ = false;
154     }
155 }
156 
UpdateMemTotalFromKernel()157 void AvailBufferManager::UpdateMemTotalFromKernel()
158 {
159     std::string content;
160     if (!KernelInterface::GetInstance().ReadFromFile("/proc/meminfo", content)) {
161         return;
162     }
163     content = std::regex_replace(content, std::regex("\n+"), " "); // replace \n with space
164     std::regex re("MemTotal:[[:s:]]*([[:d:]]+) kB[[:s:]]*");
165     std::smatch res;
166     if (std::regex_search(content, res, re)) {
167         try {
168         this->memTotal_ = (unsigned int) std::stoi(res.str(1)); // 1: memTotal index
169         } catch (std::out_of_range&) {
170             HILOGE("stoi() failed: out_of_range");
171             return;
172         }
173         HILOGI(" : %{public}d", this->memTotal_);
174     }
175 }
176 } // namespace Memory
177 } // namespace OHOS
178