参照元†
- free_list から取得した領域は大きすぎる可能性があるため、
余分な領域を分割して、小さい領域用の free_area に追加する。
- 例えば、要求されたサイズが 2(オーダー 2, 4 pages)なのに、
free_list から取得した領域が 5(オーダー 5, 32 pages)だとする。
- 32 pages の領域を 4, 4, 8, 16 と分割し、先頭の 4 pages 以外を使い、他は空き領域として free_list に追加する。
- struct zone *zone
- struct page *page
- int low
- int high
- struct free_area *area
- int migratetype
- マイグレーションの種類
- どの free_list に空き領域を追加するか決めるために使う。
返り値†
/*
* The order of subdivision here is critical for the IO subsystem.
* Please do not alter this order without good reasons and regression
* testing. Specifically, as large blocks of memory are subdivided,
* the order in which smaller blocks are delivered depends on the order
* they're subdivided in this function. This is the primary factor
* influencing the order in which pages are delivered to the IO
* subsystem according to empirical testing, and this is also justified
* by considering the behavior of a buddy system containing a single
* large block of memory acted on by a series of small allocations.
* This behavior is a critical factor in sglist merging's success.
*
* -- nyc
*/
static inline void expand(struct zone *zone, struct page *page,
int low, int high, struct free_area *area,
int migratetype)
{
unsigned long size = 1 << high;
while (high > low) {
area--;
high--;
size >>= 1;
VM_BUG_ON_PAGE(bad_range(zone, &page[size]), &page[size]);
- 1つ小さいオーダーの free_area を選択する。
if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) &&
debug_guardpage_enabled() &&
high < debug_guardpage_minorder()) {
/*
* Mark as guard pages (or page), that will allow to
* merge back to allocator when buddy will be freed.
* Corresponding page table entries will not be touched,
* pages will stay not present in virtual address space
*/
set_page_guard(zone, &page[size], high, migratetype);
continue;
}
list_add(&page[size].lru, &area->free_list[migratetype]);
area->nr_free++;
set_page_order(&page[size], high);
- オーダー high 用の free_area の free_list に空き領域を追加する。
- page_order を high の値に設定する。
}
}
コメント†