424 | | Dans le fichier , on peut voir qu'il existe un tableau `Objects[]` contenant de cases qu'il existe de taille d'objets possibles (mesurée en nombre de lignes) et dont chaque case contient le nombre d'objet libre |
425 | | de listes d'objets libres, indexé par les identifiants de slab (l'identifiant de slab est la taille des objets qu'il contient en nombre de lignes). Le tableau `Objects` contiens le nombre d'objets alloués. Il faudrait un autre tableau semblable contenant le nombre d'objets libres disponible. |
| 426 | |
| 427 | Si on alloue un objet d'une taille T et que la liste des objets libres de taille T est vide alors on ouvre un slab (on l'alloue). Si on libère l'objet de taille T, alors le slab est entièrement libre et on ferme le slab (on le libère). Si on fait ça en boucle, l'ouverture/fermeture (allocation/libération) des slabs est une perte de temps. Il est sans doute préférable d'avoir toujours des listes d'objets libres non vides. On peut donc définir un seuil d'objets libres en dessous duquel ne pas descendre. |
| 428 | |
| 429 | Dans le fichier `kernel/kmemory.c`, on peut voir qu'il existe un tableau `Objects[]` contenant autant de cases qu'il existe de taille d'objets possibles (mesurée en nombre de lignes) et dont chaque case contient le nombre d'objets alloués de cette taille. Ce tableau a 256 cases au maximum (si la ligne de cache fait 16 octets), la case 0 contient le nombre de pages allouées, la case 1 contient le nombre d'objets alloués d'1 ligne, la case 2 pour les objets de 2 lignes, etc. |
| 430 | |
| 431 | Il n'y a pas de tableau pour compter le nombre d'objets libres dans les listes d'objets. L'idée c'est d'en ajouter un, et ne pas demander la suppression de slab si le nombre d'objet est inférieur à un seuil choisi (qui pourrait être 1). |
| 432 | |
| 433 | **kernel/kfree** |
| 434 | |
| 435 | {{{#!c |
| 436 | void kfree (void * obj, size_t size) |
| 437 | { |
| 438 | size_t nbline= NBLINE(size) % MaxLinePage; // which slab to use |
| 439 | size_t npage = (size_t)(obj - (void *)kmb)>>12; // relative page number from kmb |
| 440 | |
| 441 | PANIC_IF ((nbline>255)||(npage >= NbPages), // too big or outside of the region |
| 442 | "\ncan't free object not allocated by kmalloc()"); // write a message then panic |
| 443 | |
| 444 | list_addfirst (&Slab[nbline], (list_t *)obj); // add it to the right free list |
| 445 | Objects[nbline]--; // decr the number of obj of size nbline |
| 446 | if (size == PAGE_SIZE) return; |
| 447 | if (--Page[npage].alloc==0) { // splitted page and no more object left |
| 448 | list_t *page = (list_t *)((size_t)obj & ~0xFFF); // address of the page containing obj |
| 449 | list_foreach (&Slab[nbline], item) { // browse all item in free list |
| 450 | size_t np_item = (size_t)((char*)item-kmb)>>12; // page number Page[] table |
| 451 | if (np_item == npage) { // if current item is in the page |
| 452 | list_unlink (item); // unlink it |
| 453 | } |
| 454 | } |
| 455 | Page[npage].slab = 0; // since the page is empty, thus slab 0 |
| 456 | list_addfirst (&Slab[0], (list_t *)page); // add the free page in slab[O] |
| 457 | Objects[0]--; // decr the number of pages used |
| 458 | } |
| 459 | } |
| 460 | }}} |
| 461 | |
| 462 | **Explication de l'usage du tableau `Page`** :\\Le tableau `Page[]` est un tableau de structures dont chaque case contient l'usage de la page : pour quel slab la page est utilisée et combien d'objets y sont alloués. Lors de la libération d'un objet du noyau par `kfree()`, l'allocateur remet l'objet dans la liste des objets libres de sa taille (le tableau de listes `Slab[]`) et il décrémente le compteur d'objets présents dans la page `--Page[npage].alloc` (`npage` identifie la page). Si la page ne contient plus d'objet alloué alors `kfree()` recherche les objets libres de même taille qui sont dans la page `npage` alors il les retire. Ensuite la page est libérée.\\Vous n'avez pas à changer ce fonctionnement, ce qu'il faut c'est ne pas l'invoquer si le nombre d'objet libre est en dessous d'un seuil. |
| 463 | |
| 464 | |