include/apr_pools.h | 14 ++++++++++ memory/unix/apr_pools.c | 64 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/include/apr_pools.h b/include/apr_pools.h index 7ae1ed6..db2bb51 100644 --- a/include/apr_pools.h +++ b/include/apr_pools.h @@ -512,6 +512,19 @@ APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b); */ APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag); +#include "apr_thread_mutex.h" + +#if APR_HAS_THREADS +/** + * Add a mutex to a pool to make it suitable to use from multiple threads. + * @param pool The pool to add the mutex to + * @param mutex The mutex + * @remark The mutex does not protect the destroy operation just the low level allocs. + */ +APR_DECLARE(void) apr_pool_mutex_set(apr_pool_t *pool, + apr_thread_mutex_t *mutex); +#endif + /* * User data management @@ -536,6 +549,7 @@ APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag); * key names is a typical way to help ensure this uniqueness. * */ + APR_DECLARE(apr_status_t) apr_pool_userdata_set( const void *data, const char *key, diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c index 9ac3977..154ac42 100644 --- a/memory/unix/apr_pools.c +++ b/memory/unix/apr_pools.c @@ -504,7 +504,9 @@ struct apr_pool_t { apr_abortfunc_t abort_fn; apr_hash_t *user_data; const char *tag; - +#if APR_HAS_THREADS + apr_thread_mutex_t *user_mutex; +#endif #if !APR_POOL_DEBUG apr_memnode_t *active; apr_memnode_t *self; /* The node containing the pool itself */ @@ -526,6 +528,7 @@ struct apr_pool_t { #endif /* APR_POOL_DEBUG */ #ifdef NETWARE apr_os_proc_t owner_proc; + #endif /* defined(NETWARE) */ cleanup_t *pre_cleanups; }; @@ -663,9 +666,12 @@ APR_DECLARE(void) apr_pool_terminate(void) APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) { apr_memnode_t *active, *node; - void *mem; + void *mem = NULL; apr_size_t size, free_index; +#if APR_HAS_THREADS + if (pool->user_mutex) apr_thread_mutex_lock(pool->user_mutex); +#endif size = APR_ALIGN_DEFAULT(in_size); if (size < in_size) { if (pool->abort_fn) @@ -680,7 +686,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) mem = active->first_avail; active->first_avail += size; - return mem; + goto end; } node = active->next; @@ -692,7 +698,8 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) if (pool->abort_fn) pool->abort_fn(APR_ENOMEM); - return NULL; + mem = NULL; + goto end; } } @@ -711,7 +718,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) active->free_index = (APR_UINT32_TRUNC_CAST)free_index; node = active->next; if (free_index >= node->free_index) - return mem; + goto end; do { node = node->next; @@ -721,6 +728,10 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) list_remove(active); list_insert(active, node); + end: +#if APR_HAS_THREADS + if (pool->user_mutex) apr_thread_mutex_unlock(pool->user_mutex); +#endif return mem; } @@ -753,6 +764,10 @@ APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) { apr_memnode_t *active; +#if APR_HAS_THREADS + if (pool->user_mutex) apr_thread_mutex_lock(pool->user_mutex); +#endif + /* Run pre destroy cleanups */ run_cleanups(&pool->pre_cleanups); pool->pre_cleanups = NULL; @@ -782,14 +797,27 @@ APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) active->first_avail = pool->self_first_avail; if (active->next == active) - return; + goto end; *active->ref = NULL; allocator_free(pool->allocator, active->next); active->next = active; active->ref = &active->next; + + end: +#if APR_HAS_THREADS + if (pool->user_mutex) apr_thread_mutex_unlock(pool->user_mutex); +#endif } +#if APR_HAS_THREADS +APR_DECLARE(void) apr_pool_mutex_set(apr_pool_t *pool, + apr_thread_mutex_t *mutex) +{ + pool->user_mutex = mutex; +} +#endif + APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) { apr_memnode_t *active; @@ -907,7 +935,9 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, pool->subprocesses = NULL; pool->user_data = NULL; pool->tag = NULL; - +#if APR_HAS_THREADS + pool->user_mutex = NULL; +#endif #ifdef NETWARE pool->owner_proc = (apr_os_proc_t)getnlmhandle(); #endif /* defined(NETWARE) */ @@ -1117,6 +1147,10 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) apr_memnode_t *active, *node; apr_size_t free_index; +#if APR_HAS_THREADS + if (pool->user_mutex) apr_thread_mutex_lock(pool->user_mutex); +#endif + ps.node = active = pool->active; ps.pool = pool; ps.vbuff.curpos = ps.node->first_avail; @@ -1135,7 +1169,8 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) pool->abort_fn(APR_ENOMEM); } - return NULL; + strp = NULL; + goto end; } } @@ -1143,7 +1178,8 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) if (pool->abort_fn) pool->abort_fn(APR_ENOMEM); - return NULL; + strp = NULL; + goto end; } strp = ps.vbuff.curpos; @@ -1161,7 +1197,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) * Link the node in if it's a new one */ if (!ps.got_a_new_node) - return strp; + goto end; active = pool->active; node = ps.node; @@ -1179,7 +1215,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) node = active->next; if (free_index >= node->free_index) - return strp; + goto end; do { node = node->next; @@ -1189,6 +1225,12 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) list_remove(active); list_insert(active, node); + end: + +#if APR_HAS_THREADS + if (pool->user_mutex) apr_thread_mutex_unlock(pool->user_mutex); +#endif + return strp; }