Chapter3:MemoryManagement
mm/page_alloc.c
static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist,
int nr_zones, enum zone_type zone_type)
{
struct zone *zone;
do {
zone = pgdat->node_zones + zone_type;
if (populated_zone(zone)) {
zonelist->zones[nr_zones++] = zone;
}
zone_type--;
} while (zone_type >= 0);
return nr_zones;
}
The fallback list entries are ordered by means of thezone_typeparameter that specifies the zone from
which memory is best taken and is calculated usinghighest_zoneas shown. Recall that it can have one
of the following values:ZONE_HIGHMEM,ZONE_NORMAL,ZONE_DMA,orZONE_DMA32.nr_zonedenotes the
position in the fallback list at which filling new entries starts. The caller has passed 0 since there is no
entry in the list yet.
The kernel then iterates over all zones from costly to less costly. In each step,populated_zoneensures
thatzone->present_pagesis greater than 0 for the selected zone; that is, whether there are pages in the
zone. If so, a pointer to thezoneinstance previously determined is added at the current position within
thezonelistzonelist->zones. The current position in the zone list is held innr_zone.
At the end of each step, the zone type is decremented by 1; in other words, it is set to a more costly zone
type. For example, if the start zone isZONE_HIGHMEM, decrementing by 1 ensures that the next zone type
used isZONE_NORMAL.
Consider a system with the zonesZONE_HIGHMEM,ZONE_NORMAL,andZONE_DMA.Inthefirstrunof
build_zonelists_node, the following assignments are made:
zonelist->zones[0] = ZONE_HIGHMEM;
zonelist->zones[1] = ZONE_NORMAL;
zonelist->zones[2] = ZONE_DMA;
Figure 3-9 illustrates this for the case in which a fallback list for node 2 of a system is successively filled.
There are a total of four nodes in the system (numnodes = 4);k = ZONE_HIGHMEMalso applies.
C2 C1 C0
C0C1C2 D2 D1 D0
C0C1C2 D2 D1 D0 A2 A1 A0 B2 B1 B0
... NULL
A = Node 0
B = Node 1
C = Node 2
D = Node 3
0 = DMA
1 = Normal
2 = Highmem
Figure 3-9: Successive filling of the fallback list.