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: