#author("2025-09-10T18:52:04+09:00","default:guest","guest") #author("2025-09-10T18:58:11+09:00","default:guest","guest") *参照元 [#ibebb39a] #backlinks *説明 [#b7993f50] -パス: [[linux-5.15/]] -パス: [[linux-5.15/mm/compaction.c]] -FIXME: これは何? --説明 **引数 [#zaa333b0] - -pg_data_t *pgdat -- --[[linux-5.15/pg_data_t]] **返り値 [#r061ce2b] - -- -なし **参考 [#b3c7f72d] *実装 [#x24667b2] static void kcompactd_do_work() { /* * With no special task, compact all zones so that a page of requested * order is allocatable. */ int zoneid; struct zone *zone; struct compact_control cc = { .order = pgdat->kcompactd_max_order, .search_order = pgdat->kcompactd_max_order, .highest_zoneidx = pgdat->kcompactd_highest_zoneidx, .mode = MIGRATE_SYNC_LIGHT, .ignore_skip_hint = false, .gfp_mask = GFP_KERNEL, }; trace_mm_compaction_kcompactd_wake(pgdat->node_id, cc.order, cc.highest_zoneidx); count_compact_event(KCOMPACTD_WAKE); - --[[linux-5.15/zone]] --[[linux-5.15/compact_control]] --[[linux-5.15/trace_mm_compaction_kcompactd_wake()]] --[[linux-5.15/count_compact_event()]] for (zoneid = 0; zoneid <= cc.highest_zoneidx; zoneid++) { int status; zone = &pgdat->node_zones[zoneid]; if (!populated_zone(zone)) continue; -ページを持たないゾーンは無視します。 --[[linux-5.15/populated_zone()]] if (compaction_deferred(zone, cc.order)) continue; -コンパクションを延期するなら、このゾーンは無視します。 --[[linux-5.15/compaction_deferred()]] if (compaction_suitable(zone, cc.order, 0, zoneid) != COMPACT_CONTINUE) continue; -コンパクションを実施しない(結果がCOMPACT_CONTINUE以外)なら、このゾーンは無視します。 --[[linux-5.15/compaction_suitable()]] if (kthread_should_stop()) return; -終了すべきなら関数を抜けます。 --[[linux-5.15/kthread_should_stop()]] cc.zone = zone; status = compact_zone(&cc, NULL); -コンパクションを実施します。 --[[linux-5.15/compact_zone()]] if (status == COMPACT_SUCCESS) { compaction_defer_reset(zone, cc.order, false); -コンパクションに成功したので延期条件をリセットします。 --[[linux-5.15/compaction_defer_reset()]] } else if (status == COMPACT_PARTIAL_SKIPPED || status == COMPACT_COMPLETE) { /* * Buddy pages may become stranded on pcps that could * otherwise coalesce on the zone's free area for * order >= cc.order. This is ratelimited by the * upcoming deferral. */ drain_all_pages(zone); /* * We use sync migration mode here, so we defer like * sync direct compaction does. */ defer_compaction(zone, cc.order); } - --[[linux-5.15/drain_all_pages()]] --[[linux-5.15/defer_compaction()]] count_compact_events(KCOMPACTD_MIGRATE_SCANNED, cc.total_migrate_scanned); count_compact_events(KCOMPACTD_FREE_SCANNED, cc.total_free_scanned); VM_BUG_ON(!list_empty(&cc.freepages)); VM_BUG_ON(!list_empty(&cc.migratepages)); } - --[[linux-5.15/count_compact_events()]] --[[linux-5.15/VM_BUG_ON()]] --[[linux-5.15/list_empty()]] /* * Regardless of success, we are done until woken up next. But remember * the requested order/highest_zoneidx in case it was higher/tighter * than our current ones */ if (pgdat->kcompactd_max_order <= cc.order) pgdat->kcompactd_max_order = 0; if (pgdat->kcompactd_highest_zoneidx >= cc.highest_zoneidx) pgdat->kcompactd_highest_zoneidx = pgdat->nr_zones - 1; } *コメント [#h71cb58f]