1ba5c3796Sopenharmony_ci/* 2ba5c3796Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3ba5c3796Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4ba5c3796Sopenharmony_ci * you may not use this file except in compliance with the License. 5ba5c3796Sopenharmony_ci * You may obtain a copy of the License at 6ba5c3796Sopenharmony_ci * 7ba5c3796Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8ba5c3796Sopenharmony_ci * 9ba5c3796Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10ba5c3796Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11ba5c3796Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12ba5c3796Sopenharmony_ci * See the License for the specific language governing permissions and 13ba5c3796Sopenharmony_ci * limitations under the License. 14ba5c3796Sopenharmony_ci */ 15ba5c3796Sopenharmony_ci#include "kswapd_observer.h" 16ba5c3796Sopenharmony_ci 17ba5c3796Sopenharmony_ci#include <cerrno> 18ba5c3796Sopenharmony_ci#include <fcntl.h> 19ba5c3796Sopenharmony_ci#include <sstream> 20ba5c3796Sopenharmony_ci#include <string> 21ba5c3796Sopenharmony_ci#include <sys/epoll.h> 22ba5c3796Sopenharmony_ci#include <unistd.h> 23ba5c3796Sopenharmony_ci 24ba5c3796Sopenharmony_ci#include "memmgr_log.h" 25ba5c3796Sopenharmony_ci#include "memmgr_ptr_util.h" 26ba5c3796Sopenharmony_ci#include "memory_level_constants.h" 27ba5c3796Sopenharmony_ci#ifdef USE_PURGEABLE_MEMORY 28ba5c3796Sopenharmony_ci#include "purgeable_mem_manager.h" 29ba5c3796Sopenharmony_ci#endif 30ba5c3796Sopenharmony_ci 31ba5c3796Sopenharmony_cinamespace OHOS { 32ba5c3796Sopenharmony_cinamespace Memory { 33ba5c3796Sopenharmony_cinamespace { 34ba5c3796Sopenharmony_ciconst std::string TAG = "KswapdObserver"; 35ba5c3796Sopenharmony_ci} 36ba5c3796Sopenharmony_ci 37ba5c3796Sopenharmony_ciKswapdObserver::KswapdObserver() 38ba5c3796Sopenharmony_ci{ 39ba5c3796Sopenharmony_ci MAKE_POINTER(handler_, shared, AppExecFwk::EventHandler, "failed to create event handler", return, 40ba5c3796Sopenharmony_ci AppExecFwk::EventRunner::Create()); 41ba5c3796Sopenharmony_ci HILOGI("handler init success!"); 42ba5c3796Sopenharmony_ci} 43ba5c3796Sopenharmony_ci 44ba5c3796Sopenharmony_civoid KswapdObserver::Init() 45ba5c3796Sopenharmony_ci{ 46ba5c3796Sopenharmony_ci epollfd_ = epoll_create(6); // 6 : max epoll events 47ba5c3796Sopenharmony_ci if (epollfd_ == -1) { 48ba5c3796Sopenharmony_ci HILOGE("epoll_create failed (errno=%{public}d)", errno); 49ba5c3796Sopenharmony_ci return; 50ba5c3796Sopenharmony_ci } 51ba5c3796Sopenharmony_ci HILOGI("epoll_create success epollfd_=<%{public}d>", epollfd_); 52ba5c3796Sopenharmony_ci 53ba5c3796Sopenharmony_ci if (!RegisterKswapdListener()) { 54ba5c3796Sopenharmony_ci HILOGE("register kswapd pressure failed!"); 55ba5c3796Sopenharmony_ci return; 56ba5c3796Sopenharmony_ci } 57ba5c3796Sopenharmony_ci // call MainLoop at handler thread 58ba5c3796Sopenharmony_ci if (handler_ != nullptr) { 59ba5c3796Sopenharmony_ci handler_->PostImmediateTask([this] { this->MainLoop(); }); 60ba5c3796Sopenharmony_ci HILOGD("call MainLoop at handler thread"); 61ba5c3796Sopenharmony_ci } 62ba5c3796Sopenharmony_ci} 63ba5c3796Sopenharmony_ci 64ba5c3796Sopenharmony_cibool KswapdObserver::RegisterKswapdListener() 65ba5c3796Sopenharmony_ci{ 66ba5c3796Sopenharmony_ci struct epoll_event epollEvent; 67ba5c3796Sopenharmony_ci 68ba5c3796Sopenharmony_ci // open file 69ba5c3796Sopenharmony_ci do { 70ba5c3796Sopenharmony_ci kswapdMonitorFd_ = open(KSWAPD_PRESSURE_FILE, O_WRONLY | O_CLOEXEC); 71ba5c3796Sopenharmony_ci } while (kswapdMonitorFd_ == -1 && errno == EINTR); 72ba5c3796Sopenharmony_ci if (kswapdMonitorFd_ < 0) { 73ba5c3796Sopenharmony_ci HILOGE("invalid fd (errno=%{public}d)", errno); 74ba5c3796Sopenharmony_ci return false; 75ba5c3796Sopenharmony_ci } 76ba5c3796Sopenharmony_ci 77ba5c3796Sopenharmony_ci epollEvent.events = EPOLLPRI; 78ba5c3796Sopenharmony_ci epollEvent.data.ptr = nullptr; 79ba5c3796Sopenharmony_ci epollEvent.data.fd = kswapdMonitorFd_; 80ba5c3796Sopenharmony_ci if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, kswapdMonitorFd_, &epollEvent) < 0) { 81ba5c3796Sopenharmony_ci close(kswapdMonitorFd_); 82ba5c3796Sopenharmony_ci kswapdMonitorFd_ = -1; 83ba5c3796Sopenharmony_ci HILOGE("failed to add file fd to epoll : errno=%{public}d", errno); 84ba5c3796Sopenharmony_ci return false; 85ba5c3796Sopenharmony_ci } 86ba5c3796Sopenharmony_ci HILOGI("fd for kswapd monitor = %{public}d", kswapdMonitorFd_); 87ba5c3796Sopenharmony_ci return true; 88ba5c3796Sopenharmony_ci} 89ba5c3796Sopenharmony_ci 90ba5c3796Sopenharmony_civoid KswapdObserver::MainLoop(void) 91ba5c3796Sopenharmony_ci{ 92ba5c3796Sopenharmony_ci struct epoll_event *curEpollEvent; 93ba5c3796Sopenharmony_ci 94ba5c3796Sopenharmony_ci while (1) { 95ba5c3796Sopenharmony_ci HILOGD("waiting for epoll event ..."); 96ba5c3796Sopenharmony_ci struct epoll_event events[1]; 97ba5c3796Sopenharmony_ci int i; 98ba5c3796Sopenharmony_ci int nevents = epoll_wait(epollfd_, events, 1, -1); 99ba5c3796Sopenharmony_ci HILOGD("receive events, num=%{public}d!", nevents); 100ba5c3796Sopenharmony_ci if (nevents == -1) { 101ba5c3796Sopenharmony_ci if (errno == EINTR) { 102ba5c3796Sopenharmony_ci continue; 103ba5c3796Sopenharmony_ci } 104ba5c3796Sopenharmony_ci HILOGE("failed to wait epoll event(errno=%{public}d)", errno); 105ba5c3796Sopenharmony_ci continue; 106ba5c3796Sopenharmony_ci } 107ba5c3796Sopenharmony_ci 108ba5c3796Sopenharmony_ci for (i = 0, curEpollEvent = &events[0]; i < nevents; ++i, curEpollEvent++) { 109ba5c3796Sopenharmony_ci if (curEpollEvent->events & EPOLLHUP) { 110ba5c3796Sopenharmony_ci HILOGE("EPOLLHUP in events[%{public}d]", i); 111ba5c3796Sopenharmony_ci HandleEventEpollHup(curEpollEvent); 112ba5c3796Sopenharmony_ci continue; 113ba5c3796Sopenharmony_ci } 114ba5c3796Sopenharmony_ci if (curEpollEvent->events & EPOLLERR) { 115ba5c3796Sopenharmony_ci HILOGE("epoll err in events[%{public}d]", i); 116ba5c3796Sopenharmony_ci continue; 117ba5c3796Sopenharmony_ci } 118ba5c3796Sopenharmony_ci if ((curEpollEvent->events & EPOLLPRI) && curEpollEvent->data.fd == kswapdMonitorFd_) { 119ba5c3796Sopenharmony_ci HandleKswapdReport(); 120ba5c3796Sopenharmony_ci } 121ba5c3796Sopenharmony_ci } // end of for 122ba5c3796Sopenharmony_ci } // end of while 123ba5c3796Sopenharmony_ci} 124ba5c3796Sopenharmony_ci 125ba5c3796Sopenharmony_civoid KswapdObserver::HandleEventEpollHup(struct epoll_event *curEpollEvent) 126ba5c3796Sopenharmony_ci{ 127ba5c3796Sopenharmony_ci if (epoll_ctl(epollfd_, EPOLL_CTL_DEL, curEpollEvent->data.fd, NULL) < 0) { 128ba5c3796Sopenharmony_ci HILOGE("Failed to unmonitor for kswapd, errno=%{public}d", errno); 129ba5c3796Sopenharmony_ci } 130ba5c3796Sopenharmony_ci if (curEpollEvent->data.fd >= 0) { 131ba5c3796Sopenharmony_ci close(curEpollEvent->data.fd); 132ba5c3796Sopenharmony_ci } 133ba5c3796Sopenharmony_ci if (curEpollEvent->data.fd == kswapdMonitorFd_) { 134ba5c3796Sopenharmony_ci kswapdMonitorFd_ = -1; 135ba5c3796Sopenharmony_ci } 136ba5c3796Sopenharmony_ci} 137ba5c3796Sopenharmony_ci 138ba5c3796Sopenharmony_civoid HandleKswapdReport() 139ba5c3796Sopenharmony_ci{ 140ba5c3796Sopenharmony_ci HILOGD("called"); 141ba5c3796Sopenharmony_ci#ifdef USE_PURGEABLE_MEMORY 142ba5c3796Sopenharmony_ci SystemMemoryInfo info = {MemorySource::KSWAPD, SystemMemoryLevel::MEMORY_LEVEL_LOW}; 143ba5c3796Sopenharmony_ci PurgeableMemManager::GetInstance().NotifyMemoryLevel(info); 144ba5c3796Sopenharmony_ci#endif 145ba5c3796Sopenharmony_ci} 146ba5c3796Sopenharmony_ci 147ba5c3796Sopenharmony_ciKswapdObserver::~KswapdObserver() 148ba5c3796Sopenharmony_ci{ 149ba5c3796Sopenharmony_ci if (kswapdMonitorFd_ >= 0) { 150ba5c3796Sopenharmony_ci epoll_ctl(epollfd_, EPOLL_CTL_DEL, kswapdMonitorFd_, NULL); 151ba5c3796Sopenharmony_ci close(kswapdMonitorFd_); 152ba5c3796Sopenharmony_ci } 153ba5c3796Sopenharmony_ci if (epollfd_ >= 0) { 154ba5c3796Sopenharmony_ci close(epollfd_); 155ba5c3796Sopenharmony_ci } 156ba5c3796Sopenharmony_ci} 157ba5c3796Sopenharmony_ci} // namespace Memory 158ba5c3796Sopenharmony_ci} // namespace OHOS 159