

static struct page * rmqueue(zone_t *zone, unsigned long order)
{
free_area_t * area = zone->free_area + order;
unsigned long curr_order = order;
do {
head = &area->free_list;
curr = memlist_next(head);
if (curr != head) { /* czy jest wolny blok na tym poziomie? */
unsigned int index;
page = memlist_entry(curr, struct page, list);
memlist_del(curr); /* usuń blok z listy wolnych */
/* uaktualnij licznik wolnych stron: */
zone->free_pages -= 1 << order;
page = expand(zone, page, index, order, curr_order, area);
return page;
}
curr_order++; /* przejdź do następnego poziomu */
area++;
} while (curr_order < MAX_ORDER);
}
Powyższy fragment kodu szuka najmniejszego wolnego bloku o rozmiarze nie mniejszym niż żądany (2^order), następnie jeśli taki znajdzie to usuwa go z listy i wykonuje funkcję expand() - ta funkcja kolejno dzieli ten blok na połówki aż do otrzymania bloku o pożądanej wielkości - ten blok zwraca, a pozostałe dodaje do listy wolnych.
static void __free_pages_ok (struct page *page, unsigned long order)
{
mask = (~0UL) << order;
base = zone->zone_mem_map;
page_idx = page - base;
index = page_idx >> (1 + order);
area = zone->free_area + order;
zone->free_pages -= mask;
while (mask + (1 << (MAX_ORDER-1))) {
if (!__test_and_change_bit(index, area->map))
/* Blok bliźniaczy jest zajęty - nie ma go na liście wolnych */
break;
/* Blok bliźniaczy jest na liście wolnych */
buddy1 = base + (page_idx ^ -mask);
buddy2 = base + page_idx;
/* Usuń go więc z listy wolnych, a bloki bliźniacze połącz: */
memlist_del(&buddy1->list);
mask <<= 1;
area++;
index >>= 1;
page_idx &= mask;
}
/* Dodaj blok do listy wolnych bloków: */
memlist_add_head(&(base + page_idx)->list, &area->free_list);
}
Uwagi:

