【Linux 内核 内存管理】物理分配页 ⑨ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | retry 标号代码分析 )
文章目錄
- 一、retry 標號代碼分析
- 二、retry 標號完整代碼
在 【Linux 內核 內存管理】物理分配頁 ② ( __alloc_pages_nodemask 函數參數分析 | __alloc_pages_nodemask 函數分配物理頁流程 ) 博客中 , 分析了 __alloc_pages_nodemask 函數分配物理頁流程如下 :
首先 , 根據 gfp_t gfp_mask 分配標志位 參數 , 得到 " 內存節點 “ 的 首選 ” 區域類型 " 和 " 遷移類型 " ;
然后 , 執行 " 快速路徑 " , 第一次分配 嘗試使用 低水線分配 ;
如果上述 " 快速路徑 " 分配失敗 , 則執行 " 慢速路徑 " 分配 ;
上述涉及到了 " 快速路徑 " 和 " 慢速路徑 " 222 種物理頁分配方式 ;
繼續接著上一篇博客 【Linux 內核 內存管理】物理分配頁 ⑧ ( __alloc_pages_slowpath 慢速路徑調用函數源碼分析 | 獲取首選內存區域 | 異步回收內存頁 | 最低水線也分配 | 直接分配 ) 分析 __alloc_pages_slowpath 慢速路徑 內存分配 調用函數 的后續部分源碼 ;
一、retry 標號代碼分析
下面開始分析 __alloc_pages_slowpath 慢速路徑 內存分配 調用函數 中的 retry 標號下的代碼 ,
調用 wake_all_kswapds 函數 , 確保 " 頁回收線程 " 在遍歷時 保持喚醒狀態 , 不會由于意外導致休眠 ;
retry:/* Ensure kswapd doesn't accidentally go to sleep as long as we loop */if (gfp_mask & __GFP_KSWAPD_RECLAIM)wake_all_kswapds(order, ac);源碼路徑 : linux-4.12\mm\page_alloc.c#3794
調用 get_page_from_freelist 函數 , 嘗試使用 調整過的 區域列表 和 分配標志位 進行 內存分配 , 如果 內存分配成功 , 則跳轉到 got_pg 標號執行 ;
/* Attempt with potentially adjusted zonelist and alloc_flags */page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);if (page)goto got_pg;源碼路徑 : linux-4.12\mm\page_alloc.c#3811
如果 調用者 不想等待 浪費時間 , 則不執行后續操作 , 跳轉到 nopage 處執行 后續代碼 ;
/* Caller is not willing to reclaim, we can't balance anything */if (!can_direct_reclaim)goto nopage;源碼路徑 : linux-4.12\mm\page_alloc.c#3817
調用 __alloc_pages_direct_reclaim 函數 , 直接進行頁回收 ;
/* Try direct reclaim and then allocating */page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,&did_some_progress);if (page)goto got_pg;源碼路徑 : linux-4.12\mm\page_alloc.c#3833
調用 __alloc_pages_direct_compact 函數 , 針對申請 物理頁 階數 大于 0 的情況 , 執行 同步模式 下的 內存碎片整理 操作 ;
/* Try direct compaction and then allocating */page = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags, ac,compact_priority, &compact_result);if (page)goto got_pg;源碼路徑 : linux-4.12\mm\page_alloc.c#3839
再次進行判斷 , 如果調用者 不想進行循環 , 則放棄內存申請 , 跳轉到 nopage 標號執行 ;
/* Do not loop if specifically requested */if (gfp_mask & __GFP_NORETRY)goto nopage;源碼路徑 : linux-4.12\mm\page_alloc.c#3845
如果 申請 物理頁 階數 大于 0 , 則調用 should_compact_retry 函數 , 判斷是否重新嘗試 執行 內存碎片整理操作 , 如果判定成功 , 則繼續跳轉到 retry 標號處再執行一遍 ;
/** It doesn't make any sense to retry for the compaction if the order-0* reclaim is not able to make any progress because the current* implementation of the compaction depends on the sufficient amount* of free memory (see __compaction_suitable)*/if (did_some_progress > 0 &&should_compact_retry(ac, order, alloc_flags,compact_result, &compact_priority,&compaction_retries))goto retry;源碼路徑 : linux-4.12\mm\page_alloc.c#3865
調用 read_mems_allowed_retry 函數 , 判定 cpuset 是否允許修改當前進程 從 指定的內存節點申請 物理頁內存 ;
/** It's possible we raced with cpuset update so the OOM would be* premature (see below the nopage: label for full explanation).*/if (read_mems_allowed_retry(cpuset_mems_cookie))goto retry_cpuset;源碼路徑 : linux-4.12\mm\page_alloc.c#3875
調用 __alloc_pages_may_oom 函數 , 如果內存耗盡 , 分配內存失敗 , 則殺死一個進程 , 以獲取足夠的內存空間 ;
/* Reclaim has failed us, start killing things */page = __alloc_pages_may_oom(gfp_mask, order, ac, &did_some_progress);if (page)goto got_pg;源碼路徑 : linux-4.12\mm\page_alloc.c#3879
假如 當前進程 出現內存耗盡的情況 , 則忽略 最低水線 的限制 , 或者 不允許使用 緊急保留內存 ;
/* Avoid allocations with no watermarks from looping endlessly */if (test_thread_flag(TIF_MEMDIE) &&(alloc_flags == ALLOC_NO_WATERMARKS ||(gfp_mask & __GFP_NOMEMALLOC)))goto nopage;源碼路徑 : linux-4.12\mm\page_alloc.c#3884
內存耗盡殺手 取得一定進展 , 繼續跳轉到 retry 標號重新嘗試分配內存 ;
/* Retry as long as the OOM killer is making progress */if (did_some_progress) {no_progress_loops = 0;goto retry;}源碼路徑 : linux-4.12\mm\page_alloc.c#3890
二、retry 標號完整代碼
retry 標號完整代碼 :
static inline struct page * __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,struct alloc_context *ac) {... retry:/* Ensure kswapd doesn't accidentally go to sleep as long as we loop */if (gfp_mask & __GFP_KSWAPD_RECLAIM)wake_all_kswapds(order, ac);if (gfp_pfmemalloc_allowed(gfp_mask))alloc_flags = ALLOC_NO_WATERMARKS;/** Reset the zonelist iterators if memory policies can be ignored.* These allocations are high priority and system rather than user* orientated.*/if (!(alloc_flags & ALLOC_CPUSET) || (alloc_flags & ALLOC_NO_WATERMARKS)) {ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,ac->high_zoneidx, ac->nodemask);}/* Attempt with potentially adjusted zonelist and alloc_flags */page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);if (page)goto got_pg;/* Caller is not willing to reclaim, we can't balance anything */if (!can_direct_reclaim)goto nopage;/* Make sure we know about allocations which stall for too long */if (time_after(jiffies, alloc_start + stall_timeout)) {warn_alloc(gfp_mask & ~__GFP_NOWARN, ac->nodemask,"page allocation stalls for %ums, order:%u",jiffies_to_msecs(jiffies-alloc_start), order);stall_timeout += 10 * HZ;}/* Avoid recursion of direct reclaim */if (current->flags & PF_MEMALLOC)goto nopage;/* Try direct reclaim and then allocating */page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,&did_some_progress);if (page)goto got_pg;/* Try direct compaction and then allocating */page = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags, ac,compact_priority, &compact_result);if (page)goto got_pg;/* Do not loop if specifically requested */if (gfp_mask & __GFP_NORETRY)goto nopage;/** Do not retry costly high order allocations unless they are* __GFP_REPEAT*/if (costly_order && !(gfp_mask & __GFP_REPEAT))goto nopage;if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,did_some_progress > 0, &no_progress_loops))goto retry;/** It doesn't make any sense to retry for the compaction if the order-0* reclaim is not able to make any progress because the current* implementation of the compaction depends on the sufficient amount* of free memory (see __compaction_suitable)*/if (did_some_progress > 0 &&should_compact_retry(ac, order, alloc_flags,compact_result, &compact_priority,&compaction_retries))goto retry;/** It's possible we raced with cpuset update so the OOM would be* premature (see below the nopage: label for full explanation).*/if (read_mems_allowed_retry(cpuset_mems_cookie))goto retry_cpuset;/* Reclaim has failed us, start killing things */page = __alloc_pages_may_oom(gfp_mask, order, ac, &did_some_progress);if (page)goto got_pg;/* Avoid allocations with no watermarks from looping endlessly */if (test_thread_flag(TIF_MEMDIE) &&(alloc_flags == ALLOC_NO_WATERMARKS ||(gfp_mask & __GFP_NOMEMALLOC)))goto nopage;/* Retry as long as the OOM killer is making progress */if (did_some_progress) {no_progress_loops = 0;goto retry;}... }源碼路徑 : linux-4.12\mm\page_alloc.c#3792
總結
以上是生活随笔為你收集整理的【Linux 内核 内存管理】物理分配页 ⑨ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | retry 标号代码分析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 定制电竞比分网LOL英雄联盟数据API接
- 下一篇: linux安装pcre错误,安装PCRE