#author("2025-09-10T15:44:27+09:00","default:guest","guest") #author("2025-09-10T16:56:17+09:00","default:guest","guest") *参照元 [#lf84ca32] #backlinks *説明 [#wf684f6e] -パス: [[linux-5.15/mm/page_alloc.c]] -ゾーンにmark以上の空きページがあるか取得する。 --markに指定する値は任意だが、watermarkが指定されることが多い。 **引数 [#q19c0df5] -struct zone *z --メモリゾーン。 --[[linux-5.15/zone]] -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)を指定することが多い。 **返り値 [#t5b04011] -bool --十分な空きページがあればtrue、なければfalse。 **参考 [#ae5f60c8] *実装 [#j7b78854] /* * 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)から割り当て不能な領域を除外する。 -[[linux-5.15/__zone_watermark_unusable_free()]] /* free_pages may go negative - that's OK */ free_pages -= __zone_watermark_unusable_free(z, order, alloc_flags); ALLOC_HIGHフラグがあったら、markを引き下げて1/2にする -空きページ数(free_pages)から割り当て不能な領域を除外する。 --[[linux-5.15/__zone_watermark_unusable_free()]] if (alloc_flags & ALLOC_HIGH) min -= min / 2; -ALLOC_HIGHフラグがあったら、markを引き下げて1/2にする ALLOC_HARDER, ALLOC_OOMフラグがあったらmarkを引き下げて、普段よりメモリを確保しようとする。 - ALLOC_HARDER: markを3/4にする - ALLOC_OOM : 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; } free_pagesがmark + protection以下だったら十分な空きメモリがないと判断しfalseを返す。 -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がwatermark + protection以上で、order 0なら十分な空きメモリがあると判断しtrueを返す。 order 1以上の場合はさらに追加の判定が必要。 -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; 注目しているorderの空きブロック数が0なら、もう1段階大きいorderを見に行く。 --[[linux-5.15/free_area]] if (!area->nr_free) continue; MIGRATE_UNMOVABLE, MOVABLE, RECLAIMABLEを見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。 -注目しているorderの空きブロック数が0なら、もう1段階大きいorderを見に行く。 --[[linux-5.15/free_area]] - 0: MIGRATE_UNMOVABLE - 1: MIGRATE_MOVABLE - 2: MIGRATE_RECLAIMABLE - 3: MIGRATE_PCPTYPES = MIGRATE_HIGHATOMIC --[[linux-5.15/migratetype]] --[[linux-5.15/free_area_empty()]] for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) { if (!free_area_empty(area, mt)) return true; } CMAから確保してよければMIGRATE_CMAも見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。 MIGRATE_CMAの空き容量は/proc/zoneinfoのnr_free_cmaで確認できる。 - 4: MIGRATE_CMA -MIGRATE_UNMOVABLE, MOVABLE, RECLAIMABLEを見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。 --0: MIGRATE_UNMOVABLE --1: MIGRATE_MOVABLE --2: MIGRATE_RECLAIMABLE --3: MIGRATE_PCPTYPES = MIGRATE_HIGHATOMIC --[[linux-5.15/migratetype]] --[[linux-5.15/free_area_empty()]] #ifdef CONFIG_CMA if ((alloc_flags & ALLOC_CMA) && !free_area_empty(area, MIGRATE_CMA)) { return true; } #endif ALLOC_HARDERかALLOC_OOMが指定されていたら、MIGRAGE_HIGHATOMICを見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。 - 3: MIGRATE_PCPTYPES = MIGRATE_HIGHATOMIC -CMAから確保してよければMIGRATE_CMAも見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。 MIGRATE_CMAの空き容量は/proc/zoneinfoのnr_free_cmaで確認できる。 --4: MIGRATE_CMA --[[linux-5.15/migratetype]] if (alloc_harder && !free_area_empty(area, MIGRATE_HIGHATOMIC)) return true; -ALLOC_HARDERかALLOC_OOMが指定されていたら、MIGRAGE_HIGHATOMICを見に行く。空いていれば十分な空きメモリがあると判断しtrueを返す。 --3: MIGRATE_PCPTYPES = MIGRATE_HIGHATOMIC --[[linux-5.15/migratetype]] } return false; } *コメント [#e23a4086]