Linuxのbuddy allocatorでpage数のwatermarkをチェックしているのは__zone_watermark_ok()。そんなわけで、今日はその辺りの動作を見てみる。
__zone_watermark_ok()は他のファイルから直接呼べないので、zone_watermark_ok()を使う。例えば、mm/compaction.cにあるtry_to_compact_pages()はwatermarkを下回らないzoneを対象に処理するので、zone_watermark_ok()を使う。
zone_watermark_ok()はこのように__zone_watermark_ok()を呼ぶ。最後の引数は対象のzone、zの空きページ数。
1834 bool zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, 1835 int classzone_idx, int alloc_flags) 1836 { 1837 return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, 1838 zone_page_state(z, NR_FREE_PAGES)); 1839 }
zone_page_state()はこのような関数でzone構造体のメンバ変数vm_statを参照する。
130 static inline unsigned long zone_page_state(struct zone *zone, 131 enum zone_stat_item item) 132 { 133 long x = atomic_long_read(&zone->vm_stat[item]); 134 #ifdef CONFIG_SMP 135 if (x < 0) 136 x = 0; 137 #endif 138 return x; 139 }
vm_statはstruct zoneの定義の一番最後にある。
528 /* Zone statistics */ 529 atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
NR_FREE_PAGESはenum型で、include/linux/mmzone.hで定義されている。
114 enum zone_stat_item { 115 /* First 128 byte cacheline (assuming 64 bit words) */ 116 NR_FREE_PAGES, 117 NR_ALLOC_BATCH, ~略~
そして、本日のメインになる__zone_watermark_ok()はこちら。
1799 static bool __zone_watermark_ok(struct zone *z, unsigned int order, 1800 unsigned long mark, int classzone_idx, int alloc_flags, 1801 long free_pages) 1802 { 1803 /* free_pages may go negative - that's OK */ 1804 long min = mark; 1805 int o; 1806 long free_cma = 0; 1807
最初に空きページ数からorder分のpage数-1した数を引く。
1808 free_pages -= (1 << order) - 1;
次に、alloc_flagsの設定によって、watermarkの位置を変更する。 ここの計算は2.6.12-rc1の時点ですでにこうなってたらしい。
1809 if (alloc_flags & ALLOC_HIGH) 1810 min -= min / 2; 1811 if (alloc_flags & ALLOC_HARDER) 1812 min -= min / 4;
Contiguous Memory Allocator機能が有効な場合はCMAの領域についても空きページ数を調べる。
1813 #ifdef CONFIG_CMA 1814 /* If allocation can't use CMA areas don't use free CMA pages */ 1815 if (!(alloc_flags & ALLOC_CMA)) 1816 free_cma = zone_page_state(z, NR_FREE_CMA_PAGES); 1817 #endif
空きページ数(CMA以外 + CMA)を足してもまだwatermarkまで回復しない場合はfalse。try_to_compact_pages()から呼ばれた場合だと、このzoneはcompactionしないということになる。
1818 1819 if (free_pages - free_cma <= min + z->lowmem_reserve[classzone_idx]) 1820 return false;
次に、対象のzone「z」のorder「o」のfree_areaの空きページ数をo分左シフトした値と、minを2で割った値を比較して、空きページ数の方が下回るならfalseを返す。これをorder 0から確保しようとしたoder - 1まで実行する。
1821 for (o = 0; o < order; o++) { 1822 /* At the next order, this order's pages become unavailable */ 1823 free_pages -= z->free_area[o].nr_free << o; 1824 1825 /* Require fewer higher order pages to be free */ 1826 min >>= 1; 1827 1828 if (free_pages <= min) 1829 return false; 1830 } 1831 return true; 1832 } 1833
途中でreturnせずにforループを抜けたら問題なしということでtrueを返す。
The Art of Computer Programming Volume 1 Fundamental Algorithms Third Edition 日本語版
- 作者: Donald E.Knuth,有澤 誠,和田 英一,有澤誠,和田英一,青木孝,筧一彦,鈴木健一,長尾高弘
- 出版社/メーカー: KADOKAWA
- 発売日: 2015/06/26
- メディア: 単行本
- この商品を含むブログを見る