add therad support
This commit is contained in:
parent
80fedbeb03
commit
3fa3ff5304
10 changed files with 248 additions and 34 deletions
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
void free(void *ptr);
|
void free(void *ptr);
|
||||||
void *malloc(size_t size);
|
void *malloc(size_t size);
|
||||||
|
void *calloc(size_t count, size_t size);
|
||||||
void *realloc(void *ptr, size_t size);
|
void *realloc(void *ptr, size_t size);
|
||||||
void show_alloc_mem(void);
|
void show_alloc_mem(void);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
# include <stddef.h>
|
# include <stddef.h>
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
|
# include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
# define TINY 512
|
# define TINY 512
|
||||||
# define SMALL 4096
|
# define SMALL 4096
|
||||||
|
@ -23,28 +25,34 @@
|
||||||
# define MAGIC 0xDEADBEEF
|
# define MAGIC 0xDEADBEEF
|
||||||
# define NALLOC 100
|
# define NALLOC 100
|
||||||
|
|
||||||
typedef struct s_chunk
|
typedef struct s_chunk
|
||||||
{
|
{
|
||||||
uint8_t is_free;
|
uint8_t is_free;
|
||||||
size_t size;
|
size_t size;
|
||||||
struct s_chunk *next;
|
struct s_chunk *next;
|
||||||
struct s_chunk *prev;
|
struct s_chunk *prev;
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
} t_chunk;
|
} t_chunk;
|
||||||
|
|
||||||
# define CHUNK_SIZE(size) ((size) + sizeof(t_chunk))
|
# define CHUNK_SIZE(size) ((size) + sizeof(t_chunk))
|
||||||
|
|
||||||
typedef struct s_arena
|
typedef struct s_arena
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
size_t size;
|
size_t size;
|
||||||
struct s_arena *next;
|
struct s_arena *next;
|
||||||
t_chunk *heap;
|
t_chunk *heap;
|
||||||
} t_arena;
|
} t_arena;
|
||||||
|
|
||||||
# define HEAP_SIZE(size) ((size) - sizeof(t_arena))
|
# define HEAP_SIZE(size) ((size) - sizeof(t_arena))
|
||||||
# define ARENA_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
|
#endif
|
||||||
|
|
|
@ -7,6 +7,7 @@ project(
|
||||||
)
|
)
|
||||||
|
|
||||||
add_global_arguments(
|
add_global_arguments(
|
||||||
|
'-O0',
|
||||||
'-Wall',
|
'-Wall',
|
||||||
'-Wextra',
|
'-Wextra',
|
||||||
'-Werror',
|
'-Werror',
|
||||||
|
@ -30,6 +31,7 @@ sources = [
|
||||||
'src/malloc.c',
|
'src/malloc.c',
|
||||||
'src/free.c',
|
'src/free.c',
|
||||||
'src/realloc.c',
|
'src/realloc.c',
|
||||||
|
'src/get_arena_type.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
libft = subproject('libft')
|
libft = subproject('libft')
|
||||||
|
|
35
src/calloc.c
Normal file
35
src/calloc.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* calloc.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: gtertysh <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* 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);
|
||||||
|
}
|
11
src/free.c
11
src/free.c
|
@ -6,14 +6,14 @@
|
||||||
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2019/05/06 22:35:53 by foton #+# #+# */
|
/* 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.h"
|
||||||
#include "ft_malloc_internal.h"
|
#include "ft_malloc_internal.h"
|
||||||
|
|
||||||
void free(void *used)
|
void free_core(void *used)
|
||||||
{
|
{
|
||||||
t_chunk *chunk;
|
t_chunk *chunk;
|
||||||
|
|
||||||
|
@ -39,3 +39,10 @@ void free(void *used)
|
||||||
chunk->next->prev = chunk;
|
chunk->next->prev = chunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free(void *used)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&g_malloc_mutex);
|
||||||
|
free_core(used);
|
||||||
|
pthread_mutex_unlock(&g_malloc_mutex);
|
||||||
|
}
|
||||||
|
|
22
src/get_arena_type.c
Normal file
22
src/get_arena_type.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* get_arena_type.c :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: gtertysh <marvin@42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* 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);
|
||||||
|
}
|
25
src/malloc.c
25
src/malloc.c
|
@ -6,7 +6,7 @@
|
||||||
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2019/05/06 22:35:57 by foton #+# #+# */
|
/* 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};
|
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)
|
static size_t get_actual_size(size_t size, int type)
|
||||||
{
|
{
|
||||||
size_t minimum;
|
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);
|
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)
|
static t_arena *get_more_arena(size_t size, int type)
|
||||||
{
|
{
|
||||||
t_arena *arena;
|
t_arena *arena;
|
||||||
|
@ -85,7 +78,7 @@ static t_chunk *chunk_heap(t_chunk *chunk, size_t size)
|
||||||
return (new_chunk);
|
return (new_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *malloc(size_t size)
|
void *malloc_core(size_t size)
|
||||||
{
|
{
|
||||||
t_arena *arena;
|
t_arena *arena;
|
||||||
t_chunk *heap;
|
t_chunk *heap;
|
||||||
|
@ -112,3 +105,13 @@ void *malloc(size_t size)
|
||||||
}
|
}
|
||||||
return (space + 1);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2019/05/06 22:35:48 by foton #+# #+# */
|
/* 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 "ft_malloc_internal.h"
|
||||||
#include "libft.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 *chunk;
|
||||||
t_chunk *new_chunk;
|
t_chunk *new_chunk;
|
||||||
|
@ -26,8 +26,18 @@ void *realloc(void *ptr, size_t size)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (chunk->size >= CHUNK_SIZE(size))
|
if (chunk->size >= CHUNK_SIZE(size))
|
||||||
return (ptr);
|
return (ptr);
|
||||||
new_chunk = malloc(size);
|
new_chunk = malloc_core(size);
|
||||||
ft_memmove(new_chunk, ptr, chunk->size - CHUNK_SIZE(0));
|
ft_memmove(new_chunk, ptr, chunk->size - CHUNK_SIZE(0));
|
||||||
free(ptr);
|
free_core(ptr);
|
||||||
return (new_chunk);
|
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);
|
||||||
|
}
|
||||||
|
|
114
t/fuzzy_fast.c
Normal file
114
t/fuzzy_fast.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// gcc -O2 -o main main.c -lz
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
|
@ -6,13 +6,25 @@ malloc_tests = executable(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
malloc_fuzzy_tests = executable(
|
malloc_fuzzy = executable(
|
||||||
'malloc_fuzzy',
|
'malloc_fuzzy',
|
||||||
'fuzzy.c',
|
'fuzzy.c',
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
link_with: ft_malloc,
|
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'])
|
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'])
|
Loading…
Reference in a new issue