Linux Kernel Architecture

(Jacob Rumans) #1

Chapter3:MemoryManagement


all when too little memory is available to satisfy a request or when available memory is slowly running
out. If sufficient memory is available, the necessary work is quickly done as the start of the code shows.

mm/page_alloc.c
struct page * fastcall
__alloc_pages(gfp_t gfp_mask, unsigned int order,
struct zonelist *zonelist)
{
const gfp_t wait = gfp_mask & __GFP_WAIT;
struct zone **z;
struct page *page;
struct reclaim_state reclaim_state;
struct task_struct *p = current;
int do_retry;
int alloc_flags;
int did_some_progress;

might_sleep_if(wait);

restart:
z = zonelist->zones; /* the list of zones suitable for gfp_mask */

if (unlikely(*z == NULL)) {
/*
* Happens if we have an empty zonelist as a result of
* GFP_THISNODE being used on a memoryless node
*/
return NULL;
}

page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order,
zonelist, ALLOC_WMARK_LOW|ALLOC_CPUSET);
if (page)
goto got_pg;
...

In the simplest scenario, allocation of a fresh memory area involves a single invocation of
get_page_from_freelistto return the required number of pages (which is handled by the code at the
labelgot_pg).

The first memory allocation attempt is not particularly aggressive. A failure to find memory in any of the
zones means that there isn’t much memory left but requires more than a moderate increase in effort from
the kernel to find more memory (the big guns are brought out later).

mm/page_alloc.c
...
for (z = zonelist->zones; *z; z++)
wakeup_kswapd(*z, order);

alloc_flags = ALLOC_WMARK_MIN;
if ((unlikely(rt_task(p)) && !in_interrupt()) || !wait)
alloc_flags |= ALLOC_HARDER;
if (gfp_mask & __GFP_HIGH)
Free download pdf