From 912064ae31d14a3eec9c5ac7a11eec69110b342a Mon Sep 17 00:00:00 2001 From: gbrochar Date: Fri, 11 Jul 2025 14:21:25 +0200 Subject: [PATCH] feat: malloc multi zones and large blocks --- inc/malloc.h | 2 + main.c | 19 +++-- src/init.c | 7 +- src/malloc.c | 191 +++++++++++++++++++++++++++++++++++++-------------- test.sh | 2 +- 5 files changed, 157 insertions(+), 64 deletions(-) diff --git a/inc/malloc.h b/inc/malloc.h index 845ca9a..f74afbd 100644 --- a/inc/malloc.h +++ b/inc/malloc.h @@ -29,7 +29,9 @@ typedef struct s_zones { size_t pagesize; size_t max_align; size_t tiny_block_max_size; + size_t tiny_zone_size; size_t small_block_max_size; + size_t small_zone_size; t_zone *tiny_zones; t_zone *small_zones; t_block *large_blocks; diff --git a/main.c b/main.c index a70f1b3..494d941 100644 --- a/main.c +++ b/main.c @@ -1,16 +1,15 @@ #include #include "inc/malloc.h" -int main(void) { - int *arr = ft_malloc(42); - printf ("addr of arr is : %p\n", arr); - arr = realloc(arr, 42); - int *arr2 = ft_malloc(124); - int *arr3 = ft_malloc(1540); - printf ("addr of arr is : %p\n", arr); - printf ("addr of arr2 is : %p\n", arr2); - printf ("addr of arr3 is : %p\n", arr3); - free(arr); +int main(int argc, char **argv) { + srand(argv[1][0]+argv[1][1]+argv[1][2]); + int *arr; + size_t size; + for (int i = 0; i < atoi(argv[2]); i++) { + size = (rand() & 0x7ff) | 0xf00000; + arr = (int *)ft_malloc(size * sizeof(int)); + printf ("arr %d addr: %p arr size: %zu\n", i, arr, size); + } show_alloc_sizes(); return 0; } diff --git a/src/init.c b/src/init.c index cb78851..a02e130 100644 --- a/src/init.c +++ b/src/init.c @@ -5,16 +5,18 @@ t_zones g_zones; void init_tiny_zones(void) { g_zones.tiny_block_max_size = g_zones.pagesize / 2; + g_zones.tiny_zone_size = g_zones.tiny_block_max_size * 128; // TODO protect mmap - g_zones.tiny_zones = (t_zone *)mmap(NULL, g_zones.tiny_block_max_size * 128, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + g_zones.tiny_zones = (t_zone *)mmap(NULL, g_zones.tiny_zone_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); g_zones.tiny_zones->head = NULL; g_zones.tiny_zones->next = NULL; } void init_small_zones(void) { g_zones.small_block_max_size = g_zones.tiny_block_max_size * 128; + g_zones.small_zone_size = g_zones.small_block_max_size * 128; // TODO protect mmap - g_zones.small_zones = (t_zone *)mmap(NULL, g_zones.small_block_max_size * 128, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + g_zones.small_zones = (t_zone *)mmap(NULL, g_zones.small_zone_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); g_zones.small_zones->head = NULL; g_zones.small_zones->next = NULL; } @@ -25,5 +27,6 @@ static void init_malloc(void) { g_zones.max_align = MAX_ALIGNMENT; init_tiny_zones(); init_small_zones(); + g_zones.large_blocks = NULL; } diff --git a/src/malloc.c b/src/malloc.c index 7c8dfca..eb24946 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -1,78 +1,167 @@ #include "malloc.h" +t_zone *create_new_tiny_zone(void) { + t_zone *zone; + // TODO protect mmap + zone = (t_zone *)mmap(NULL, g_zones.tiny_zone_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + zone->head = NULL; + zone->next = NULL; + return zone; +} + void *malloc_tiny(size_t size) { - // TODO check if zone still has size and expand zone if needed - t_block **head = &(g_zones.tiny_zones->head); - if (*head == NULL) { - // TODO size_t should be replaced by char * for pointer arithmetic - size_t addr = ((size_t)g_zones.tiny_zones + sizeof(t_zone)); - printf("addr %zu\n", addr); - if ((addr + sizeof(t_block)) % 16 != 0) { - addr += 16 - ((addr + sizeof(t_block)) % 16); + t_zone *zone = g_zones.tiny_zones; + + while (1) { + t_block *curr = zone->head; + if (curr == NULL) { + // TODO size_t should be replaced by char * for pointer arithmetic + size_t addr = ((size_t)zone + sizeof(t_zone)); + if ((addr + sizeof(t_block)) % 16 != 0) { + addr += 16 - ((addr + sizeof(t_block)) % 16); + } + zone->head = (t_block *)addr; + curr = zone->head; + printf("addr of g_zones.tiny_zones : %p\n" + "addr of zone : %p\n" + "addr of *head %p\n" + "sizeof tzone : %zu\n" + "size of tblock %zu\n", + g_zones.tiny_zones, + zone, + curr, + sizeof(t_zone), + sizeof(t_block)); + curr->size = size; + curr->free = 0; + curr->next = NULL; + return (void *)((char *)(curr) + sizeof(t_block)); + } + else { + while (curr->next) { + // todo check if free and defrag + curr = curr->next; + } + // TODO size_t should be replaced by char * for pointer arithmetic + size_t addr = (size_t)curr + sizeof(t_block) + curr->size; + if ((addr + sizeof(t_block)) % 16 != 0) { + addr += 16 - ((addr + sizeof(t_block)) % 16); + } + if (((size_t)zone + g_zones.tiny_zone_size) - addr >= size + sizeof(t_block) + (16 - sizeof(t_block) % 16)) + { + curr->next = (t_block *)addr; + curr = curr->next; + curr->size = size; + curr->free = 0; + curr->next = NULL; + return (void *)((char *)curr + sizeof(t_block)); + } + if (zone->next == NULL) { + zone->next = create_new_tiny_zone(); + } + zone = zone->next; } - printf("addr %zu\n", addr); - *head = (t_block *)addr; - printf("addr of g_zones.tiny_zones : %p\n \ - addr of *head %p\n \ - sizeof tzone : %zu\n \ - size of tblock %zu\n", - g_zones.tiny_zones, - *head, - sizeof(t_zone), - sizeof(t_block)); - (*head)->size = size; - (*head)->free = 0; - (*head)->next = NULL; - return (void *)((char *)(*head) + sizeof(t_block)); } - else { - t_block *curr = *head; - while (curr->next) { - // todo check if free and defrag - curr = curr->next; + return NULL; +} + +t_zone *create_new_small_zone(void) { + t_zone *zone; + // TODO protect mmap + zone = (t_zone *)mmap(NULL, g_zones.small_zone_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + zone->head = NULL; + zone->next = NULL; + return zone; +} + +void *malloc_small(size_t size) { + t_zone *zone = g_zones.small_zones; + + while (1) { + t_block *curr = zone->head; + if (curr == NULL) { + // TODO size_t should be replaced by char * for pointer arithmetic + size_t addr = ((size_t)zone + sizeof(t_zone)); + if ((addr + sizeof(t_block)) % 16 != 0) { + addr += 16 - ((addr + sizeof(t_block)) % 16); + } + zone->head = (t_block *)addr; + curr = zone->head; + printf("addr of g_zones.small_zones : %p\n" + "addr of zone : %p\n" + "addr of *head %p\n" + "sizeof tzone : %zu\n" + "size of tblock %zu\n", + g_zones.small_zones, + zone, + curr, + sizeof(t_zone), + sizeof(t_block)); + curr->size = size; + curr->free = 0; + curr->next = NULL; + return (void *)((char *)(curr) + sizeof(t_block)); } - printf("addr of curr %p\n \ - curr->size %zu\n", curr, curr->size); - // TODO size_t should be replaced by char * for pointer arithmetic - size_t addr = (size_t)curr + sizeof(t_block) + curr->size; - printf("addr %zu\n", addr); - if ((addr + sizeof(t_block)) % 16 != 0) { - addr += 16 - ((addr + sizeof(t_block)) % 16); + else { + while (curr->next) { + // todo check if free and defrag + curr = curr->next; + } + // TODO size_t should be replaced by char * for pointer arithmetic + size_t addr = (size_t)curr + sizeof(t_block) + curr->size; + if ((addr + sizeof(t_block)) % 16 != 0) { + addr += 16 - ((addr + sizeof(t_block)) % 16); + } + if (((size_t)zone + g_zones.small_zone_size) - addr >= size + sizeof(t_block) + (16 - sizeof(t_block) % 16)) + { + curr->next = (t_block *)addr; + curr = curr->next; + curr->size = size; + curr->free = 0; + curr->next = NULL; + return (void *)((char *)curr + sizeof(t_block)); + } + if (zone->next == NULL) { + zone->next = create_new_small_zone(); + } + zone = zone->next; } - printf("addr %zu\n", addr); - curr->next = (t_block *)addr; - curr = curr->next; - printf("addr of curr %p\n", curr); + } + return NULL; +} + +void *malloc_large(size_t size) { + t_block *curr = g_zones.large_blocks; + if (curr == NULL) { + // TODO protect mmap + curr = (t_block *)((char *)mmap(NULL, size + sizeof(t_block) + (16 - sizeof(t_block) % 16), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) + (16 - sizeof(t_block) % 16)); curr->size = size; curr->free = 0; curr->next = NULL; return (void *)((char *)curr + sizeof(t_block)); } - return NULL; -} - -void *malloc_small(size_t size) { - (void)size; - return NULL; -} - -void *malloc_large(size_t size) { - (void)size; - return NULL; + while (curr->next) { + curr = curr->next; + } + // TODO protect mmap + curr->next = (t_block *)((char *)mmap(NULL, size + sizeof(t_block) + (16 - sizeof(t_block) % 16), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) + (16 - sizeof(t_block) % 16)); + curr = curr->next; + curr->size = size; + curr->free = 0; + curr->next = NULL; + return (void *)((char *)curr + sizeof(t_block)); } void *ft_malloc(size_t size) { pthread_mutex_lock(&g_malloc_mutex); void *ptr = NULL; if (size < g_zones.tiny_block_max_size) { - printf("entering malloc_tiny\n"); ptr = malloc_tiny(size); } else if (size < g_zones.small_block_max_size) { ptr = malloc_small(size); } else { ptr = malloc_large(size); } - write(1, "42 from malloc\n", 15); pthread_mutex_unlock(&g_malloc_mutex); return ptr; } diff --git a/test.sh b/test.sh index d8e2d31..b3d20fa 100755 --- a/test.sh +++ b/test.sh @@ -1,4 +1,4 @@ #!/bin/sh make gcc main.c libft_malloc.so -o malloc_test.out -LD_LIBRARY_PATH=. LD_PRELOAD=./libft_malloc.so ./malloc_test.out +LD_LIBRARY_PATH=. LD_PRELOAD=./libft_malloc.so ./malloc_test.out $1 $2