参照元†
- ゾーンにmark以上の空きページがあるか取得する。
- markに指定する値は任意だが、watermarkが指定されることが多い。
- struct zone *z
- unsigned int order
- オーダー。カーネルのメモリ確保関数は、ページ数を2^orderの形で表すことがある。つまりorder 0 = 1ページ, order 1 = 2ページ, order 2 = 4ページ, order 3 = 8ページのようになる。
- unsigned long mark
- 十分な空きページがあると判定するための閾値。指定する値は任意だが、watermarkが指定されることが多い。
- int highest_zoneidx
- ゾーンインデックス。このインデックス以下のゾーンからメモリを確保する。
- unsigned int alloc_flags
- long free_pages
- 空きページ数。
- zone_page_state(z, NR_FREE_PAGES)を指定することが多い。
返り値†
- bool
- 十分な空きページがあればtrue、なければfalse。
/*
* Return true if free base pages are above 'mark'. For high-order checks it
* will return true of the order-0 watermark is reached and there is at least
* one free page of a suitable size. Checking now avoids taking the zone lock
* to check in the allocation paths if no pages are free.
*/
bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
int highest_zoneidx, unsigned int alloc_flags,
long free_pages)
{
long min = mark;
int o;
const bool alloc_harder = (alloc_flags & (ALLOC_HARDER|ALLOC_OOM));
/* free_pages may go negative - that's OK */
free_pages -= __zone_watermark_unusable_free(z, order, alloc_flags);
- 空きページ数(free_pages)から割り当て不能な領域を除外する。
if (alloc_flags & ALLOC_HIGH)
min -= min / 2;
- ALLOC_HIGHフラグがあったら、markを引き下げて1/2にする
if (unlikely(alloc_harder)) {
/*
* OOM victims can try even harder than normal ALLOC_HARDER
* users on the grounds that it's definitely going to be in
* the exit path shortly and free memory. Any allocation it
* makes during the free path will be small and short-lived.
*/
if (alloc_flags & ALLOC_OOM)
min -= min / 2;
else
min -= min / 4;
}
- ALLOC_HARDER, ALLOC_OOMフラグがあったらmarkを引き下げて、普段よりメモリを確保しようとする。
- ALLOC_HARDER: markを3/4にする
- ALLOC_OOM : markを1/2にする
/*
* Check watermarks for an order-0 allocation request. If these
* are not met, then a high-order request also cannot go ahead
* even if a suitable page happened to be free.
*/
if (free_pages <= min + z->lowmem_reserve[highest_zoneidx])
return false;
- free_pagesがmark + protection以下だったら十分な空きメモリがないと判断しfalseを返す。
/* If this is an order-0 request then the watermark is fine */
if (!order)
return true;
- free_pagesがwatermark + protection以上で、order 0なら十分な空きメモリがあると判断しtrueを返す。
- order 1以上の場合はさらに追加の判定が必要。
/* For a high-order request, check at least one suitable page is free */
for (o = order; o < MAX_ORDER; o++) {
struct free_area *area = &z->free_area[o];
int mt;
if (!area->nr_free)
continue;
- 注目しているorderの空きブロック数が0なら、もう1段階大きいorderを見に行く。
for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) {
if (!free_area_empty(area, mt))
return true;
}
- MIGRATE_UNMOVABLE, MOVABLE, RECLAIMABLEを見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。
#ifdef CONFIG_CMA
if ((alloc_flags & ALLOC_CMA) &&
!free_area_empty(area, MIGRATE_CMA)) {
return true;
}
#endif
- CMAから確保してよければMIGRATE_CMAも見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。
MIGRATE_CMAの空き容量は/proc/zoneinfoのnr_free_cmaで確認できる。
if (alloc_harder && !free_area_empty(area, MIGRATE_HIGHATOMIC))
return true;
- ALLOC_HARDERかALLOC_OOMが指定されていたら、MIGRAGE_HIGHATOMICを見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。
}
return false;
}
コメント†