diff --git a/src/block.c b/src/block.c index 8d922ff..b8d76c7 100644 --- a/src/block.c +++ b/src/block.c @@ -10,7 +10,7 @@ #include "chunk.h" #include "chunk_manager.h" -int add_new_block(chunk_t* chunk, size_t size, void *prev, void *next, bool is_used) +int add_new_block(chunk_t* chunk, size_t size, void *prev, bool is_used) { static int block_id = 0; void *new_block; @@ -18,9 +18,13 @@ int add_new_block(chunk_t* chunk, size_t size, void *prev, void *next, bool is_u // TODO check with getrlimit() - new_block = mmap(NULL, size + ALIGN_MARGING + CHUNK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + new_block = mmap(NULL, size + ALIGN_MARGING + HEADER_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#ifndef DEBUG + if (new_block == NULL) + write(2, "mmap failed\n", 12); +#endif - chunk_init(chunk, size + ALIGN_MARGING - get_align_increment(new_block + CHUNK_SIZE), block_id, prev, new_block, next, is_used); + chunk_init(chunk, size + ALIGN_MARGING - get_align_increment(new_block + HEADER_SIZE), block_id, prev, new_block, NULL, is_used); if (prev != NULL) { diff --git a/src/block.h b/src/block.h index 8dcf9c5..cbf18a7 100644 --- a/src/block.h +++ b/src/block.h @@ -4,5 +4,5 @@ #include "chunk.h" -int add_new_block(chunk_t* chunk, size_t size, void *prev, void *next, bool is_used); +int add_new_block(chunk_t* chunk, size_t size, void *prev, bool is_used); void destroy_block(chunk_t *chunk); \ No newline at end of file diff --git a/src/chunk.c b/src/chunk.c index cb586e9..6b8e96f 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -32,7 +32,7 @@ void chunk_read(void * const *block, chunk_t *chunk) void chunk_init(chunk_t *chunk, size_t size, long block_id, void *prev, void *current, void *next, bool is_used) { - void *data_start = current + CHUNK_SIZE; + void *data_start = current + HEADER_SIZE; data_start = data_start + get_align_increment(data_start); diff --git a/src/chunk.h b/src/chunk.h index 6ab803e..d3cefd8 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -21,10 +21,11 @@ enum { CHUNK_IS_USED_POS, CHUNK_BLOCK_ID_POS, CHUNK_DATA_START_POS, - - CHUNK_SIZE + BOZO }; +#define HEADER_SIZE BOZO * sizeof(void*) + enum { TINY, SMALL, diff --git a/src/chunk_manager.c b/src/chunk_manager.c index 9696528..dbb8769 100644 --- a/src/chunk_manager.c +++ b/src/chunk_manager.c @@ -1,24 +1,10 @@ #include "chunk.h" #include "align.h" +#include "raw_chunk_manager.h" #include "print.h" +#include "block.h" -int get_unused_chunk(chunk_t *root, size_t size, chunk_t *result) -{ - void** current = root->current; - - while (current != NULL) - { - if ((bool) current[CHUNK_IS_USED_POS] == true) - continue; - if ((size_t) current[CHUNK_SIZE_POS] >= size) - { - chunk_read(current, result); - return 0; - } - current = current[CHUNK_NEXT_POS]; - } - return 1; -} +#include void chunk_merge(chunk_t *first, chunk_t *second) { @@ -26,20 +12,26 @@ void chunk_merge(chunk_t *first, chunk_t *second) if (first->block_id != second->block_id) putstr("Attempt merge two chunk on different block\n"); #endif - first->size = first->size + second->size + CHUNK_SIZE + ALIGN_MARGING - get_align_increment(first->next); + first->size = second->data_start - first->data_start + second->size; first->next = second->next; + + chunk_write(first); } -int chunk_split(chunk_t *chunk, chunk_t *new_chunk, size_t new_size) +int chunk_split(chunk_t *chunk, size_t new_size) { - // NOT ENOUGH SIZE TO BE SPLITTED - if (chunk->size + 1 < new_size + CHUNK_SIZE + get_align_increment(chunk->current + CHUNK_SIZE)) - return 1; - - void *new_chunk_pos = chunk->data_start + new_size; + chunk_t new_chunk; - chunk_init(new_chunk, chunk->size - new_size - CHUNK_SIZE - get_align_increment(new_chunk_pos + CHUNK_SIZE), chunk->block_id, chunk->current, new_chunk_pos, chunk->next, true); - chunk_init(chunk, new_size, chunk->block_id, chunk->prev, chunk->current, new_chunk->current, false); +#ifndef DEBUG + // NOT ENOUGH SIZE TO BE SPLITTED + if (chunk->size + 1 < new_size + HEADER_SIZE + get_align_increment(chunk->current + HEADER_SIZE)) + write(2, "chunk too small to be splitted\n", 31); +#endif + + void* new_chunk_pos = chunk->data_start + new_size; + + chunk_init(&new_chunk, chunk->size - new_size - HEADER_SIZE - get_align_increment(new_chunk_pos + HEADER_SIZE), chunk->block_id, chunk->current, new_chunk_pos, chunk->next, false); + chunk_init(chunk, new_size, chunk->block_id, chunk->prev, chunk->current, new_chunk.current, true); return 0; } @@ -55,4 +47,17 @@ void chunk_iter(chunk_t *root, void (*f)(chunk_t*)) break; chunk_read(current->next, current); } +} + +int get_append_unused_chunk(void *root, size_t size, chunk_t *result, size_t new_block_size) +{ + if (get_unused_chunk_raw(root, size, result)) + { + if (add_new_block(result, new_block_size, raw_get_last_chunk(root), false)) + return 1; + if (result->size + 1 < size + HEADER_SIZE + get_align_increment(result->current + HEADER_SIZE)) + return 0; + chunk_split(result, size); + } + return 0; } \ No newline at end of file diff --git a/src/chunk_manager.h b/src/chunk_manager.h index 2df733a..926dbc9 100644 --- a/src/chunk_manager.h +++ b/src/chunk_manager.h @@ -3,4 +3,6 @@ #include "chunk.h" void chunk_iter(chunk_t *root, void (*f)(chunk_t*)); -void chunk_merge(chunk_t *first, chunk_t *second); \ No newline at end of file +void chunk_merge(chunk_t *first, chunk_t *second); +int get_append_unused_chunk(void *root, size_t size, chunk_t *result, size_t new_block_size); +int chunk_split(chunk_t *chunk, size_t new_size); \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index 694af3c..1ac5bcf 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -14,8 +14,22 @@ void* allocs_tree[3] = { 0, 0, 0}; void *alloc_tiny(size_t size) { - (void)size; - return NULL; + chunk_t chunk; + + if (allocs_tree[TINY] == NULL) + { + if (add_new_block(&chunk, N, NULL, false)) + return NULL; + allocs_tree[TINY] = chunk.current; + } + else + { + if (get_append_unused_chunk(allocs_tree[TINY], size, &chunk, N)) + return NULL; + } + if (chunk_split(&chunk, size)) + return NULL; + return chunk.data_start; } void *alloc_small(size_t size) @@ -31,7 +45,7 @@ void *alloc_large(size_t size) if (first == NULL) { - if (add_new_block(&new_chunk, size, NULL, NULL, true)) + if (add_new_block(&new_chunk, size, NULL, true)) return NULL; allocs_tree[LARGE] = new_chunk.current; return new_chunk.data_start; @@ -39,7 +53,7 @@ void *alloc_large(size_t size) void *last = raw_get_last_chunk(first); - if (add_new_block(&new_chunk, size, last, NULL, true)) + if (add_new_block(&new_chunk, size, last, true)) return NULL; return new_chunk.data_start; @@ -56,7 +70,30 @@ void *ft_malloc(size_t size) void free_tiny(chunk_t *chunk) { - (void) chunk; + chunk_t chunk_prev, chunk_next, *first_chunk = chunk, *last_chunk = chunk; + + if (chunk->prev) + { + chunk_read(chunk->prev, &chunk_prev); + if (chunk_prev.is_used == false && chunk_prev.block_id == chunk->block_id) + first_chunk = &chunk_prev; + } + if (chunk->next) + { + chunk_read(chunk->next, &chunk_next); + if (chunk_next.is_used == false && chunk_next.block_id == chunk->block_id) + last_chunk = &chunk_next; + } + + first_chunk->is_used = false; + chunk_merge(first_chunk, last_chunk); + + if (is_alone_on_block(first_chunk)) + { + if (first_chunk->current == allocs_tree[TINY]) + allocs_tree[TINY] = last_chunk->next; + destroy_block(first_chunk); + } } void free_small(chunk_t *chunk) diff --git a/src/raw_chunk_manager.c b/src/raw_chunk_manager.c index 0a8f8b7..6d2cbd1 100644 --- a/src/raw_chunk_manager.c +++ b/src/raw_chunk_manager.c @@ -1,5 +1,6 @@ #include "chunk.h" -#include "./malloc.h" +#include "malloc.h" +#include "block.h" void *raw_get_last_chunk(void **root) { @@ -27,4 +28,34 @@ void *raw_get_chunk(void **root, void *data_start) } return NULL; +} + +int get_unused_chunk_raw(void *root, size_t size, chunk_t *result) +{ + void** current = root; + + while (current != NULL) + { + if ((bool) current[CHUNK_IS_USED_POS] == false) + { + if ((size_t) current[CHUNK_SIZE_POS] >= size) + { + chunk_read(current, result); + return 0; + } + } + current = current[CHUNK_NEXT_POS]; + } + return 1; +} + +int is_alone_on_block(const chunk_t *chunk) +{ + if (chunk->prev) + if (((long) ((void **) chunk->prev)[CHUNK_BLOCK_ID_POS]) == chunk->block_id) + return 0; + if (chunk->next) + if (((long) ((void **) chunk->next)[CHUNK_BLOCK_ID_POS]) == chunk->block_id) + return 0; + return 1; } \ No newline at end of file diff --git a/src/raw_chunk_manager.h b/src/raw_chunk_manager.h index fe46795..b6c96aa 100644 --- a/src/raw_chunk_manager.h +++ b/src/raw_chunk_manager.h @@ -1,4 +1,6 @@ #pragma once void *raw_get_last_chunk(void **root); -void *raw_get_chunk(void **root, void *data_start); \ No newline at end of file +void *raw_get_chunk(void **root, void *data_start); +int get_unused_chunk_raw(void *root, size_t size, chunk_t *result); +int is_alone_on_block(const chunk_t *chunk); \ No newline at end of file diff --git a/src/size.h b/src/size.h index f1da247..14c2411 100644 --- a/src/size.h +++ b/src/size.h @@ -4,4 +4,4 @@ #define N n * 100 // TINY MUST BE STORED IN ZONES OF N bytes #define m 10000 // SMALL MAX SIZE -#define M m * 100 // SMALL MUST BE STORED IN ZONES OF N bytes \ No newline at end of file +#define M m * 100 // SMALL MUST BE STORED IN ZONES OF N bytes \ No newline at end of file diff --git a/test/main.c b/test/main.c index 2eee572..ad039de 100644 --- a/test/main.c +++ b/test/main.c @@ -19,6 +19,7 @@ void test(const void* expected_value, const void* value, const char* test_name, int main(int ac, char **av) { + void *ptr, *ptr1, *ptr2, *ptr3; (void) ac; (void) av; @@ -27,15 +28,15 @@ int main(int ac, char **av) test((void*) 15, (void*) get_align_increment((void*) 1), "align test 2", ""); printf("-----------ALLOC (LARGE)-----------\n"); - void* ptr = ft_malloc(10000000); + ptr = ft_malloc(10000000); ft_free(ptr); test(NULL, allocs_tree[LARGE], "alloc free", "simple alloc, simple free"); ptr = ft_malloc(10000000); test(ptr, ((void **) allocs_tree[LARGE])[CHUNK_DATA_START_POS], "free alloc", "alloc after a free on the first block"); ft_free(ptr); - void *ptr1 = ft_malloc(10000000); - void *ptr2 = ft_malloc(10000000); - void *ptr3 = ft_malloc(10000000); + ptr1 = ft_malloc(10000000); + ptr2 = ft_malloc(10000000); + ptr3 = ft_malloc(10000000); test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[LARGE], ptr1) == NULL), "alloc first", ""); test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[LARGE], ptr2) == NULL), "alloc second", ""); test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[LARGE], ptr3) == NULL), "alloc third", ""); @@ -46,5 +47,29 @@ int main(int ac, char **av) ft_free(ptr2); test(NULL, allocs_tree[LARGE], "free disorder3", ""); + printf("-----------ALLOC (TINY)-----------\n"); + ptr = ft_malloc(4); + ft_free(ptr); + test(NULL, allocs_tree[TINY], "alloc free", "simple alloc, simple free"); + ptr = ft_malloc(4); + test(ptr, ((void **) allocs_tree[TINY])[CHUNK_DATA_START_POS], "free alloc", "alloc after a free on the first block"); + ft_free(ptr); + ptr1 = ft_malloc(4); + ptr2 = ft_malloc(4); + ptr3 = ft_malloc(4); + test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[TINY], ptr1) == NULL), "alloc first", ""); + test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[TINY], ptr2) == NULL), "alloc second", ""); + test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[TINY], ptr3) == NULL), "alloc third", ""); + show_alloc_mem(); + ft_free(ptr1); + test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[TINY], ptr2) == NULL), "free disorder1", ""); + ft_free(ptr3); + test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[TINY], ptr2) == NULL), "free disorder2", ""); + show_alloc_mem(); + ft_free(ptr2); + show_alloc_mem(); + test(NULL, allocs_tree[TINY], "free disorder3", ""); + + return 0; } \ No newline at end of file