diff --git a/dm_alloc/allocateur_blocs_taille_fixe.c b/dm_alloc/allocateur_blocs_taille_fixe.c new file mode 100644 index 0000000..9d13d45 --- /dev/null +++ b/dm_alloc/allocateur_blocs_taille_fixe.c @@ -0,0 +1,159 @@ +// #include +// #include +// #include + +// const uint64_t HEAP_SIZE = 32; +// const uint64_t BLOCK_SIZE = 8; +// uint64_t heap[HEAP_SIZE]; + +// void init_heap() { +// heap[0] = 2; +// for (uint64_t i = 1; i + BLOCK_SIZE <= HEAP_SIZE; i += BLOCK_SIZE) { +// heap[i] = 0; +// } +// } + +// bool is_free(uint64_t i) { return !heap[i - 1]; } +// void set_free(uint64_t i) { heap[i - 1] = 0; } +// void set_used(uint64_t i) { heap[i - 1] = 1; } + +// uint64_t *malloc_ui(uint64_t size) { +// for (uint64_t i = 2; i - 1 + BLOCK_SIZE <= HEAP_SIZE; i += BLOCK_SIZE) { +// if (is_free(i)) { +// set_used(i); +// if (i > heap[0]) { +// heap[0] = i; +// } +// return &heap[i]; +// } +// } +// return NULL; +// } + +// void free_ui(uint64_t *p) { +// uint64_t i = p - heap; +// heap[i - 1] = 0; +// if (i == heap[0]) { +// while (is_free(heap[0]) && heap[0] > 2) { +// heap[0] -= BLOCK_SIZE; +// } +// } +// } + +#include +#include +#include +#include +#include + +// Comme uint64_t est un peu pénible à taper, on utilise +// un typedef : +typedef uint64_t ui; + +#define HEAP_SIZE 32 + +ui heap[HEAP_SIZE]; + +// Cette fonction convertit un pointeur (qui doit être issu de +// malloc_ui) en un indice dans le tableau heap. +// Vous en aurez besoin pour écrire les différentes versions +// de free_ui (juste un appel au début, ensuite on ne manipule plus +// que des indices), mais il est complètement normal de ne pas +// comprendre comment elle fonctionne : c'est de l'arithmétique des +// pointeurs, qui est hors programme. +ui heap_index(ui *p) { return p - heap; } + +// Cette fonction initialise le tas à une valeur particulière, que +// vous avez peu de chance d'utiliser par hasard. Cela nous +// permettra en pratique de repérer les cases dont la valeur n'a +// jamais été modifiée quand on affiche le contenu du tas. +// Elle est destinée à être appelée une unique fois, tout au début +// de l'exécution du programme. +void pre_initialize_heap(void) { + for (ui i = 0; i < HEAP_SIZE; i++) { + heap[i] = 0xFFFFFFFF; + } +} + +// La fonction suivante affiche le contenu du tas. Les cases +// identifiées comme n'ayant jamais été modifiées sont affichées +// de manière particulière. +void print_heap(void) { + for (ui i = 0; i < HEAP_SIZE; i++) { + ui x = heap[i]; + if (x == 0xFFFFFFFF) { + printf("... "); + } else { + printf("%3" PRIu64 " ", x); + } + } + printf("\n"); +} + +void set_memory(ui *p, ui size, ui value) { + for (ui i = 0; i < size; i++) { + p[i] = value; + } +} + +const ui block_size = 8; + +void init_heap(void) { + heap[0] = 2; + for (ui i = 1; i + block_size <= HEAP_SIZE; i += block_size) { + heap[i] = 0; + } +} + +bool is_free(uint64_t i) { return !heap[i - 1]; } + +void set_free(uint64_t i) { heap[i - 1] = 0; } + +void set_used(uint64_t i) { heap[i - 1] = 1; } + +uint64_t *malloc_ui64(uint64_t size) { + for (ui i = 2; i - 1 + block_size <= HEAP_SIZE; i += block_size) { + if (is_free(i)) { + set_used(i); + if (i >= heap[0]) { + heap[0] = i + block_size; + } + return &heap[i]; + } + } + return NULL; +} + +void free_ui64(uint64_t *p) { + // Indice du bloc à libérer + uint64_t i = heap_index(p); + heap[i - 1] = 0; + if (i + block_size == heap[0]) { + while (heap[0] > 2 && is_free(heap[0] - block_size)) { + heap[0] -= block_size; + } + } +} + +int main(void) { + pre_initialize_heap(); + + // Pour tester, une fois que les fonctions sont implémentées + init_heap(); + uint64_t *p1 = malloc_ui64(6); + uint64_t *p2 = malloc_ui64(3); + set_memory(p1, 6, 42); + set_memory(p2, 3, 52); + print_heap(); + uint64_t *p3 = malloc_ui64(5); + set_memory(p3, 5, 62); + print_heap(); + free_ui64(p2); + print_heap(); + free_ui64(p3); + print_heap(); + free_ui64(p1); + print_heap(); + + return EXIT_SUCCESS; +} diff --git a/dm_alloc/allocateur_lineaire.c b/dm_alloc/allocateur_lineaire.c new file mode 100644 index 0000000..edb5b8d --- /dev/null +++ b/dm_alloc/allocateur_lineaire.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include + +// Comme uint64_t est un peu pénible à taper, on utilise +// un typedef : +typedef uint64_t ui; + +#define HEAP_SIZE 32 + +ui heap[HEAP_SIZE]; + +// Cette fonction initialise le tas à une valeur particulière, que +// vous avez peu de chance d'utiliser par hasard. Cela nous +// permettra en pratique de repérer les cases dont la valeur n'a +// jamais été modifiée quand on affiche le contenu du tas. +// Elle est destinée à être appelée une unique fois, tout au début +// de l'exécution du programme. +void pre_initialize_heap(void) { + for (ui i = 0; i < HEAP_SIZE; i++) { + heap[i] = 0xFFFFFFFF; + } +} + +// La fonction suivante affiche le contenu du tas. Les cases +// identifiées comme n'ayant jamais été modifiées sont affichées +// de manière particulière. +void print_heap(void) { + for (ui i = 0; i < HEAP_SIZE; i++) { + ui x = heap[i]; + if (x == 0xFFFFFFFF) { + printf("... "); + } else { + printf("%3" PRIu64 " ", x); + } + } + printf("\n"); +} + +void set_memory(ui *p, ui size, ui value) { + for (ui i = 0; i < size; i++) { + p[i] = value; + } +} + +void free_ui64(uint64_t *p) {} + +void init_heap() { heap[0] = 1; } + +uint64_t *malloc_ui64(uint64_t size) { + if (heap[0] + size > HEAP_SIZE) { + return NULL; + } else { + heap[0] += size; + return &heap[heap[0] - size]; + } +} + +int main(void) { + + pre_initialize_heap(); + + // Pour tester, une fois que les fonctions sont implémentées + init_heap(); + uint64_t *p1 = malloc_ui64(6); + uint64_t *p2 = malloc_ui64(5); + set_memory(p1, 6, 42); + set_memory(p2, 5, 52); + free_ui64(p2); + free_ui64(p1); + + print_heap(); + return EXIT_SUCCESS; +}