321 Star 2.1K Fork 1K

OpenHarmony / kernel_liteos_a

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
los_vm_scan.c 9.98 KB
一键复制 编辑 原始数据 按行查看 历史
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef LOSCFG_FS_VFS
#include "fs/file.h"
#include "los_vm_filemap.h"
#ifdef LOSCFG_KERNEL_VM
/* unmap a lru page by map record info caller need lru lock */
VOID OsUnmapPageLocked(LosFilePage *page, LosMapInfo *info)
{
if (page == NULL || info == NULL) {
VM_ERR("UnmapPage error input null!");
return;
}
page->n_maps--;
LOS_ListDelete(&info->node);
LOS_AtomicDec(&page->vmPage->refCounts);
LOS_ArchMmuUnmap(info->archMmu, info->vaddr, 1);
LOS_MemFree(m_aucSysMem0, info);
}
VOID OsUnmapAllLocked(LosFilePage *page)
{
LosMapInfo *info = NULL;
LosMapInfo *next = NULL;
LOS_DL_LIST *immap = &page->i_mmap;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(info, next, immap, LosMapInfo, node) {
OsUnmapPageLocked(page, info);
}
}
/* add a new lru node to lru list, lruType can be file or anon */
VOID OsLruCacheAdd(LosFilePage *fpage, enum OsLruList lruType)
{
UINT32 intSave;
LosVmPhysSeg *physSeg = fpage->physSeg;
LosVmPage *page = fpage->vmPage;
LOS_SpinLockSave(&physSeg->lruLock, &intSave);
OsSetPageActive(page);
OsCleanPageReferenced(page);
physSeg->lruSize[lruType]++;
LOS_ListTailInsert(&physSeg->lruList[lruType], &fpage->lru);
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);
}
/* delete a lru node, caller need hold lru_lock */
VOID OsLruCacheDel(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
int type = OsIsPageActive(fpage->vmPage) ? VM_LRU_ACTIVE_FILE : VM_LRU_INACTIVE_FILE;
physSeg->lruSize[type]--;
LOS_ListDelete(&fpage->lru);
}
BOOL OsInactiveListIsLow(LosVmPhysSeg *physSeg)
{
return (physSeg->lruSize[VM_LRU_ACTIVE_FILE] >
physSeg->lruSize[VM_LRU_INACTIVE_FILE]) ? TRUE : FALSE;
}
/* move a page from inactive list to active list head */
STATIC INLINE VOID OsMoveToActiveList(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
physSeg->lruSize[VM_LRU_ACTIVE_FILE]++;
physSeg->lruSize[VM_LRU_INACTIVE_FILE]--;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_ACTIVE_FILE], &fpage->lru);
}
/* move a page from active list to inactive list head */
STATIC INLINE VOID OsMoveToInactiveList(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
physSeg->lruSize[VM_LRU_ACTIVE_FILE]--;
physSeg->lruSize[VM_LRU_INACTIVE_FILE]++;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_INACTIVE_FILE], &fpage->lru);
}
/* move a page to the most active pos in lru list(active head) */
STATIC INLINE VOID OsMoveToActiveHead(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_ACTIVE_FILE], &fpage->lru);
}
/* move a page to the most active pos in lru list(inactive head) */
STATIC INLINE VOID OsMoveToInactiveHead(LosFilePage *fpage)
{
LosVmPhysSeg *physSeg = fpage->physSeg;
LOS_ListDelete(&fpage->lru);
LOS_ListTailInsert(&physSeg->lruList[VM_LRU_INACTIVE_FILE], &fpage->lru);
}
/* page referced add: (call by page cache get)
----------inactive----------|----------active------------
[ref:0,act:0], [ref:1,act:0]|[ref:0,act:1], [ref:1,act:1]
ref:0, act:0 --> ref:1, act:0
ref:1, act:0 --> ref:0, act:1
ref:0, act:1 --> ref:1, act:1
*/
VOID OsPageRefIncLocked(LosFilePage *fpage)
{
BOOL isOrgActive;
UINT32 intSave;
LosVmPage *page = NULL;
if (fpage == NULL) {
return;
}
LOS_SpinLockSave(&fpage->physSeg->lruLock, &intSave);
page = fpage->vmPage;
isOrgActive = OsIsPageActive(page);
if (OsIsPageReferenced(page) && !OsIsPageActive(page)) {
OsCleanPageReferenced(page);
OsSetPageActive(page);
} else if (!OsIsPageReferenced(page)) {
OsSetPageReferenced(page);
}
if (!isOrgActive && OsIsPageActive(page)) {
/* move inactive to active */
OsMoveToActiveList(fpage);
/* no change, move head */
} else {
if (OsIsPageActive(page)) {
OsMoveToActiveHead(fpage);
} else {
OsMoveToInactiveHead(fpage);
}
}
LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, intSave);
}
/* page referced dec: (call by shrinker)
----------inactive----------|----------active------------
[ref:0,act:0], [ref:1,act:0]|[ref:0,act:1], [ref:1,act:1]
ref:1, act:1 --> ref:0, act:1
ref:0, act:1 --> ref:1, act:0
ref:1, act:0 --> ref:0, act:0
*/
VOID OsPageRefDecNoLock(LosFilePage *fpage)
{
BOOL isOrgActive;
LosVmPage *page = NULL;
if (fpage == NULL) {
return;
}
page = fpage->vmPage;
isOrgActive = OsIsPageActive(page);
if (!OsIsPageReferenced(page) && OsIsPageActive(page)) {
OsCleanPageActive(page);
OsSetPageReferenced(page);
} else if (OsIsPageReferenced(page)) {
OsCleanPageReferenced(page);
}
if (isOrgActive && !OsIsPageActive(page)) {
OsMoveToInactiveList(fpage);
}
}
VOID OsShrinkActiveList(LosVmPhysSeg *physSeg, int nScan)
{
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
LOS_DL_LIST *activeFile = &physSeg->lruList[VM_LRU_ACTIVE_FILE];
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, activeFile, LosFilePage, lru) {
if (LOS_SpinTrylock(&fpage->mapping->list_lock) != LOS_OK) {
continue;
}
/* happened when caller hold cache lock and try reclaim this page */
if (OsIsPageLocked(fpage->vmPage)) {
LOS_SpinUnlock(&fpage->mapping->list_lock);
continue;
}
if (OsIsPageMapped(fpage) && (fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE)) {
LOS_SpinUnlock(&fpage->mapping->list_lock);
continue;
}
OsPageRefDecNoLock(fpage);
LOS_SpinUnlock(&fpage->mapping->list_lock);
if (--nScan <= 0) {
break;
}
}
}
int OsShrinkInactiveList(LosVmPhysSeg *physSeg, int nScan, LOS_DL_LIST *list)
{
UINT32 nrReclaimed = 0;
LosVmPage *page = NULL;
SPIN_LOCK_S *flock = NULL;
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
LosFilePage *ftemp = NULL;
LOS_DL_LIST *inactive_file = &physSeg->lruList[VM_LRU_INACTIVE_FILE];
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, inactive_file, LosFilePage, lru) {
flock = &fpage->mapping->list_lock;
if (LOS_SpinTrylock(flock) != LOS_OK) {
continue;
}
page = fpage->vmPage;
if (OsIsPageLocked(page)) {
LOS_SpinUnlock(flock);
continue;
}
if (OsIsPageMapped(fpage) && (OsIsPageDirty(page) || (fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE))) {
LOS_SpinUnlock(flock);
continue;
}
if (OsIsPageDirty(page)) {
ftemp = OsDumpDirtyPage(fpage);
if (ftemp != NULL) {
LOS_ListTailInsert(list, &ftemp->node);
}
}
OsDeletePageCacheLru(fpage);
LOS_SpinUnlock(flock);
nrReclaimed++;
if (--nScan <= 0) {
break;
}
}
return nrReclaimed;
}
#ifdef LOSCFG_FS_VFS
int OsTryShrinkMemory(size_t nPage)
{
UINT32 intSave;
size_t totalPages;
size_t nReclaimed = 0;
LosVmPhysSeg *physSeg = NULL;
UINT32 index;
LOS_DL_LIST_HEAD(dirtyList);
LosFilePage *fpage = NULL;
LosFilePage *fnext = NULL;
if (nPage == 0) {
nPage = VM_FILEMAP_MIN_SCAN;
}
if (nPage > VM_FILEMAP_MAX_SCAN) {
nPage = VM_FILEMAP_MAX_SCAN;
}
for (index = 0; index < g_vmPhysSegNum; index++) {
physSeg = &g_vmPhysSeg[index];
LOS_SpinLockSave(&physSeg->lruLock, &intSave);
totalPages = physSeg->lruSize[VM_LRU_ACTIVE_FILE] + physSeg->lruSize[VM_LRU_INACTIVE_FILE];
if (totalPages < VM_FILEMAP_MIN_SCAN) {
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);
continue;
}
if (OsInactiveListIsLow(physSeg)) {
OsShrinkActiveList(physSeg, (nPage < VM_FILEMAP_MIN_SCAN) ? VM_FILEMAP_MIN_SCAN : nPage);
}
nReclaimed += OsShrinkInactiveList(physSeg, nPage, &dirtyList);
LOS_SpinUnlockRestore(&physSeg->lruLock, intSave);
if (nReclaimed >= nPage) {
break;
}
}
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &dirtyList, LosFilePage, node) {
OsDoFlushDirtyPage(fpage);
}
return nReclaimed;
}
#else
int OsTryShrinkMemory(size_t nPage)
{
return 0;
}
#endif
#endif
#endif
C
1
https://gitee.com/openharmony/kernel_liteos_a.git
git@gitee.com:openharmony/kernel_liteos_a.git
openharmony
kernel_liteos_a
kernel_liteos_a
master

搜索帮助