Linux Kernel Architecture

(Jacob Rumans) #1

Chapter3:MemoryManagement


Once the batch size (which is the basis for calculating the minimum and maximum fill level) has
been determined withzone_batchsize, the code iterates over all CPUs in the system and invokes
setup_pagesetto fill the constants of eachper_cpu_pagesetinstance. Thezone_pcpmacro used when
this function is invoked selects thepagesetinstance of the zone associated with the CPU currently being
examined.

Let us take a closer look at how the watermark is calculated.

mm/page_alloc.c
static int __devinit zone_batchsize(struct zone *zone)
{
int batch;

batch = zone->present_pages / 1024;
if (batch * PAGE_SIZE > 512 * 1024)
batch = (512 * 1024) / PAGE_SIZE;
batch /= 4;
if (batch < 1)
batch = 1;

batch = (1 << (fls(batch + batch/2)-1)) - 1;

return batch;
}

The code calculatesbatchso that it corresponds to roughly 25 percent of a thousandth of the pages
present in the zone. The shift operation also ensures that the value calculated has the form 2nāˆ’1because
it has been established empirically that this minimizes cache aliasing effects for most system loads.fls
is a machine-specific operation to yield the last set bit of a value. Note that this alignment will cause the
resulting values to deviate from 25 percent of one-thousandth the zones pages. The maximal deviation
arises for that casebatch = 22.Since22+ 11 āˆ’ 1 =32,flswill find bit 5 as last set bit in the number, and
1<<5-1=31. Because the deviation will usually be smaller, it can be neglected for all practical purposes.

The batch size does not increase when the memory in the zone exceeds 512 MiB. For systems with a page
size of 4,096 KiB, for instance, this limit is reached when more than 131,072 pages are present. Figure 3-17
shows how the batch size evolves with the number of pages present in a zone.

The batch value makes sense when we consider howbatchis used to calculate the cache limits in
setup_pageset.

mm/page_alloc.c
inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
{
struct per_cpu_pages *pcp;

memset(p, 0, sizeof(*p));

pcp = &p->pcp[0]; /* hot */
pcp->count = 0;
pcp->high = 6 * batch;
pcp->batch = max(1UL, 1 * batch);
INIT_LIST_HEAD(&pcp->list);
Free download pdf