add: tiny
This commit is contained in:
parent
fe833fbfcb
commit
545c02c8f8
10
src/block.c
10
src/block.c
@ -10,7 +10,7 @@
|
|||||||
#include "chunk.h"
|
#include "chunk.h"
|
||||||
#include "chunk_manager.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;
|
static int block_id = 0;
|
||||||
void *new_block;
|
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()
|
// 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)
|
if (prev != NULL)
|
||||||
{
|
{
|
||||||
|
@ -4,5 +4,5 @@
|
|||||||
|
|
||||||
#include "chunk.h"
|
#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);
|
void destroy_block(chunk_t *chunk);
|
@ -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 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);
|
data_start = data_start + get_align_increment(data_start);
|
||||||
|
|
||||||
|
@ -21,10 +21,11 @@ enum {
|
|||||||
CHUNK_IS_USED_POS,
|
CHUNK_IS_USED_POS,
|
||||||
CHUNK_BLOCK_ID_POS,
|
CHUNK_BLOCK_ID_POS,
|
||||||
CHUNK_DATA_START_POS,
|
CHUNK_DATA_START_POS,
|
||||||
|
BOZO
|
||||||
CHUNK_SIZE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HEADER_SIZE BOZO * sizeof(void*)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TINY,
|
TINY,
|
||||||
SMALL,
|
SMALL,
|
||||||
|
@ -1,24 +1,10 @@
|
|||||||
#include "chunk.h"
|
#include "chunk.h"
|
||||||
#include "align.h"
|
#include "align.h"
|
||||||
|
#include "raw_chunk_manager.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
#include "block.h"
|
||||||
|
|
||||||
int get_unused_chunk(chunk_t *root, size_t size, chunk_t *result)
|
#include <unistd.h>
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void chunk_merge(chunk_t *first, chunk_t *second)
|
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)
|
if (first->block_id != second->block_id)
|
||||||
putstr("Attempt merge two chunk on different block\n");
|
putstr("Attempt merge two chunk on different block\n");
|
||||||
#endif
|
#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;
|
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
|
chunk_t new_chunk;
|
||||||
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_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);
|
#ifndef DEBUG
|
||||||
chunk_init(chunk, new_size, chunk->block_id, chunk->prev, chunk->current, new_chunk->current, false);
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -55,4 +47,17 @@ void chunk_iter(chunk_t *root, void (*f)(chunk_t*))
|
|||||||
break;
|
break;
|
||||||
chunk_read(current->next, current);
|
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;
|
||||||
}
|
}
|
@ -3,4 +3,6 @@
|
|||||||
#include "chunk.h"
|
#include "chunk.h"
|
||||||
|
|
||||||
void chunk_iter(chunk_t *root, void (*f)(chunk_t*));
|
void chunk_iter(chunk_t *root, void (*f)(chunk_t*));
|
||||||
void chunk_merge(chunk_t *first, chunk_t *second);
|
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);
|
47
src/malloc.c
47
src/malloc.c
@ -14,8 +14,22 @@ void* allocs_tree[3] = { 0, 0, 0};
|
|||||||
|
|
||||||
void *alloc_tiny(size_t size)
|
void *alloc_tiny(size_t size)
|
||||||
{
|
{
|
||||||
(void)size;
|
chunk_t chunk;
|
||||||
return NULL;
|
|
||||||
|
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)
|
void *alloc_small(size_t size)
|
||||||
@ -31,7 +45,7 @@ void *alloc_large(size_t size)
|
|||||||
|
|
||||||
if (first == NULL)
|
if (first == NULL)
|
||||||
{
|
{
|
||||||
if (add_new_block(&new_chunk, size, NULL, NULL, true))
|
if (add_new_block(&new_chunk, size, NULL, true))
|
||||||
return NULL;
|
return NULL;
|
||||||
allocs_tree[LARGE] = new_chunk.current;
|
allocs_tree[LARGE] = new_chunk.current;
|
||||||
return new_chunk.data_start;
|
return new_chunk.data_start;
|
||||||
@ -39,7 +53,7 @@ void *alloc_large(size_t size)
|
|||||||
|
|
||||||
void *last = raw_get_last_chunk(first);
|
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 NULL;
|
||||||
|
|
||||||
return new_chunk.data_start;
|
return new_chunk.data_start;
|
||||||
@ -56,7 +70,30 @@ void *ft_malloc(size_t size)
|
|||||||
|
|
||||||
void free_tiny(chunk_t *chunk)
|
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)
|
void free_small(chunk_t *chunk)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "chunk.h"
|
#include "chunk.h"
|
||||||
#include "./malloc.h"
|
#include "malloc.h"
|
||||||
|
#include "block.h"
|
||||||
|
|
||||||
void *raw_get_last_chunk(void **root)
|
void *raw_get_last_chunk(void **root)
|
||||||
{
|
{
|
||||||
@ -27,4 +28,34 @@ void *raw_get_chunk(void **root, void *data_start)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
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;
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void *raw_get_last_chunk(void **root);
|
void *raw_get_last_chunk(void **root);
|
||||||
void *raw_get_chunk(void **root, void *data_start);
|
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);
|
@ -4,4 +4,4 @@
|
|||||||
#define N n * 100 // TINY MUST BE STORED IN ZONES OF N bytes
|
#define N n * 100 // TINY MUST BE STORED IN ZONES OF N bytes
|
||||||
|
|
||||||
#define m 10000 // SMALL MAX SIZE
|
#define m 10000 // SMALL MAX SIZE
|
||||||
#define M m * 100 // SMALL MUST BE STORED IN ZONES OF N bytes
|
#define M m * 100 // SMALL MUST BE STORED IN ZONES OF N bytes
|
33
test/main.c
33
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)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
|
void *ptr, *ptr1, *ptr2, *ptr3;
|
||||||
(void) ac;
|
(void) ac;
|
||||||
(void) av;
|
(void) av;
|
||||||
|
|
||||||
@ -27,15 +28,15 @@ int main(int ac, char **av)
|
|||||||
test((void*) 15, (void*) get_align_increment((void*) 1), "align test 2", "");
|
test((void*) 15, (void*) get_align_increment((void*) 1), "align test 2", "");
|
||||||
|
|
||||||
printf("-----------ALLOC (LARGE)-----------\n");
|
printf("-----------ALLOC (LARGE)-----------\n");
|
||||||
void* ptr = ft_malloc(10000000);
|
ptr = ft_malloc(10000000);
|
||||||
ft_free(ptr);
|
ft_free(ptr);
|
||||||
test(NULL, allocs_tree[LARGE], "alloc free", "simple alloc, simple free");
|
test(NULL, allocs_tree[LARGE], "alloc free", "simple alloc, simple free");
|
||||||
ptr = ft_malloc(10000000);
|
ptr = ft_malloc(10000000);
|
||||||
test(ptr, ((void **) allocs_tree[LARGE])[CHUNK_DATA_START_POS], "free alloc", "alloc after a free on the first block");
|
test(ptr, ((void **) allocs_tree[LARGE])[CHUNK_DATA_START_POS], "free alloc", "alloc after a free on the first block");
|
||||||
ft_free(ptr);
|
ft_free(ptr);
|
||||||
void *ptr1 = ft_malloc(10000000);
|
ptr1 = ft_malloc(10000000);
|
||||||
void *ptr2 = ft_malloc(10000000);
|
ptr2 = ft_malloc(10000000);
|
||||||
void *ptr3 = 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], 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], ptr2) == NULL), "alloc second", "");
|
||||||
test(0, (const void*) (uintptr_t) (raw_get_chunk(allocs_tree[LARGE], ptr3) == NULL), "alloc third", "");
|
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);
|
ft_free(ptr2);
|
||||||
test(NULL, allocs_tree[LARGE], "free disorder3", "");
|
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;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user