next up previous contents
Next: Realizacja Up: Alokator płytowy Previous: Opis   Spis rzeczy

Struktury danych

Struktura deskryptora pamięci podręcznej (UWAGA! - tylko najwazniejsze pola):

struct kmem_cache_t {
 struct list_head  slabs;          // częściowo uporządkowane płyty
 struct list_head  *firstnotfull;  // pierwsza niecałkiem pełna płyta
 unsigned int      objsize;        // rozmiar obiektu
 unsigned int      flags;          // flagi - m.in. CFLGS_OFF_SLAB oznacza,
                                   // że deskryptory poza płytą
 unsigned int      num;            // ilość obiektów w płycie
 unsigned int      gfporder;       // określa rozmiar płyty
                                   // przekazywane do get_free_pages
 unsigned int      gfpflags;       // flagi dla get_free_pages
 size_t            colour;         // wartość maksymalnego koloru płyty
 unsigned int      colour_next;    // kolor następnej płyty
 void (*ctor)(void *, kmem_cache_t *, unsigned long);  // konstruktor
 void (*dtor)(void *, kmem_cache_t *, unsigned long);  // destruktor
 char              name[CACHE_NAMELEN];                // nazwa pamięci podręcznej
 struct list_head  next;                               // następna pamięć podr.
};

Struktura deskryptora płyty:

struct slab_t {
 struct list_head  list;       // lista deskryptorów płyt
 unsigned long     colouroff;  // przesunięcie pierwszego obiektu w płycie
                               // (na skutek kolorowania)
 void              *s_mem;     // pierwszy obiekt w płycie (uwzględnione
                               // przesunięcie wynikające z kolorowania)
 unsigned int      inuse;      // liczba używanych obiektów w płycie
 kmem_bufctl_t     free;       // indeks wolnego obiektu (patrz opis 
                               // deskryptora obiektu)
};

Wreszcie deskryptor obiektu:

typedef unsigned int kmem_bufctl_t; // deskryptor obiektu w płycie

#define slab_bufctl(slabp) \        // makro dające dostęp do deskryptora
         ((kmem_bufctl_t *)(((slab_t*)slabp)+1))  // pierwszego obiektu

#define BUFCTL_END 0xffffFFFF       // znacznik końca `listy'
Jak widać deskryptor obiektu to po prostu liczba. Jest ona wykorzystywana całkiem sprytnie - przy jej pomocy organizowana jest lista wolnych obiektów w płycie, gdzie indeks obiektu funkcjonuje niejako jako wskaźnik do obiektu. Jest to połączone ze sprytną arytmetyką na wskaźnikach w celu dostępu do obiektu o danym indeksie (wskaźnik do obiektu o indeksie i to po prostu slabd->s_mem + i*cached->objsize). Trochę jaśniej (mam nadzieję): dla obiektu wolnego deskryptor ten jest po prostu numerem kolejnego wolnego obiektu. Dodatkowo pole free w deskryptorze płyty (slab_t) to indeks pierwszego wolnego obiektu w całej płycie, a stała BUFCTL_END jest znacznikiem końca takiej listy.

Przy tworzeniu pustej płyty kolejne deskryptory otrzymują kolejne wartości poczynając od 1, poza ostatnim, w którym wpisane zostaje BUFCTL_END, a pole free w deskryptorze płyty jest ustawiane na 0. Przy poszukiwaniu obiektu do alokacji zagląda się do pola free - będzie to indeks głowy naszej listy i zostanie przydzielony jako obiekt, a do pola free wpisana zostanie wartość, którą przechowywał jego deskryptor (czyli kolejny wolny obiekt) (to ważne) wolnego obiektu. Przy dealokacji natomiast obiekt wstawiany jest na początek listy, czyli free ustawiane jest na niego, a w jego deskryptor wpisywana jest stara wartość free.

Być może na początku zrozumienie funkcjonowania tego może być trochę kłopotliwe, ale kluczowe jest uzmysłowienie sobie, że to nic innego jak lista zorganizowana na indeksach tablicy. Mam nadzieję, że pomocny okaże się ten rysunek:

\includegraphics{pic/figSlab1.eps}
Organizacja listy wolnych obiektów w płycie i budowa płyty


next up previous contents
Next: Realizacja Up: Alokator płytowy Previous: Opis   Spis rzeczy
Adam Koprowski 2001-12-18