参照元†
- struct zone *zone
- unsigned int order
- メモリオーダー、2 のべき乗で指定する
- 0 なら 1 ページ、1 なら 2 ページ、n なら 2^n ページ
- int migratetype
- マイグレーションの種類、MIGRATE_XXX を指定する
- unsigned int alloc_flags
返り値†
/*
* Do the hard work of removing an element from the buddy allocator.
* Call me with the zone->lock already held.
*/
static __always_inline struct page *
__rmqueue(struct zone *zone, unsigned int order, int migratetype,
unsigned int alloc_flags)
{
struct page *page;
if (IS_ENABLED(CONFIG_CMA)) {
/*
* Balance movable allocations between regular and CMA areas by
* allocating from CMA when over half of the zone's free memory
* is in the CMA area.
*/
if (alloc_flags & ALLOC_CMA &&
zone_page_state(zone, NR_FREE_CMA_PAGES) >
zone_page_state(zone, NR_FREE_PAGES) / 2) {
page = __rmqueue_cma_fallback(zone, order);
if (page)
goto out;
}
}
- CMAから空きページを取得すべきならCMAから取得する。以前(linux-4.4など)はこの処理がなかったのでCMAのメモリがほとんど使われなかった。
retry:
page = __rmqueue_smallest(zone, order, migratetype);
- マイグレーションの種類が指しているfree_listから、空きページを取得する。
if (unlikely(!page)) {
if (alloc_flags & ALLOC_CMA)
page = __rmqueue_cma_fallback(zone, order);
if (!page && __rmqueue_fallback(zone, order, migratetype,
alloc_flags))
goto retry;
}
- ページを取得できないとき、CMAから確保してよければCMAから、それ以外はフォールバック処理。
out:
if (page)
trace_mm_page_alloc_zone_locked(page, order, migratetype);
return page;
}
コメント†