diff options
author | Stefan Fritsch <sf@apache.org> | 2013-01-26 20:41:15 +0000 |
---|---|---|
committer | Stefan Fritsch <sf@apache.org> | 2013-01-26 20:41:15 +0000 |
commit | 0f9bec1ff8867743822886253e3e0a94a706714e (patch) | |
tree | 41f9d0959c73d69c03934f89c50bfc485ac146aa /memory | |
parent | 9257d6c7a193f152b17448304ef2de9ae6db5a3f (diff) | |
download | apr-0f9bec1ff8867743822886253e3e0a94a706714e.tar.gz |
Add valgrind support
Teach valgrind about apr pools, allocators, and bucket allocators
if --with-valgrind is passed to configure.
This has less impact on program behavior and performance than compiling
with complete pool-debugging. Even with valgrind support compiled in,
the performance impact if not running under valgrind should be minimal.
It may make sense to use pool-debugging together with valgrind support
because pool-debugging does not help with allocators and bucket
allocators.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1438957 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'memory')
-rw-r--r-- | memory/unix/apr_pools.c | 145 |
1 files changed, 126 insertions, 19 deletions
diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c index d6af9b210..9bbfd32ac 100644 --- a/memory/unix/apr_pools.c +++ b/memory/unix/apr_pools.c @@ -27,6 +27,7 @@ #include "apr_thread_mutex.h" #include "apr_hash.h" #include "apr_time.h" +#include "apr_support.h" #define APR_WANT_MEMFUNC #include "apr_want.h" #include "apr_env.h" @@ -43,6 +44,11 @@ #include <sys/mman.h> #endif +#if HAVE_VALGRIND +#define REDZONE APR_ALIGN_DEFAULT(8) +int apr_running_on_valgrind = 0; +#endif + /* * Magic numbers */ @@ -287,10 +293,7 @@ apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size) apr_thread_mutex_unlock(allocator->mutex); #endif /* APR_HAS_THREADS */ - node->next = NULL; - node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; - - return node; + goto have_node; } #if APR_HAS_THREADS @@ -327,10 +330,7 @@ apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size) apr_thread_mutex_unlock(allocator->mutex); #endif /* APR_HAS_THREADS */ - node->next = NULL; - node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; - - return node; + goto have_node; } #if APR_HAS_THREADS @@ -350,11 +350,15 @@ apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size) #endif return NULL; - node->next = NULL; node->index = index; - node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; node->endp = (char *)node + size; +have_node: + node->next = NULL; + node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; + + APR_VALGRIND_UNDEFINED(node->first_avail, size - APR_MEMNODE_T_SIZE); + return node; } @@ -381,6 +385,9 @@ void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node) next = node->next; index = node->index; + APR_VALGRIND_NOACCESS((char *)node + APR_MEMNODE_T_SIZE, + (node->index+1) << BOUNDARY_INDEX); + if (max_free_index != APR_ALLOCATOR_MAX_FREE_UNLIMITED && index + 1 > current_free_index) { node->next = freelist; @@ -576,6 +583,10 @@ APR_DECLARE(apr_status_t) apr_pool_initialize(void) if (apr_pools_initialized++) return APR_SUCCESS; +#if HAVE_VALGRIND + apr_running_on_valgrind = RUNNING_ON_VALGRIND; +#endif + #if APR_ALLOCATOR_USES_MMAP && defined(_SC_PAGESIZE) boundary_size = sysconf(_SC_PAGESIZE); boundary_index = 12; @@ -672,6 +683,10 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) apr_size_t size, free_index; size = APR_ALIGN_DEFAULT(in_size); +#if HAVE_VALGRIND + if (apr_running_on_valgrind) + size += 2 * REDZONE; +#endif if (size < in_size) { if (pool->abort_fn) pool->abort_fn(APR_ENOMEM); @@ -684,8 +699,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) if (size <= node_free_space(active)) { mem = active->first_avail; active->first_avail += size; - - return mem; + goto have_mem; } node = active->next; @@ -716,7 +730,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) active->free_index = free_index; node = active->next; if (free_index >= node->free_index) - return mem; + goto have_mem; do { node = node->next; @@ -726,7 +740,19 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t in_size) list_remove(active); list_insert(active, node); +have_mem: +#if HAVE_VALGRIND + if (!apr_running_on_valgrind) { + return mem; + } + else { + mem = (char *)mem + REDZONE; + VALGRIND_MEMPOOL_ALLOC(pool, mem, in_size); + return mem; + } +#else return mem; +#endif } /* Provide an implementation of apr_pcalloc for backward compatibility @@ -786,6 +812,8 @@ APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) active = pool->active = pool->self; active->first_avail = pool->self_first_avail; + APR_IF_VALGRIND(VALGRIND_MEMPOOL_TRIM(pool, pool, 1)); + if (active->next == active) return; @@ -863,6 +891,7 @@ APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) if (apr_allocator_owner_get(allocator) == pool) { apr_allocator_destroy(allocator); } + APR_IF_VALGRIND(VALGRIND_DESTROY_MEMPOOL(pool)); } APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, @@ -899,8 +928,23 @@ APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, node->next = node; node->ref = &node->next; +#if HAVE_VALGRIND + if (!apr_running_on_valgrind) { + pool = (apr_pool_t *)node->first_avail; + pool->self_first_avail = (char *)pool + SIZEOF_POOL_T; + } + else { + pool = (apr_pool_t *)(node->first_avail + REDZONE); + pool->self_first_avail = (char *)pool + SIZEOF_POOL_T + 2 * REDZONE; + VALGRIND_MAKE_MEM_NOACCESS(pool->self_first_avail, + node->endp - pool->self_first_avail); + VALGRIND_CREATE_MEMPOOL(pool, REDZONE, 0); + } +#else pool = (apr_pool_t *)node->first_avail; - node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T; + pool->self_first_avail = (char *)pool + SIZEOF_POOL_T; +#endif + node->first_avail = pool->self_first_avail; pool->allocator = allocator; pool->active = pool->self = node; @@ -1117,7 +1161,11 @@ static int psprintf_flush(apr_vformatter_buff_t *vbuff) ps->got_a_new_node = 1; } + APR_VALGRIND_UNDEFINED(node->first_avail, + node->endp - node->first_avail); memcpy(node->first_avail, active->first_avail, cur_len); + APR_VALGRIND_NOACCESS(active->first_avail, + active->endp - active->first_avail); ps->node = node; ps->vbuff.curpos = node->first_avail + cur_len; @@ -1126,6 +1174,35 @@ static int psprintf_flush(apr_vformatter_buff_t *vbuff) return 0; } +#if HAVE_VALGRIND +static int add_redzone(int (*flush_func)(apr_vformatter_buff_t *b), + struct psprintf_data *ps) +{ + apr_size_t len = ps->vbuff.curpos - ps->node->first_avail + REDZONE; + + while (ps->vbuff.curpos - ps->node->first_avail < len) { + if (ps->vbuff.endpos - ps->node->first_avail >= len) + ps->vbuff.curpos = ps->node->first_avail + len; + else + ps->vbuff.curpos = ps->vbuff.endpos; + + /* + * Prevent valgrind from complaining when psprintf_flush() + * does a memcpy(). The VALGRIND_MEMPOOL_ALLOC() will reset + * the redzone to NOACCESS. + */ + if (ps->vbuff.curpos != ps->node->first_avail) + VALGRIND_MAKE_MEM_DEFINED(ps->node->first_avail, + ps->vbuff.curpos - ps->node->first_avail); + if (ps->vbuff.curpos == ps->vbuff.endpos) { + if (psprintf_flush(&ps->vbuff) == -1) + return -1; + } + } + return 0; +} +#endif + APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) { struct psprintf_data ps; @@ -1148,18 +1225,46 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) */ if (ps.node->first_avail == ps.node->endp) { if (psprintf_flush(&ps.vbuff) == -1) - goto error; + goto error; + } +#if HAVE_VALGRIND + if (apr_running_on_valgrind) { + if (add_redzone(psprintf_flush, &ps) == -1) + goto error; + if (!ps.got_a_new_node) { + /* psprintf_flush() has not been called, allow access to our node */ + VALGRIND_MAKE_MEM_UNDEFINED(ps.vbuff.curpos, + ps.node->endp - ps.vbuff.curpos); + } } +#endif /* HAVE_VALGRIND */ if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) goto error; - strp = ps.vbuff.curpos; - *strp++ = '\0'; + *ps.vbuff.curpos++ = '\0'; - size = strp - ps.node->first_avail; - size = APR_ALIGN_DEFAULT(size); +#if HAVE_VALGRIND + if (!apr_running_on_valgrind) { + strp = ps.node->first_avail; + } + else { + if (add_redzone(psprintf_flush, &ps) == -1) + goto error; + if (ps.node->endp != ps.vbuff.curpos) + APR_VALGRIND_NOACCESS(ps.vbuff.curpos, + ps.node->endp - ps.vbuff.curpos); + strp = ps.node->first_avail + REDZONE; + size = ps.vbuff.curpos - strp; + VALGRIND_MEMPOOL_ALLOC(pool, strp, size); + VALGRIND_MAKE_MEM_DEFINED(strp, size); + } +#else strp = ps.node->first_avail; +#endif + + size = ps.vbuff.curpos - ps.node->first_avail; + size = APR_ALIGN_DEFAULT(size); ps.node->first_avail += size; if (ps.free) @@ -1206,6 +1311,8 @@ error: ps.node->next = ps.free; allocator_free(pool->allocator, ps.node); } + APR_VALGRIND_NOACCESS(pool->active->first_avail, + pool->active->endp - pool->active->first_avail); return NULL; } |