next up previous contents
Next: Alokator płytowy Up: Realizacja Previous: Przydział pamięci   Spis rzeczy

Zwolnienie pamięci

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
}



Adam Koprowski 2001-12-18