init: large bugged

This commit is contained in:
starnakin 2024-07-30 09:28:43 +02:00
commit 290a120319
17 changed files with 472 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
bozo
bozo.d
libmalloc.so
build
.vscode

41
Makefile Normal file
View File

@ -0,0 +1,41 @@
MAKEFLAGS += -j
CC := gcc
LD := $(CC)
CFLAGS := -g -O0 -Wall -Wextra -Werror -MMD
OBJ := $(patsubst src/%.c,build/%.o,$(wildcard src/*.c))
DEP := $(patsubst %.o,%.d,$(OBJ))
NAME := libmalloc.so
all: $(NAME)
$(NAME): $(OBJ)
@printf 'LD %s\n' "$@"
$(LD) -shared -o $(NAME) $(OBJ)
build/%.o: src/%.c
@printf 'CC %s\n' "$@"
@mkdir -p $(@D)
@$(CC) $(CFLAGS) -fPIC -c -o $@ $<
clean:
@printf 'RM build\n'
@rm -rf build/
fclean:
@printf 'RM build %s\n' "$(NAME)"
@rm -rf build/ $(NAME) bozo bozo.d
re:
@make --no-print-directory fclean
@make --no-print-directory all
test:
@make --no-print-directory all
@$(CC) $(CFLAGS) test/main.c -o bozo -L. -lmalloc
@export LD_LIBRARY_PATH=$(shell pwd) && valgrind ./bozo
.PHONY: all clean fclean re test
-include $(DEP)

7
include/malloc.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <stdlib.h>
void ft_free(void *ptr);
void *ft_malloc(size_t size);
void *ft_realloc(void *ptr, size_t size);

12
src/align.c Normal file
View File

@ -0,0 +1,12 @@
#include <stddef.h>
#include <stdint.h>
#include "align.h"
size_t get_align_increment(void *block)
{
size_t gap = ((uintptr_t) block) % ALIGN_MARGING;
if (gap == 0)
return 0;
return ALIGN_MARGING - gap;
}

7
src/align.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <stddef.h>
#define ALIGN_MARGING 16
size_t get_align_increment(void *block);

34
src/block.c Normal file
View File

@ -0,0 +1,34 @@
#include <stdbool.h>
#include <stddef.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdint.h>
#include "align.h"
#include "./chunk.h"
int add_new_block(chunk_t* chunk, size_t size, void *prev, void *next, bool is_used)
{
static int block_id = 0;
void *new_block;
chunk_t previous_chunk;
// TODO check with getrlimit()
new_block = mmap(NULL, size + ALIGN_MARGING + CHUNK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
init_chunk(chunk, size + ALIGN_MARGING - get_align_increment(new_block + CHUNK_SIZE), block_id, prev, new_block, next, is_used);
if (prev != NULL)
{
chunk_read(prev, &previous_chunk);
previous_chunk.next = chunk->current;
chunk_write(&previous_chunk);
}
block_id++;
return 0;
}

7
src/block.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <stddef.h>
#include "chunk.h"
int add_new_block(chunk_t* chunk, size_t size, void *prev, void *next, bool is_used);

51
src/chunk.c Normal file
View File

@ -0,0 +1,51 @@
#include <stddef.h>
#include <stdbool.h>
#include "./chunk.h"
#include "./align.h"
void chunk_write(const chunk_t *chunk)
{
void **block = chunk->current;
block[CHUNK_NEXT_POS] = (void*) chunk->next;
block[CHUNK_CURRENT_POS] = (void*) chunk->current;
block[CHUNK_PREV_POS] = (void*) chunk->prev;
block[CHUNK_SIZE_POS] = (void*) chunk->size;
block[CHUNK_IS_USED_POS] = (void*) chunk->is_used;
block[CHUNK_BLOCK_ID_POS] = (void*) chunk->block_id;
block[CHUNK_DATA_START_POS] = chunk->data_start;
}
void chunk_read(void * const *block, chunk_t *chunk)
{
chunk->next = block[CHUNK_NEXT_POS];
chunk->current = block[CHUNK_CURRENT_POS];
chunk->prev = block[CHUNK_PREV_POS];
chunk->size = (size_t) block[CHUNK_SIZE_POS];
chunk->is_used = block[CHUNK_IS_USED_POS];
chunk->block_id = (long) block[CHUNK_BLOCK_ID_POS];
chunk->data_start = block[CHUNK_DATA_START_POS];
}
void init_chunk(chunk_t *chunk, size_t size, long block_id, void *prev, void *current, void *next, bool is_used)
{
void *data_start = current + CHUNK_SIZE;
data_start = data_start + get_align_increment(data_start);
chunk->is_used = is_used;
chunk->data_start = data_start;
chunk->prev = prev;
chunk->current = current;
chunk->next = next;
chunk->size = size;
chunk->block_id = block_id;
chunk_write(chunk);
}
size_t get_physical_size(const chunk_t *chunk)
{
return chunk->data_start + chunk->size - chunk->current;
}

37
src/chunk.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <stddef.h>
#include <stdbool.h>
typedef struct {
void *next;
void *current;
void *prev;
size_t size;
bool is_used;
long block_id;
void *data_start;
} chunk_t;
enum {
CHUNK_NEXT_POS,
CHUNK_CURRENT_POS,
CHUNK_PREV_POS,
CHUNK_SIZE_POS,
CHUNK_IS_USED_POS,
CHUNK_BLOCK_ID_POS,
CHUNK_DATA_START_POS,
CHUNK_SIZE
};
enum {
TINY,
SMALL,
LARGE
};
void chunk_read(void * const *block, chunk_t *chunk);
void chunk_write(const chunk_t *chunk);
void init_chunk(chunk_t *chunk, size_t size, long block_id, void *prev, void *current, void *next, bool is_used);
size_t get_physical_size(const chunk_t *chunk);

63
src/chunk_manager.c Normal file
View File

@ -0,0 +1,63 @@
#include "chunk.h"
#include "align.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;
}
void chunk_merge(chunk_t *first, chunk_t *second)
{
//if (first->block_id != second->block_id)
first->size = first->size + second->size + CHUNK_SIZE + ALIGN_MARGING - get_align_increment(first->next);
first->next = second->next;
}
int chunk_split(chunk_t *chunk, chunk_t *new_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;
init_chunk(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);
init_chunk(chunk, new_size, chunk->block_id, chunk->prev, chunk->current, new_chunk->current, false);
return 0;
}
void destroy_chunk(chunk_t *chunk)
{
chunk_t chunk_next_to;
if (chunk->prev != NULL)
{
chunk_read(chunk->prev, &chunk_next_to);
if (chunk_next_to.block_id == chunk->block_id && chunk_next_to.is_used == false)
chunk_merge(&chunk_next_to, chunk);
*chunk = chunk_next_to;
}
if (chunk->next != NULL)
{
chunk_read(chunk->next, &chunk_next_to);
if (chunk_next_to.block_id == chunk->block_id && chunk_next_to.is_used == false)
chunk_merge(chunk, &chunk_next_to);
}
chunk->is_used = false;
chunk_write(chunk);
}

5
src/chunk_manager.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "chunk.h"
void destroy_chunk(chunk_t *chunk);

110
src/malloc.c Normal file
View File

@ -0,0 +1,110 @@
#include <stddef.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "./size.h"
#include "block.h"
#include "raw_chunk_manager.h"
#include "chunk_manager.h"
#include "malloc.h"
void *alloc_tiny(size_t size)
{
(void)size;
return NULL;
}
void *alloc_small(size_t size)
{
(void)size;
return NULL;
}
void *alloc_large(size_t size)
{
chunk_t new_chunk;
void *first = allocs_tree[LARGE];
if (first == NULL)
{
if (add_new_block(&new_chunk, size, NULL, NULL, true))
return NULL;
allocs_tree[LARGE] = new_chunk.current;
return new_chunk.data_start;
}
void *last = raw_get_last_chunk(first);
if (add_new_block(&new_chunk, size, last, NULL, true))
return NULL;
return new_chunk.data_start;
}
void *ft_malloc(size_t size)
{
if (size < n)
return alloc_tiny(size);
if (size < m)
return alloc_small(size);
return alloc_large(size);
//mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
void free_tiny(chunk_t *chunk)
{
(void) chunk;
}
void free_small(chunk_t *chunk)
{
(void) chunk;
}
void free_large(chunk_t *chunk)
{
if (chunk->current == allocs_tree[LARGE])
allocs_tree[LARGE] = chunk->next;
destroy_chunk(chunk);
munmap(chunk->current, get_physical_size(chunk));
}
static void (*free_funcs[3])(chunk_t*) = {free_tiny, free_small, free_large};
void ft_free(void *ptr)
{
void **root;
void *raw_chunk;
chunk_t chunk;
size_t i;
for (i = TINY; i <= LARGE + 1; i++)
{
if (i > LARGE)
{
// THROW ERROR
write(2, "block not found\n", 16);
}
root = allocs_tree[i];
raw_chunk = raw_get_chunk(root, ptr);
if (raw_chunk == NULL)
continue;
break;
}
chunk_read(raw_chunk, &chunk);
if (chunk.is_used == false)
{
write(2, "double free\n", 12);
// THROW ERROR
}
// CALL THE RIGHT FREE FUNCTION DEPEND ON SIZE
free_funcs[i](&chunk);
}

3
src/malloc.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void* allocs_tree[3] = { 0, 0, 0};

29
src/raw_chunk_manager.c Normal file
View File

@ -0,0 +1,29 @@
#include "chunk.h"
void *raw_get_last_chunk(void **root)
{
void **current = root;
if (current == NULL)
return NULL;
while (current[CHUNK_NEXT_POS] != NULL)
current = current[CHUNK_NEXT_POS];
return current;
}
void *raw_get_chunk(void **root, void *data_start)
{
void**current = root;
while (current != NULL)
{
if (current[CHUNK_DATA_START_POS] == data_start)
return current;
current = current[CHUNK_NEXT_POS];
}
return NULL;
}

4
src/raw_chunk_manager.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
void *raw_get_last_chunk(void **root);
void *raw_get_chunk(void **root, void *data_start);

7
src/size.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#define n 400 // TINY MAX SIZE
#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

50
test/main.c Normal file
View File

@ -0,0 +1,50 @@
#include "../include/malloc.h"
#include "../src/align.h"
#include "../src/malloc.h"
#include "../src/chunk.h"
#include "../src/raw_chunk_manager.h"
#include <stdio.h>
#define NOT_NULL (void*) 55342301
void test(const void* expected_value, const void* value, const char* test_name, const char* description)
{
printf("%s ", test_name);
if ((expected_value == NOT_NULL && value != NULL) || (expected_value != NOT_NULL && expected_value == value))
printf("[OK]");
else
printf("[FAILED] %s {%p != %p}", description, expected_value, value);
printf("\n");
}
int main(int ac, char **av)
{
(void) ac;
(void) av;
printf("-----------ALIGN-----------\n");
test(0, (void*) get_align_increment(0), "align test 1", "");
test((void*) 15, (void*) get_align_increment((void*) 1), "align test 2", "");
printf("-----------ALLOC (LARGE)-----------\n");
void* 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");
void *ptr1 = ft_malloc(10000000);
void *ptr2 = ft_malloc(10000000);
void *ptr3 = ft_malloc(10000000);
test(NOT_NULL, raw_get_chunk(allocs_tree[LARGE], ptr1), "alloc first", "");
test(NOT_NULL, raw_get_chunk(allocs_tree[LARGE], ptr2), "alloc second", "");
test(NOT_NULL, raw_get_chunk(allocs_tree[LARGE], ptr3), "alloc third", "");
ft_free(ptr1);
test(NOT_NULL, raw_get_chunk(allocs_tree[LARGE], ptr2), "free disorder1", "");
ft_free(ptr3);
test(NOT_NULL, raw_get_chunk(allocs_tree[LARGE], ptr2), "free disorder1", "");
ft_free(ptr2);
test(NULL, allocs_tree[LARGE], "free disorder1", "");
return 0;
}