/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* ft_free.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: thrieg +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/11/19 15:44:05 by thrieg #+# #+# */ /* Updated: 2025/12/13 06:52:01 by thrieg ### ########.fr */ /* */ /* ************************************************************************** */ #include "../includes/ft_malloc.h" // returns non-0 (1) when the function munmap the zone int defrag_zone(t_zone *zone) { t_header *header = (t_header *)(zone + 1); char *last_adr = ((char *)zone) + zone->size - sizeof(t_header); while ((((char *)header) + header->size) < last_adr) { t_header *next_header = (t_header *)(((char *)header) + sizeof(t_header) + header->size); if (!header->occupied && !next_header->occupied) { header->size = header->size + sizeof(t_header) + next_header->size; } else { header = next_header; } } // if only 1 free header left, mmunmap the zone if (header == (t_header *)(zone + 1) && !header->occupied) { if (zone->type == E_SMALL) { if (g_state.small_zone == zone) { if (zone->next) g_state.small_zone = zone->next; else return (0); // last small zone, don't deallocate to avoid mmap stress } } else if (zone->type == E_TINY) { if (g_state.tiny_zone == zone) { if (zone->next) g_state.tiny_zone = zone->next; else return (0); // last tiny zone, don't deallocate to avoid mmap stress } } if (zone->prev) zone->prev->next = zone->next; if (zone->next) zone->next->prev = zone->prev; munmap(zone, zone->size); return (1); } return (0); } void free(void *ptr) { pthread_mutex_lock(&g_mut); if (!g_state.is_init) init_env_variables(); // shouldn't ever happen because free can't be called first, but it protects the program if (!ptr) return ((void)pthread_mutex_unlock(&g_mut)); t_header *header = ((t_header *)ptr) - 1; if (header->zone->type == E_LARGE) { if (header->zone->prev) header->zone->prev->next = header->zone->next; if (header->zone->next) header->zone->next->prev = header->zone->prev; if (header->zone == g_state.large_zone) { if (g_state.large_zone->next) g_state.large_zone = g_state.large_zone->next; else g_state.large_zone = NULL; } void *ptr = header->zone; size_t len = header->zone->size; munmap(ptr, len); pthread_mutex_unlock(&g_mut); return; } else if (header->zone->type == E_SMALL) { header->occupied = false; if (defrag_zone(header->zone)) return; //zone munmaped, avoid all other logic on this memory } else if (header->zone->type == E_TINY) { header->occupied = false; if (defrag_zone(header->zone)) return; //zone munmaped, avoid all other logic on this memory } else { pthread_mutex_unlock(&g_mut); return; // we didn't allocate this ptr } if (g_state.patern) ft_memset(ptr, g_state.patern ^ 0xFF, header->size); // need to lock because this memory can be reallocated from another thread at any time (even before this function returns if we put it outside of lock) pthread_mutex_unlock(&g_mut); }