My Project
Chargement...
Recherche...
Aucune correspondance
kmalloc-zs.c
Aller à la documentation de ce fichier.
1
9#include "manux/printk.h"
10#include <manux/debug.h> // assert
11#include <manux/memoire.h>
12#include <manux/kmalloc-zs.h>
13
18#define MANUX_KMALLOC_MAGIQUE 0x4832
19
23#define MANUX_KMALLOC_ORDRE_MIN 3
24#define MANUX_KMALLOC_ORDRE_MAX 12
25
47
52
53#ifdef MANUX_KMALLOC_STAT
54int32_t nbPagesAllouees = 0;
55uint32_t nbAlloc[MANUX_KMALLOC_ORDRE_MAX+1] = {0};
56uint32_t nbFree[MANUX_KMALLOC_ORDRE_MAX+1] = {0};
57#endif // MANUX_KMALLOC_STAT
58
60{
62 enteteBlocMemoire * bloc;
63 int nb;
64
65 printkc("Pages allouees (kmalloc) / total : %d (%d) / %d\n",
66 nombrePagesAllouees(), nbPagesAllouees, nombrePagesTotal());
67 printkc("ordre alloc free blocs\n");
69 nb=0;
70 for (bloc = blocsLibres[ordre]; bloc != NULL; bloc = bloc->e.suivant){
71 nb++;
72 }
73 printkc(" %2d %4d %4d %4d\n", ordre, nbAlloc[ordre], nbFree[ordre], nb);
74 }
75}
76
81{
82 // Pour le moment, on commence à vide !
83
84 // Attention, on ne peut rien afficher car il faut que cette
85 // fonction soit invoquée (le jour où elle fera quelque chose !)
86 // avant l'initialisation de la console, au cas où la macro
87 // MANUX_ATOMIQUE_AUDIT soit initialisée, ...
88}
89
93static inline uint16_t ordreDe(uint16_t taille)
94{
96 uint16_t tailleTotale = taille + sizeof(enteteBlocMemoire);
97
98 assert(tailleTotale <= (1<<MANUX_KMALLOC_ORDRE_MAX));
99
100 while (1<< (result - 1) >= tailleTotale) {
101 result --;
102 }
103
104 return result;
105}
106
110static
111void decouperUnBloc(uint16_t o)
112{
113 enteteBlocMemoire * origine = blocsLibres[o];
114 enteteBlocMemoire * part1, * part2;
115
116 assert(blocsLibres[o] != NULL);
117
118 // On supprime le bloc de la liste d'ordre o
119 blocsLibres[o] = origine->e.suivant;
120
121 // On descend d'un ordre
122 o--;
123
124 // Le suivant est à une distance d'un ordre inférieur
125 part1 = origine;
126 part2 = (enteteBlocMemoire *)((void *)origine + (1<<o));
127
128 // On les insère en tête de liste
129 part1->e.suivant = part2;
130 part2->e.suivant = blocsLibres[o];
131 blocsLibres[o] = part1;
132
133}
134
139void * kmalloc(size_t n)
140{
141 enteteBlocMemoire * enteteBlocAlloue = NULL;
142 uint16_t ordre; //< Log2 de la taille totale
143 uint16_t o; //< indice de recherche de blocs
144
145 ordre = ordreDe(n);
148 };
149
152
153 // On recherche un bloc assez gros pour la demande
154 o = ordre;
155 while (( o <= MANUX_KMALLOC_ORDRE_MAX) && (blocsLibres[o] == NULL)) {
156 o++;
157 }
158
161
162 // Si on a dépasser la taille max, c'est qu'on a rien trouvé. On
163 // alloue alors un bloc de taille maximale.
164 if (o > MANUX_KMALLOC_ORDRE_MAX) {
165 // WARNING traiter cas où MANUX_KMALLOC_ORDRE_MAX est plus gros qu'une page ...
168 return NULL;
169 } else {
170#ifdef MANUX_KMALLOC_STAT
171 nbPagesAllouees++;
172#endif
175 }
176 }
177
178 // S'il est trop gros on le coupe en deux jusqu'à la bonne taille
179 while (o > ordre) {
180 decouperUnBloc(o);
181 o--;
182 }
183
184 // On y est, par construction il y a un bloc de la bonne taille
185 // on l'alloue
186 enteteBlocAlloue = blocsLibres[o];
187 blocsLibres[o] = enteteBlocAlloue->e.suivant;
188 enteteBlocAlloue->e.alloue.magique = MANUX_KMALLOC_MAGIQUE;
189 enteteBlocAlloue->e.alloue.ordre = ordre;
190
191 if (enteteBlocAlloue == NULL) {
192 return NULL;
193 } else {
194#ifdef MANUX_KMALLOC_STAT
195 nbAlloc[ordre]++;
196#endif
197
198 return enteteBlocAlloue + 1;
199 }
200}
201
210static
211void reintegrerBloc(enteteBlocMemoire * bloc)
212{
213 uint16_t ordre = bloc->e.alloue.ordre; //< Ordre du bloc à intégrer
214 enteteBlocMemoire * siamois, *prec = NULL;
215
216 do {
219
220 // On cherche le siamois, dont l'adresse ne diffère que par le
221 // bit de l'ordre
222 prec = NULL;
223 siamois = blocsLibres[ordre];
224 while ((siamois != NULL) && (((uint32_t)siamois ^ (1<<ordre)) != (uint32_t)bloc)) {
225 prec = siamois;
226 siamois = siamois->e.suivant;
227 }
228
229 // Si le siamois était dans les libres, on l'enlève et on procède
230 // à la fusion
231 if (siamois != NULL) {
232 // On extrait le siamois
233 if (prec == NULL){ // Si c'était le premier
234 blocsLibres[ordre] = siamois->e.suivant;
235 } else { // Sinon
236 prec->e.suivant = siamois->e.suivant;
237 }
238
239 // On recrée le bloc constitué de la fusion. L'adresse est celle
240 // des deux avec le bit d'ordre ordre à zéro
241 bloc = (enteteBlocMemoire *)(((uint32_t)bloc)&(~(1 << ordre)));
242
243 // On remonte donc d'un ordre
244 ordre++;
245 }
246 } while ((siamois != NULL) // Si la fusion a pu être faite, on
247 &&(ordre < MANUX_KMALLOC_ORDRE_MAX)); // essaye de fusionner un ordre au dessus
248
249 // A ce stade, on a effectué toutes les fusions possibles
250 // concernant ce bloc. L'état final du bloc intègre ces
251 // éventuellles fusions et l'ordre a donc été incrémenté à chaque
252 // fusion. Il ne nous reste donc plus qu'à intègrer le bloc final
253 // dans les libres
254 bloc->e.suivant = blocsLibres[ordre];
255 blocsLibres[ordre] = bloc;
256
257}
258
265void kfree(void * p)
266{
268
269 bloc--;
270
271 if (bloc->e.alloue.magique != MANUX_KMALLOC_MAGIQUE) {
272 paniqueNoyau("Tentative de libérer un bloc 0x%x inconnu (m=0x%x, o=%d)\n",
273 p, bloc->e.alloue.magique, bloc->e.alloue.ordre);
274 }
275
276#ifdef MANUX_KMALLOC_STAT
277 nbFree[bloc->e.alloue.ordre]++;
278#endif
279
281 reintegrerBloc(bloc);
282 }
283}
284
int nombrePagesAllouees(void)
Definition memoire.c:257
int nombrePagesTotal(void)
Definition memoire.c:262
void * allouerPage(void)
Definition memoire.c:234
Définition des fonctions de base d'entrée-sortie du noyau.
#define printkc
Une version de printk qui écrit dans la console de la tâche en cours.
Definition printk.h:61
#define NULL
Definition stddef.h:10
unsigned long uint32_t
Definition types.h:20
unsigned short uint16_t
Definition types.h:16
unsigned long int32_t
Definition types.h:24
#define MANUX_KMALLOC_MAGIQUE
Un nombre qui nous permettra d'avoir un peu plus confiance dans les blocs mémoire rendus par l'utilis...
Definition kmalloc-zs.c:18
void kmallocAfficherStatistiques(void)
Definition kmalloc-zs.c:59
#define MANUX_KMALLOC_ORDRE_MAX
Definition kmalloc-zs.c:24
enteteBlocMemoire * blocsLibres[MANUX_KMALLOC_ORDRE_MAX+1]
Listes d'entêtes de blos libres.
Definition kmalloc-zs.c:51
void kmallocInitialisation(void)
Initialisation du sytème kmalloc.
Definition kmalloc-zs.c:80
struct _enteteBlocMemoire enteteBlocMemoire
Description d'un bloc mémoire fourni à l'utilisateur En fait, on ne lui fourni que le pointeur vers l...
#define MANUX_KMALLOC_ORDRE_MIN
Log2 de la taille max allouée.
Definition kmalloc-zs.c:23
void * kmalloc(size_t n)
Allocation d'une zone de n octets.
Definition kmalloc-zs.c:139
void kfree(void *p)
Libération d'une zone mémoire allouée Si le bloc avait été légitiment alloué, il est réintégré dans l...
Definition kmalloc-zs.c:265
Une implatation simple de kmalloc fondé sur les zones siamoises (buddy areas) (C) Emmanuel Chaput 202...
#define assert(cond)
Definition debug.h:126
#define paniqueNoyau(fmt, args...)
Definition debug.h:107
Description d'un bloc mémoire fourni à l'utilisateur En fait, on ne lui fourni que le pointeur vers l...
Definition kmalloc-zs.c:38
union _enteteBlocMemoire::@2 e
struct _enteteBlocMemoire * suivant
Definition kmalloc-zs.c:44
struct _enteteBlocMemoire::@2::@3 alloue