Linux Kernel Architecture

(Jacob Rumans) #1

Chapter3:MemoryManagement


migrate list from the allocation flags. The previously introduced functionallocflags_to_migratetype
(see Section 3.5.2) comes in handy here.

When only a single page is desired, the kernel tries to speed up the request with the help of the per-CPU
cache. If the cache is empty, the kernel takes the opportunity to check the cache fill level.

mm/page_alloc.c
again:
if (order == 0) {
struct per_cpu_pages *pcp;

page = NULL;
pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
if (!pcp->count)
pcp->count = rmqueue_bulk(zone, 0,
pcp->batch, &pcp->list);
if (unlikely(!pcp->count))
goto failed;
}
...

Once the appropriate (i.e., hot or cold) per-CPU list for the current processor has been selected,
rmqueue_bulkis invoked to refill the cache. I won’t reproduce the function here as it simply removes
pages from the normal buddy system and adds them to the cache. However, it is important to note that
buffered_rmqueuestores the migrate type of the page in theprivateelement ofstruct page. This will
become important when pages are taken off the cache:

mm/page_alloc.c
/* Find a page of the appropriate migrate type */
list_for_each_entry(page, &pcp->list, lru)
if (page_private(page) == migratetype)
break;

/* Allocate more to the pcp list if necessary */
if (unlikely(&page->lru == &pcp->list)) {
pcp->count += rmqueue_bulk(zone, 0,
pcp->batch, &pcp->list, migratetype);
page = list_entry(pcp->list.next, struct page, lru);
}

list_del(&page->lru);
pcp->count--
} else {
page = __rmqueue(zone, order);
if (!page)
goto failed;
}
...

The kernel iterates over all pages on the per-CPU cache and checks if the page of the desired migrate
type is available. This need not be the case if the cache has been refilled by a previous call with pages of a
different migrate type. If no suitable page is found, some more pages with the currently desired migrate
Free download pdf