summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES10
-rw-r--r--include/apr_pools.h34
-rw-r--r--memory/unix/apr_pools.c99
3 files changed, 125 insertions, 18 deletions
diff --git a/CHANGES b/CHANGES
index c6f693d8a..5be3a1b7d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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);