From 3fa3ff530410cbe133a344210155deb6c2c4a131 Mon Sep 17 00:00:00 2001 From: Gregory Date: Wed, 8 May 2019 21:10:37 +0300 Subject: [PATCH] add therad support --- inc/ft_malloc.h | 1 + inc/ft_malloc_internal.h | 36 ++++++++----- meson.build | 2 + src/calloc.c | 35 ++++++++++++ src/free.c | 11 +++- src/get_arena_type.c | 22 ++++++++ src/malloc.c | 25 +++++---- src/realloc.c | 18 +++++-- t/fuzzy_fast.c | 114 +++++++++++++++++++++++++++++++++++++++ t/meson.build | 18 +++++-- 10 files changed, 248 insertions(+), 34 deletions(-) create mode 100644 src/calloc.c create mode 100644 src/get_arena_type.c create mode 100644 t/fuzzy_fast.c diff --git a/inc/ft_malloc.h b/inc/ft_malloc.h index a7a00f9..dbeebac 100644 --- a/inc/ft_malloc.h +++ b/inc/ft_malloc.h @@ -17,6 +17,7 @@ void free(void *ptr); void *malloc(size_t size); +void *calloc(size_t count, size_t size); void *realloc(void *ptr, size_t size); void show_alloc_mem(void); diff --git a/inc/ft_malloc_internal.h b/inc/ft_malloc_internal.h index a5a42b7..4b64f9d 100644 --- a/inc/ft_malloc_internal.h +++ b/inc/ft_malloc_internal.h @@ -15,6 +15,8 @@ # include # include +# include + # define TINY 512 # define SMALL 4096 @@ -23,28 +25,34 @@ # define MAGIC 0xDEADBEEF # define NALLOC 100 -typedef struct s_chunk +typedef struct s_chunk { - uint8_t is_free; - size_t size; - struct s_chunk *next; - struct s_chunk *prev; - uint32_t magic; -} t_chunk; + uint8_t is_free; + size_t size; + struct s_chunk *next; + struct s_chunk *prev; + uint32_t magic; +} t_chunk; # define CHUNK_SIZE(size) ((size) + sizeof(t_chunk)) -typedef struct s_arena +typedef struct s_arena { - int type; - size_t size; - struct s_arena *next; - t_chunk *heap; -} t_arena; + int type; + size_t size; + struct s_arena *next; + t_chunk *heap; +} t_arena; # define HEAP_SIZE(size) ((size) - sizeof(t_arena)) # define ARENA_SIZE(size) ((size) + sizeof(t_arena)) -extern t_arena g_base; +extern t_arena g_base; + +extern pthread_mutex_t g_malloc_mutex; + +int get_arena_type(size_t size); +void *malloc_core(size_t size); +void free_core(void *used); #endif diff --git a/meson.build b/meson.build index 0511040..3dd9c3e 100644 --- a/meson.build +++ b/meson.build @@ -7,6 +7,7 @@ project( ) add_global_arguments( + '-O0', '-Wall', '-Wextra', '-Werror', @@ -30,6 +31,7 @@ sources = [ 'src/malloc.c', 'src/free.c', 'src/realloc.c', + 'src/get_arena_type.c' ] libft = subproject('libft') diff --git a/src/calloc.c b/src/calloc.c new file mode 100644 index 0000000..fe8e8dd --- /dev/null +++ b/src/calloc.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* calloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: gtertysh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2019/05/08 21:07:09 by gtertysh #+# #+# */ +/* Updated: 2019/05/08 21:07:34 by gtertysh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_malloc_internal.h" +#include "libft.h" + +static void *calloc_core(size_t count, size_t size) +{ + void *ptr; + + ptr = malloc(count * size); + if (!ptr) + return (NULL); + ft_bzero(ptr, count * size); + return (ptr); +} + +void *calloc(size_t count, size_t size) +{ + void *ptr; + + pthread_mutex_lock(&g_malloc_mutex); + ptr = calloc_core(count, size); + pthread_mutex_unlock(&g_malloc_mutex); + return (ptr); +} diff --git a/src/free.c b/src/free.c index be98b6a..2847729 100644 --- a/src/free.c +++ b/src/free.c @@ -6,14 +6,14 @@ /* By: gtertysh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/05/06 22:35:53 by foton #+# #+# */ -/* Updated: 2019/05/06 22:40:09 by gtertysh ### ########.fr */ +/* Updated: 2019/05/08 21:08:00 by gtertysh ### ########.fr */ /* */ /* ************************************************************************** */ #include "ft_malloc.h" #include "ft_malloc_internal.h" -void free(void *used) +void free_core(void *used) { t_chunk *chunk; @@ -39,3 +39,10 @@ void free(void *used) chunk->next->prev = chunk; } } + +void free(void *used) +{ + pthread_mutex_lock(&g_malloc_mutex); + free_core(used); + pthread_mutex_unlock(&g_malloc_mutex); +} diff --git a/src/get_arena_type.c b/src/get_arena_type.c new file mode 100644 index 0000000..4d3a981 --- /dev/null +++ b/src/get_arena_type.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_arena_type.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: gtertysh +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2019/05/08 21:08:05 by gtertysh #+# #+# */ +/* Updated: 2019/05/08 21:08:06 by gtertysh ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ft_malloc_internal.h" + +int get_arena_type(size_t size) +{ + if (size <= CHUNK_SIZE(TINY)) + return (TINY); + if (size <= CHUNK_SIZE(SMALL)) + return (SMALL); + return (LARGE); +} diff --git a/src/malloc.c b/src/malloc.c index 95baa43..fb2c795 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -6,7 +6,7 @@ /* By: gtertysh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/05/06 22:35:57 by foton #+# #+# */ -/* Updated: 2019/05/08 19:44:07 by gtertysh ### ########.fr */ +/* Updated: 2019/05/08 21:08:52 by gtertysh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,8 @@ t_arena g_base = { .type = START, .size = 0, .next = &g_base, .heap = NULL}; +pthread_mutex_t g_malloc_mutex = PTHREAD_MUTEX_INITIALIZER; + static size_t get_actual_size(size_t size, int type) { size_t minimum; @@ -30,15 +32,6 @@ static size_t get_actual_size(size_t size, int type) return ((ARENA_SIZE(minimum) + page - 1) / page * page); } -static int get_arena_type(size_t size) -{ - if (size <= CHUNK_SIZE(TINY)) - return (TINY); - if (size <= CHUNK_SIZE(SMALL)) - return (SMALL); - return (LARGE); -} - static t_arena *get_more_arena(size_t size, int type) { t_arena *arena; @@ -85,7 +78,7 @@ static t_chunk *chunk_heap(t_chunk *chunk, size_t size) return (new_chunk); } -void *malloc(size_t size) +void *malloc_core(size_t size) { t_arena *arena; t_chunk *heap; @@ -112,3 +105,13 @@ void *malloc(size_t size) } return (space + 1); } + +void *malloc(size_t size) +{ + void *ptr; + + pthread_mutex_lock(&g_malloc_mutex); + ptr = malloc_core(size); + pthread_mutex_unlock(&g_malloc_mutex); + return (ptr); +} diff --git a/src/realloc.c b/src/realloc.c index 6bd37d8..06f1051 100644 --- a/src/realloc.c +++ b/src/realloc.c @@ -6,7 +6,7 @@ /* By: gtertysh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/05/06 22:35:48 by foton #+# #+# */ -/* Updated: 2019/05/08 19:44:41 by gtertysh ### ########.fr */ +/* Updated: 2019/05/08 21:09:05 by gtertysh ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,7 @@ #include "ft_malloc_internal.h" #include "libft.h" -void *realloc(void *ptr, size_t size) +static void *realloc_core(void *ptr, size_t size) { t_chunk *chunk; t_chunk *new_chunk; @@ -26,8 +26,18 @@ void *realloc(void *ptr, size_t size) return (NULL); if (chunk->size >= CHUNK_SIZE(size)) return (ptr); - new_chunk = malloc(size); + new_chunk = malloc_core(size); ft_memmove(new_chunk, ptr, chunk->size - CHUNK_SIZE(0)); - free(ptr); + free_core(ptr); return (new_chunk); } + +void *realloc(void *ptr, size_t size) +{ + void *new_ptr; + + pthread_mutex_lock(&g_malloc_mutex); + new_ptr = realloc_core(ptr, size); + pthread_mutex_unlock(&g_malloc_mutex); + return (new_ptr); +} diff --git a/t/fuzzy_fast.c b/t/fuzzy_fast.c new file mode 100644 index 0000000..c683522 --- /dev/null +++ b/t/fuzzy_fast.c @@ -0,0 +1,114 @@ +// gcc -O2 -o main main.c -lz + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct item { + void *ptr; + size_t size; + size_t hash; +}; + +int dev_urandom_fd = -1; + +static void hash_compute(struct item *item) { + unsigned long pos = 0; + do { + pos += read(dev_urandom_fd, item->ptr, item->size - pos); + assert(errno == 0); + // fprintf(stderr, "Read %lu bytes from /dev/urandom\n", pos); + } while (pos < item->size); + + item->hash = adler32(0, item->ptr, item->size); +} + +static int hash_check(struct item *item) { + if (item->ptr == NULL) + return 1; + + return (item->hash == adler32(0, item->ptr, item->size)); +} + +int main(int argc, const char *const argv[]) { + if (argc < 4) { + puts("Usage: ... num_passes num_items size_min size_max"); + return 1; + } + + dev_urandom_fd = open("/dev/urandom", O_RDONLY); + assert(dev_urandom_fd >= 0); + + size_t num_passes = atoi(argv[1]), + num_items = atoi(argv[2]), + size_min = atoi(argv[3]), + size_max = atoi(argv[4]); + struct item items[num_items]; + + srand(argc + num_items + size_min + size_max + (int)(long)argv[0]); + srand(rand() ^ time(NULL)); + bzero(items, sizeof(struct item) * num_items); + + for (size_t pass = 0; pass < num_passes; pass++) { + for (size_t i = 0; i < num_items; i++) { + if (pass % 3 == 0) { + if (rand() & 1 && items[i].ptr == NULL) { + items[i].size = rand() % (size_max - size_min) + size_min; + items[i].ptr = malloc(items[i].size); + if (items[i].ptr) { + hash_compute(&items[i]); + printf("pass %-2lu item %-4lu malloc(%lu) => %p..%p\n", + pass, i, items[i].size, items[i].ptr, items[i].ptr + items[i].size); + } else { + printf("\033[0;31mpass %-2lu item %-4lu returned NULL\033[0m\n", pass, i); + } + } + } else if (pass % 3 == 1) { + if (rand() & 1 && items[i].ptr != NULL) { + void *old_ptr = items[i].ptr; + items[i].size = rand() % (size_max - size_min) + size_min; + items[i].ptr = realloc(items[i].ptr, items[i].size); + if (items[i].ptr) { + hash_compute(&items[i]); + printf("pass %-2lu item %-4lu realloc(%p, %lu) => %p\n", + pass, i, old_ptr, items[i].size, items[i].ptr); + } else { + printf("\033[0;31mpass %-2lu item %-4lu realloc failed\033[0m\n", pass, i); + } + } + } else { + if (rand() & 1 && items[i].ptr != NULL) { + printf("pass %-2lu item %-4lu free(%p)\n", + pass, i, items[i].ptr); + free(items[i].ptr); + items[i].ptr = NULL; + } else if (pass == num_passes - 1 && items[i].ptr != NULL) { + printf("pass %-2lu item %-4lu free(%p)\n", + pass, i, items[i].ptr); + free(items[i].ptr); + items[i].ptr = NULL; + } + } + + for (size_t j = 0; j < num_items; j++) { + if (!hash_check(&items[i])) { + printf("\033[0;31mpass %-2lu item %-4lu hash_check failed\033[0m\n", pass, i); + items[i].ptr = NULL; + } + } + } + + /* show_alloc_mem(); */ + } + + close(dev_urandom_fd); + + return (0); +} diff --git a/t/meson.build b/t/meson.build index 7ec568e..b940a5d 100644 --- a/t/meson.build +++ b/t/meson.build @@ -6,13 +6,25 @@ malloc_tests = executable( ) -malloc_fuzzy_tests = executable( +malloc_fuzzy = executable( 'malloc_fuzzy', 'fuzzy.c', include_directories: inc, link_with: ft_malloc, ) -test('malloc tests', malloc_tests) +zlib_dep = dependency('zlib') -test('malloc fuzzy tests', malloc_fuzzy_tests, args: ['10', '1000', '0', '10000']) \ No newline at end of file +malloc_fuzzy_fast = executable( + 'malloc_fuzzy_fast', + 'fuzzy_fast.c', + include_directories: inc, + link_with: ft_malloc, + dependencies: zlib_dep +) + + +test('basic', malloc_tests) + +test('fuzzy', malloc_fuzzy, args: ['10', '1000', '0', '10000']) +test('fuzzy_fast', malloc_fuzzy_fast, args: ['100', '1000', '0', '10000']) \ No newline at end of file