diff --git a/include/memory_pool.h b/include/memory_pool.h index 01e38c1..f9ee749 100644 --- a/include/memory_pool.h +++ b/include/memory_pool.h @@ -10,6 +10,11 @@ #define _MEMORY_POOL_H_ #include +#include + +/* Magic numbers for double-free detection */ +#define MEMORY_POOL_MAGIC_ALLOCATED 0xABCD1234U +#define MEMORY_POOL_MAGIC_FREE 0xDEADBEEFU struct memory_pool_t { @@ -22,6 +27,7 @@ struct memory_pool_t int node_count_allocated; int node_count_free; int node_count_total; + pthread_mutex_t mutex; }; typedef struct memory_pool_t MEMORY_POOL; diff --git a/src/memory_pool.c b/src/memory_pool.c index 34de227..9e3c376 100644 --- a/src/memory_pool.c +++ b/src/memory_pool.c @@ -14,10 +14,19 @@ #include "memory_pool.h" #include #include +#include + +/* Align size to max_align_t for proper memory alignment */ +static inline size_t align_size(size_t size) +{ + size_t alignment = _Alignof(max_align_t); + return (size + alignment - 1) & ~(alignment - 1); +} MEMORY_POOL *memory_pool_init(size_t node_size, size_t node_count_per_chunk, int chunk_count_limit) { MEMORY_POOL *p_pool; + size_t aligned_node_size; if (node_size < sizeof(void *)) { @@ -25,6 +34,9 @@ MEMORY_POOL *memory_pool_init(size_t node_size, size_t node_count_per_chunk, int return NULL; } + /* Align node_size for proper memory alignment */ + aligned_node_size = align_size(node_size); + p_pool = malloc(sizeof(MEMORY_POOL)); if (p_pool == NULL) { @@ -32,7 +44,15 @@ MEMORY_POOL *memory_pool_init(size_t node_size, size_t node_count_per_chunk, int return NULL; } - p_pool->node_size = node_size; + /* Initialize mutex */ + if (pthread_mutex_init(&p_pool->mutex, NULL) != 0) + { + log_error("pthread_mutex_init error"); + free(p_pool); + return NULL; + } + + p_pool->node_size = aligned_node_size; p_pool->node_count_per_chunk = node_count_per_chunk; p_pool->chunk_count_limit = chunk_count_limit; p_pool->chunk_count = 0; @@ -42,6 +62,7 @@ MEMORY_POOL *memory_pool_init(size_t node_size, size_t node_count_per_chunk, int if (p_pool->p_chunks == NULL) { log_error("malloc(sizeof(void *) * %d) error: OOM", chunk_count_limit); + pthread_mutex_destroy(&p_pool->mutex); free(p_pool); return NULL; } @@ -60,6 +81,8 @@ void memory_pool_cleanup(MEMORY_POOL *p_pool) return; } + pthread_mutex_lock(&p_pool->mutex); + if (p_pool->node_count_allocated > 0) { log_error("Still have %d in-use nodes", p_pool->node_count_allocated); @@ -72,6 +95,10 @@ void memory_pool_cleanup(MEMORY_POOL *p_pool) } free(p_pool->p_chunks); + + pthread_mutex_unlock(&p_pool->mutex); + pthread_mutex_destroy(&p_pool->mutex); + free(p_pool); } @@ -124,9 +151,12 @@ void *memory_pool_alloc(MEMORY_POOL *p_pool) return NULL; } + pthread_mutex_lock(&p_pool->mutex); + if (p_pool->p_free == NULL && memory_pool_add_chunk(p_pool) == NULL) { log_error("Add chunk error"); + pthread_mutex_unlock(&p_pool->mutex); return NULL; } @@ -136,27 +166,53 @@ void *memory_pool_alloc(MEMORY_POOL *p_pool) (p_pool->node_count_free)--; (p_pool->node_count_allocated)++; + pthread_mutex_unlock(&p_pool->mutex); + return p_node; } void memory_pool_free(MEMORY_POOL *p_pool, void *p_node) { + uint32_t *p_magic; + if (p_pool == NULL) { log_error("NULL pointer error"); return; } + if (p_node == NULL) + { + log_error("Attempt to free NULL pointer"); + return; + } + + pthread_mutex_lock(&p_pool->mutex); + // For test and debug #ifdef _DEBUG memory_pool_check_node(p_pool, p_node); #endif + /* Check for double-free using magic number at end of node */ + p_magic = (uint32_t *)((char *)p_node + p_pool->node_size - sizeof(uint32_t)); + if (*p_magic == MEMORY_POOL_MAGIC_FREE) + { + log_error("Double-free detected for node %p", p_node); + pthread_mutex_unlock(&p_pool->mutex); + return; + } + + /* Mark node as free */ + *p_magic = MEMORY_POOL_MAGIC_FREE; + memcpy(p_node, &(p_pool->p_free), sizeof(p_pool->p_free)); p_pool->p_free = p_node; (p_pool->node_count_free)++; (p_pool->node_count_allocated)--; + + pthread_mutex_unlock(&p_pool->mutex); } int memory_pool_check_node(MEMORY_POOL *p_pool, void *p_node)