[Linux kernel memory management] Physical allocation page ⑧ ( __alloc_pages_slowpath slow path call function source code analysis | get preferred memory area | asynchronously reclaim memory pages | lowest waterline also allocated | direct allocation )

In the [Linux Kernel Memory Management] Physical Allocation Page ② ( __alloc_pages_nodemask function parameter analysis | __alloc_pages_nodemask function allocation physical page process) blog, the __alloc_pages_nodemaskfunction as follows:

First , according to the gfp_t gfp_maskallocation flag parameter, get the preferred "region type" and "migration type" of "memory node ";

Then , perform the "fast path" , the first allocation attempt uses a low watermark allocation;

If the above "fast path" assignment fails, then a "slow path" assignment is performed;

The above refers to "fast path" and "slow path" 2 22 physical page allocation methods;


Continue to the previous blog [Linux Kernel Memory Management] Physical Allocation Page ⑦ ( __alloc_pages_slowpath slow path call function source code analysis | judging page order | reading mems_allowed | allocation flag conversion) analysis Follow-up of the __alloc_pages_slowpath slow path memory allocation call function part of the source code;





1. Get the preferred memory area



Get the "preferred memory area", if the acquisition fails, gotojump to the nopagelabel position to run the subsequent code;

	/*
	 * We need to recalculate the starting point for the zonelist iterator
	 * because we might have used different nodemask in the fast path, or
	 * there was a cpuset modification and we are retrying - otherwise we
	 * could end up iterating over non-eligible zones endlessly.
	 */
	ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
					ac->high_zoneidx, ac->nodemask);
	if (!ac->preferred_zoneref->zone)
		goto nopage;

Source code path: linux-4.12\mm\page_alloc.c #3731





2. Asynchronously reclaiming memory pages



Call a wake_all_kswapdsfunction to asynchronously recycle physical memory pages,

The asynchrony here is to recycle memory pages by waking up the "recycling thread" ;

	if (gfp_mask & __GFP_KSWAPD_RECLAIM)
		wake_all_kswapds(order, ac);

Source path: linux-4.12\mm\page_alloc.c #3736





3. The lowest water line is also allocated



call get_page_from_freelistfunction to use "lowest watermark" for physical page allocation,

If the processing is successful, jump to the got_pglabel to execute;

	/*
	 * The adjusted alloc_flags might result in immediate success, so try
	 * that first
	 */
	page = get_page_from_freelist(gfp_mask, order, alloc_flags, ac);
	if (page)
		goto got_pg;

Source code path: linux-4.12\mm\page_alloc.c #3743





Fourth, allocate memory directly



Apply for the order of physical page memory , meet the following 3 33 conditions:

can_direct_reclaim

(costly_order || (order > 0 && ac->migratetype != MIGRATE_MOVABLE))

!gfp_pfmemalloc_allowed(gfp_mask)

Execute the branch "directly allocate memory" operation;

	/*
	 * For costly allocations, try direct compaction first, as it's likely
	 * that we have enough base pages and don't need to reclaim. For non-
	 * movable high-order allocations, do that as well, as compaction will
	 * try prevent permanent fragmentation by migrating from blocks of the
	 * same migratetype.
	 * Don't try this for allocations that are allowed to ignore
	 * watermarks, as the ALLOC_NO_WATERMARKS attempt didn't yet happen.
	 */
	if (can_direct_reclaim &&
			(costly_order ||
			   (order > 0 && ac->migratetype != MIGRATE_MOVABLE))
			&& !gfp_pfmemalloc_allowed(gfp_mask)) {
    
    
		page = __alloc_pages_direct_compact(gfp_mask, order,
						alloc_flags, ac,
						INIT_COMPACT_PRIORITY,
						&compact_result);
		if (page)
			goto got_pg;

		/*
		 * Checks for costly allocations with __GFP_NORETRY, which
		 * includes THP page fault allocations
		 */
		if (costly_order && (gfp_mask & __GFP_NORETRY)) {
    
    
			/*
			 * If compaction is deferred for high-order allocations,
			 * it is because sync compaction recently failed. If
			 * this is the case and the caller requested a THP
			 * allocation, we do not want to heavily disrupt the
			 * system, so we fail the allocation instead of entering
			 * direct reclaim.
			 */
			if (compact_result == COMPACT_DEFERRED)
				goto nopage;

			/*
			 * Looks like reclaim/compaction is worth trying, but
			 * sync compaction could be very expensive, so keep
			 * using async compaction.
			 */
			compact_priority = INIT_COMPACT_PRIORITY;
		}
	}

Source code path: linux-4.12\mm\page_alloc.c #3756

Guess you like

Origin blog.csdn.net/han1202012/article/details/124453282