/** * @file malloc.c * @brief malloc implementation. */ #include "malloc.h" #include "malloc_internal.h" t_heap g_heap = { 0 }; static t_chunk * _s_find_free_chunk (t_zone *zone, size_t aligned_size) { t_chunk *chunk; chunk = (t_chunk *)((char *)zone + ALIGN (sizeof (t_zone))); while (chunk) { if (chunk->is_free && chunk->size >= aligned_size) return (chunk); chunk = chunk->next; } return (NULL); } static void _s_split_chunk (t_chunk *chunk, size_t aligned_size) { t_chunk *remainder; size_t min_split; min_split = ALIGN (sizeof (t_chunk)) + ALIGNMENT; if (chunk->size >= aligned_size + min_split) { remainder = (t_chunk *)((char *)chunk + ALIGN (sizeof (t_chunk)) + aligned_size); remainder->size = chunk->size - aligned_size - ALIGN (sizeof (t_chunk)); remainder->next = chunk->next; remainder->is_free = 1; chunk->size = aligned_size; chunk->next = remainder; } chunk->is_free = 0; } void * malloc (size_t size) { t_zone **zone_list; t_zone *zone; t_chunk *chunk; size_t alloc_max; size_t aligned_size; if (size == 0) size = 1; if (size <= TINY_MAX) { zone_list = &g_heap.tiny; alloc_max = TINY_MAX; } else if (size <= SMALL_MAX) { zone_list = &g_heap.small; alloc_max = SMALL_MAX; } else { zone_list = &g_heap.large; alloc_max = size; } aligned_size = ALIGN (size); chunk = NULL; zone = *zone_list; while (zone && !chunk) { chunk = _s_find_free_chunk (zone, aligned_size); if (!chunk) zone = zone->next; } if (!chunk) { zone = zone_new (alloc_max); if (!zone) return (NULL); zone->next = *zone_list; *zone_list = zone; chunk = _s_find_free_chunk (zone, aligned_size); } _s_split_chunk (chunk, aligned_size); return ((char *)chunk + ALIGN (sizeof (t_chunk))); }