Chapter3:MemoryManagement
The search can come to an end here for two reasons:
- __GFP_NOMEMALLOCis set. This flag prohibits using the emergency reserve (which can well
be if the watermarks are ignored), so callingget_page_from_freelistwithout obeying the
watermarks is forbidden. The kernel can do nothing more than fail ultimately in this case by
jumping to thenoopagelabel, where the failure is reported to the user with a kernel message,
and aNULLpointer is returned to the caller.
- get_page_from_freelistfails despite watermarks being ignored. In this case, the search
is also aborted and terminates with an error message. However, if__GFP_NOFAILis set, the
kernel goes into an endless loop (implemented by branching back to thenofail_alloclabel)
to first wait (by means ofcongestion_wait) for the end of ‘‘congestion‘‘ in the block layer,
which can arise when pages are reclaimed (see Chapter 18). Allocation is then attempted
again until it succeeds.
IfPF_MEMALLOCis not set, the kernel still has some more options to try, but these require going sleep. This
is necessary to allowkswapdto make some progress.
The kernel now enters on aslow pathwhere time-consuming operations begin. A prerequisite is that the
__GFP_WAITflag is set in the allocation mask because the subsequent actions can put the process to sleep.
mm/page_alloc.c
/* Atomic allocations - we can’t balance anything */
if (!wait)
goto nopage;
cond_schedule();
...
Recall thatwaitis 1 if the bit is set, and 0 otherwise. If this flag is not set, allocation is aborted at this
point. Before further attempts are made, the kernel provides the opportunity of rescheduling by means
ofcond_resched. This prevents too much time being spent searching for memory so that other tasks are
left unfulfilled.
The paging mechanism provides an as-yet-unused option for swapping rarely used pages out to a block
medium to create more space in RAM. However, this option is very time-consuming and can sleep.
try_to_free_pagesis the respective helper function that attempts to find pages that are currently not
urgently needed and can therefore be swapped out. It is invoked after thePF_MEMALLOCflag has been set
for the task to indicate to the remaining kernel codethat all subsequent memory allocations are needed
in the search for memory.
mm/page_alloc.c
/* We now go into synchronous reclaim */
p->flags |= PF_MEMALLOC;
...
did_some_progress = try_to_free_pages(zonelist->zones, order, gfp_mask);
...
p->flags &= ~PF_MEMALLOC;
cond_resched();
...