*参照元 [#x8596b7f]
#backlinks

*説明 [#kb2ef2cc]
-パス: [[linux-4.4.1/mm/page_alloc.c]]

-FIXME: これは何?
--説明

-free_list から取得した領域は大きすぎる可能性があるため、
余分な領域を分割して、小さい領域用の free_area に追加する。
--例えば、要求されたサイズが 2(オーダー 2, 4 pages)なのに、
free_list から取得した領域が 5(オーダー 5, 32 pages)だとする。
--32 pages の領域を 4, 4, 8, 16 と分割し、先頭の 4 pages 以外を使い、他は空き領域として free_list に追加する。
--32 pages の領域を 4, 4, 8, 16 と分割し、先頭の 4 pages を使い、他は空き領域として free_list に追加する。

-処理の例
--上記の例だと area = order 5 用のエリア, low = 2, high = 5, size = 32 で始まる。
 while 1回目
   area = order 4 用のエリア
   high = 4
   size = 16
   page[16] を free_list に追加
   area の空き領域数を 1 追加
   page[16] の page_order を 4 に設定
 
   page
    0    4    8         16                31
   |....|....|....|....|....|....|....|....|
                       |<--- ここ処理した -->|
                       |
                       先頭は page[16]
 
 while 2回目
   area = order 3 用のエリア
   high = 3
   size = 8
   page[8] を free_list に追加
   area の空き領域数を 1 追加
   page[8] の page_order を 4 に設定
 
   page
    0    4    8         16                31
   |....|....|....|....| 空き               |
             |<- ここ->|
             |
             先頭は page[8]
 
 while 3回目
   area = order 2 用のエリア
   high = 2
   size = 4
   page[4] を free_list に追加
   area の空き領域数を 1 追加
   page[4] の page_order を 2 に設定
 
   page
    0    4    8         16                31
   |....|....| 空き     | 空き               |
        |<-->|
        |
        先頭は page[4]
 
 おしまい
   page
    0    4    8         16                31
   |....|空き| 空き     | 空き               |


**引数 [#f49edaa7]
-struct zone *zone
--ゾーン
--[[linux-4.4.1/zone]]
-struct page *page
--ページ
--[[linux-4.4.1/page]]
-int low
--実際に必要なサイズのオーダー
-int high
--確保できた空き領域のオーダー
-struct free_area *area
--フリーエリア
--オーダー high 用のエリアを指していなければならない。
--[[linux-4.4.1/free_area]]
-int migratetype
--マイグレーションの種類
--どの free_list に空き領域を追加するか決めるために使う。


**返り値 [#ndacdd79]
-void


**参考 [#mea210a4]


*実装 [#efaf0a49]
 /*
  * 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 を選択する。
--[[linux-4.4.1/VM_BUG_ON_PAGE()]]
--[[linux-4.4.1/bad_range()]]

 		if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) &&
 			debug_guardpage_enabled() &&
 			high < debug_guardpage_minorder()) {
-
--[[linux-4.4.1/IS_ENABLED()]]
--[[linux-4.4.1/CONFIG_DEBUG_PAGEALLOC]]
--[[linux-4.4.1/debug_guardpage_enabled()]]
--[[linux-4.4.1/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;
-
--[[linux-4.4.1/set_page_guard()]]

 		}
 		list_add(&page[size].lru, &area->free_list[migratetype]);
 		area->nr_free++;
 		set_page_order(&page[size], high);
-オーダー high 用の free_area の free_list に空き領域を追加する。
--[[linux-4.4.1/list_add()]]
-page_order を high の値に設定する。
--[[linux-4.4.1/set_page_order()]]

 	}
 }


*コメント [#p1172d9c]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS