diff options
-rw-r--r-- | CHANGES | 10 | ||||
-rw-r--r-- | include/apr_pools.h | 34 | ||||
-rw-r--r-- | memory/unix/apr_pools.c | 99 |
3 files changed, 125 insertions, 18 deletions
@@ -1,6 +1,16 @@ -*- coding: utf-8 -*- Changes for APR 1.3.0 + *) Introduce apr_pool_sys_allocator_set() for registering + application provided memory allocation functions that + will APR use internally whenever malloc/free is needed. + This allows to use custom memory allocators insted + sustem default malloc/free. This is one time initialization + function and must be used before any oter APR call. + After the first allocation function is called those + callbacks cannot be changed. + [Mladen Turk] + *) Introduce apr_pool_pre_cleanup_register() for registering a cleanup that is called before any subpool is destroyed within apr_pool_clear or apr_pool_destroy. diff --git a/include/apr_pools.h b/include/apr_pools.h index de0ba3b8e..a3cd4c19e 100644 --- a/include/apr_pools.h +++ b/include/apr_pools.h @@ -149,6 +149,40 @@ typedef int (*apr_abortfunc_t)(int retcode); * Initialization */ +/** A function that allocates memory from the system. */ +typedef void* (*apr_sys_alloc_t)(apr_size_t size, void *data); + +/** A function that allocates memory from the system. */ +typedef void* (*apr_sys_realloc_t)(void *mem, apr_size_t new_size, void *data); + +/** A function that frees memory. */ +typedef void (*apr_sys_free_t)(void *memory, void *data); + +/** + * Setup system memory alloc and free functions. + * + * If set APR will use those functions whenever it internally + * needs to allocate or free the memory. + * + * @param alloc_fn A function to use for allocating memory. + * @param alloc_data The data to pass to the alloc function. + * @param realloc_fn A function to use for reallocating memory. + * @param realloc_data The data to pass to the realloc function. + * @param free_fn A function to use for freeing memory. + * @param free_data The data to pass to the free function. + * @return APR_EINVAL if one of the functions is not provided. + * APR_EINIT if apr_pool_initialize was already called. + * @remark This function MUST be called before pool initializtion. + * If application don't set those functions the system + * will use malloc/realloc/free instead. + */ +APR_DECLARE(apr_status_t) apr_pool_sys_allocator_set(apr_sys_alloc_t alloc_fn, + void *alloc_data, + apr_sys_realloc_t realloc_fn, + void *realloc_data, + apr_sys_free_t free_fn, + void *free_data); + /** * Setup all of the internal structures required to use pools * @remark Programs do NOT need to call this directly. APR will call this diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c index 1276b2e92..04c239900 100644 --- a/memory/unix/apr_pools.c +++ b/memory/unix/apr_pools.c @@ -100,6 +100,44 @@ struct apr_allocator_t { #define SIZEOF_ALLOCATOR_T APR_ALIGN_DEFAULT(sizeof(apr_allocator_t)) +/* Global system allocator functions */ +static apr_sys_alloc_t global_allocfn = NULL; +static apr_sys_realloc_t global_reallocfn = NULL; +static apr_sys_free_t global_freefn = NULL; +static void *global_allocdata = NULL; +static void *global_reallocdata = NULL; +static void *global_freedata = NULL; + +/* + * System memory allocator + */ + +static APR_INLINE +void *APR_MALLOC(apr_size_t size) +{ + if (global_allocfn) + return (*global_allocfn)(size, global_allocdata); + else + return malloc(size); +} + +static APR_INLINE +void APR_FREE(void *mem) +{ + if (global_freefn) + (*global_freefn)(mem, global_freedata); + else + free(mem); +} + +static APR_INLINE +void *APR_REALLOC(void *mem, apr_size_t new_size) +{ + if (global_reallocfn) + return (*global_reallocfn)(mem, new_size, global_reallocdata); + else + return realloc(mem, new_size); +} /* * Allocator @@ -111,7 +149,7 @@ APR_DECLARE(apr_status_t) apr_allocator_create(apr_allocator_t **allocator) *allocator = NULL; - if ((new_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL) + if ((new_allocator = APR_MALLOC(SIZEOF_ALLOCATOR_T)) == NULL) return APR_ENOMEM; memset(new_allocator, 0, SIZEOF_ALLOCATOR_T); @@ -131,11 +169,11 @@ APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator) ref = &allocator->free[index]; while ((node = *ref) != NULL) { *ref = node->next; - free(node); + APR_FREE(node); } } - free(allocator); + APR_FREE(allocator); } #if APR_HAS_THREADS @@ -320,7 +358,7 @@ apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t size) /* If we haven't got a suitable node, malloc a new one * and initialize it. */ - if ((node = malloc(size)) == NULL) + if ((node = APR_MALLOC(size)) == NULL) return NULL; node->next = NULL; @@ -397,7 +435,7 @@ void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node) while (freelist != NULL) { node = freelist; freelist = node->next; - free(node); + APR_FREE(node); } } @@ -523,6 +561,31 @@ static apr_allocator_t *global_allocator = NULL; static apr_file_t *file_stderr = NULL; #endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ +APR_DECLARE(apr_status_t) apr_pool_sys_allocator_set(apr_sys_alloc_t alloc_fn, + void *alloc_data, + apr_sys_realloc_t realloc_fn, + void *realloc_data, + apr_sys_free_t free_fn, + void *free_data) +{ + if (apr_pools_initialized) { + /* We cannot intermix memory allocation functions */ + return APR_EINIT; + } + if (alloc_fn && realloc_fn && free_fn) { + global_allocfn = alloc_fn; + global_reallocfn = realloc_fn; + global_freefn = free_fn; + global_allocdata = alloc_data; + global_reallocdata = realloc_data; + global_freedata = free_data; + + return APR_SUCCESS; + } + else + return APR_EINVAL; +} + /* * Local functions */ @@ -920,7 +983,7 @@ APR_DECLARE(apr_status_t) apr_pool_create_core_ex(apr_pool_t **newpool, if (!apr_pools_initialized) return APR_ENOPOOL; if ((pool_allocator = allocator) == NULL) { - if ((pool_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL) { + if ((pool_allocator = APR_MALLOC(SIZEOF_ALLOCATOR_T)) == NULL) { if (abort_fn) abort_fn(APR_ENOMEM); @@ -1405,7 +1468,7 @@ static void *pool_alloc(apr_pool_t *pool, apr_size_t size) debug_node_t *node; void *mem; - if ((mem = malloc(size)) == NULL) { + if ((mem = APR_MALLOC(size)) == NULL) { if (pool->abort_fn) pool->abort_fn(APR_ENOMEM); @@ -1414,7 +1477,7 @@ static void *pool_alloc(apr_pool_t *pool, apr_size_t size) node = pool->nodes; if (node == NULL || node->index == 64) { - if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) { + if ((node = APR_MALLOC(SIZEOF_DEBUG_NODE_T)) == NULL) { if (pool->abort_fn) pool->abort_fn(APR_ENOMEM); @@ -1518,11 +1581,11 @@ static void pool_clear_debug(apr_pool_t *pool, const char *file_line) for (index = 0; index < node->index; index++) { memset(node->beginp[index], POOL_POISON_BYTE, (char *)node->endp[index] - (char *)node->beginp[index]); - free(node->beginp[index]); + APR_FREE(node->beginp[index]); } memset(node, POOL_POISON_BYTE, SIZEOF_DEBUG_NODE_T); - free(node); + APR_FREE(node); } pool->stat_alloc = 0; @@ -1606,7 +1669,7 @@ static void pool_destroy_debug(apr_pool_t *pool, const char *file_line) } /* Free the pool itself */ - free(pool); + APR_FREE(pool); } APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *pool, @@ -1648,7 +1711,7 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, if (!abort_fn && parent) abort_fn = parent->abort_fn; - if ((pool = malloc(SIZEOF_POOL_T)) == NULL) { + if ((pool = APR_MALLOC(SIZEOF_POOL_T)) == NULL) { if (abort_fn) abort_fn(APR_ENOMEM); @@ -1705,7 +1768,7 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, */ if ((rv = apr_thread_mutex_create(&pool->mutex, APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) { - free(pool); + APR_FREE(pool); return rv; } #endif /* APR_HAS_THREADS */ @@ -1736,7 +1799,7 @@ APR_DECLARE(apr_status_t) apr_pool_create_core_ex_debug(apr_pool_t **newpool, *newpool = NULL; - if ((pool = malloc(SIZEOF_POOL_T)) == NULL) { + if ((pool = APR_MALLOC(SIZEOF_POOL_T)) == NULL) { if (abort_fn) abort_fn(APR_ENOMEM); @@ -1781,7 +1844,7 @@ APR_DECLARE(apr_status_t) apr_pool_create_core_ex_debug(apr_pool_t **newpool, */ if ((rv = apr_thread_mutex_create(&pool->mutex, APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) { - free(pool); + APR_FREE(pool); return rv; } #endif /* APR_HAS_THREADS */ @@ -1814,7 +1877,7 @@ static int psprintf_flush(apr_vformatter_buff_t *vbuff) size = ps->vbuff.curpos - ps->mem; ps->size <<= 1; - if ((ps->mem = realloc(ps->mem, ps->size)) == NULL) + if ((ps->mem = APR_REALLOC(ps->mem, ps->size)) == NULL) return -1; ps->vbuff.curpos = ps->mem + size; @@ -1831,7 +1894,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) apr_pool_check_integrity(pool); ps.size = 64; - ps.mem = malloc(ps.size); + ps.mem = APR_MALLOC(ps.size); ps.vbuff.curpos = ps.mem; /* Save a byte for the NUL terminator */ @@ -1851,7 +1914,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) */ node = pool->nodes; if (node == NULL || node->index == 64) { - if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) { + if ((node = APR_MALLOC(SIZEOF_DEBUG_NODE_T)) == NULL) { if (pool->abort_fn) pool->abort_fn(APR_ENOMEM); |