前回の記事では__rmqueue_smallest()を見たので、今回は __rmqueue_fallback()を見ていきます。
この関数の呼び出し元は__rmqueue()で、__rmqueue_smallest()でメモリを確保できなかった場合に実行されます。 では、処理を見ていきましょう。
__rmqueue_fallback()は2つのforループにより制御されていて、ここが一番重要なところ
一番外側のループは orderの最大値(通常は11かな)-1を初期値として、メモリ確保しようとしたorderまでorderを下げつつループする
内側のループは配列(fallbacks)http://lxr.free-electrons.com/source/mm/page_alloc.c?v=4.0#L1032を見ていくためのもの この配列はMIGRATEの種類を保持している2次元配列で、fallbacks[x][y]とあったときに、xはmigratetypeをインデックスに使う 例えば、migratetypeがMIGRATE_RECLAIMABLEだった場合、fallbacks[MIGRATE_RECLAIMABLE]で該当の要素を取得して、そこに設定されているMIGRATETYPEを用いてブロックを確保できるか試みる ようは、当初指定されたmigratetypeではなくて、そのmigratetypeから変更できるマイグレートの種類からブロックの確保を行う
ここまでで、当たらに試すべきorderとmigratetypeが決まったので、次は実際にブロックの確保ができるかを行っていく
この辺の処理は前回の記事では__rmqueue_smallest()と変わらないので割愛
唯一違うところは、migratetypeがMIGRATE_CMAだった場合にtry_to_steal_freepages()が呼ばれて、多少処理があります しかし、Fedora 22、Arch LinuxどちらもデフォルトではCONFIG_CMAは有効になってないので無視しましょう。 そもそも、カーネルでもmigratetypeがMIGRATE_CMAなことはまずないと考えられているみたいだし。
include/linux/mmzone.hでこうなってます。
66 #ifdef CONFIG_CMA 67 # define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA) 68 #else 69 # define is_migrate_cma(migratetype) false 70 #endif 71
- このCMAの部分以外は__rmqueue_smallest()と同じです。 ブロックを確保できて、それが元のorderよりも大きければ分割してorderが小さい方に持って行ってという流れです。
この辺が __alloc_pages_nodemask()でget_page_from_freelist()を呼んでメモリを確保する部分です。 もし、get_page_from_freelist()がNULLを返した場合は、__alloc_pages_slowpath()を呼んでメモリの確保を試します。それでもメモリ確保できなければNULLを返す以外になくなります。
というわけで、次回は__alloc_pages_slowpath()を見てみましょう。
- 作者: 平田豊
- 出版社/メーカー: 工学社
- 発売日: 2011/07
- メディア: 単行本
- 購入: 1人 クリック: 48回
- この商品を含むブログ (5件) を見る