Tutaj można by uznać, że mamy do czynienia z nieco prosztszą sytuacją, gdyż jedyne co funkcja musi zrobić, to dokonać niezbędne zmiany w strukturach, których wymaga algorytm bliźniaków, a które zostały wcześniej omówione. Niestety kilka trick'ów stosowanych przez autorów i arytmetyka na wskaźnikach sprawiają, że wcale nie jest tak łatwo zorientować się co tutaj właściwie się dzieje 1. Pozwolę sobie tutaj pominąć serię testów na błędy jakie występują w orginalnych źródłach, w celu zwiększenia czytelności i zmniejszenia długości listingu.
static void __free_pages_ok (struct page *page, unsigned long order) { unsigned long index, page_idx, mask, flags; free_area_t *area; struct page *base; zone_t *zone; // strefa pamięci -- dokonanie serii testów i ustawień powyższych zmiennych. -- założenie spinlock'a while (mask + (1 << (MAX_ORDER - 1))) { // Aż przejrzymy wszystkie listy struct page *buddy1, *buddy2; if (!test_and_change_bit(index, area->map)) // bilźniak wciąż zaalokowany break; // koniec pracy // łączymy bliźniaków // najpierw znajdujemy ramki, w których zaczynają się obaj bliźniacy buddy1 = base + (page_idx ^ -mask); // Huh... -mask == 1 + ~mask buddy2 = base + page_idx; memlist_del(&buddy1->list); // kasujemy bliźniaka z listy wolnych // bloków - łączymy się z nim mask <<= 1; // maska na dany rozmiar bloku - za // każdym razem obszar powiększa się // dwukrotnie area++; // przejście do kolejnej listy index >>= 1; // interesująca pozycja w mapie bitowej page_idx &= mask; // wyliczenie pozycji ramki dla bliźniaka // na kolejnym poziomie } // pozostaje dopisać nowy blok (być może powstały z połączenia) // do listy wolnych bloków memlist_add_head(&(base + page_idx)->list, &area->free_list); -- zdjęcie spinlock'a }