apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s.@apache.org
Subject svn commit: r1438957 - in /apr/apr/trunk: CHANGES buckets/apr_buckets_alloc.c configure.in include/private/apr_support.h memory/unix/apr_pools.c
Date Sat, 26 Jan 2013 20:41:16 GMT
Author: sf
Date: Sat Jan 26 20:41:15 2013
New Revision: 1438957

URL: http://svn.apache.org/viewvc?rev=1438957&view=rev
Log:
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.


Modified:
    apr/apr/trunk/CHANGES
    apr/apr/trunk/buckets/apr_buckets_alloc.c
    apr/apr/trunk/configure.in
    apr/apr/trunk/include/private/apr_support.h
    apr/apr/trunk/memory/unix/apr_pools.c

Modified: apr/apr/trunk/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/trunk/CHANGES?rev=1438957&r1=1438956&r2=1438957&view=diff
==============================================================================
--- apr/apr/trunk/CHANGES [utf-8] (original)
+++ apr/apr/trunk/CHANGES [utf-8] Sat Jan 26 20:41:15 2013
@@ -1,6 +1,9 @@
                                                      -*- coding: utf-8 -*-
 Changes for APR 2.0.0
 
+  *) Add support code to teach valgrind about APR pools, allocators, and
+     bucket allocators. [Stefan Fritsch]
+
   *) Fix apr_ipsubnet_test() false positives when comparing IPv4
      subnet representation against an IPv6 address.  PR 54047.  [Joe Orton]
 

Modified: apr/apr/trunk/buckets/apr_buckets_alloc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/buckets/apr_buckets_alloc.c?rev=1438957&r1=1438956&r2=1438957&view=diff
==============================================================================
--- apr/apr/trunk/buckets/apr_buckets_alloc.c (original)
+++ apr/apr/trunk/buckets/apr_buckets_alloc.c Sat Jan 26 20:41:15 2013
@@ -18,6 +18,7 @@
 
 #include "apr_buckets.h"
 #include "apr_allocator.h"
+#include "apr_support.h"
 
 #define ALLOC_AMT (8192 - APR_MEMNODE_T_SIZE)
 
@@ -102,7 +103,8 @@ APR_DECLARE_NONSTD(apr_bucket_alloc_t *)
     list->freelist = NULL;
     list->blocks = block;
     block->first_avail += APR_ALIGN_DEFAULT(sizeof(*list));
-
+    APR_VALGRIND_NOACCESS(block->first_avail,
+                          block->endp - block->first_avail);
     return list;
 }
 
@@ -121,18 +123,21 @@ APR_DECLARE_NONSTD(void) apr_bucket_allo
 #endif
 }
 
-APR_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size, 
+APR_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t in_size,
                                             apr_bucket_alloc_t *list)
 {
     node_header_t *node;
     apr_memnode_t *active = list->blocks;
     char *endp;
+    apr_size_t size;
 
-    size += SIZEOF_NODE_HEADER_T;
+    size = in_size + SIZEOF_NODE_HEADER_T;
     if (size <= SMALL_NODE_SIZE) {
         if (list->freelist) {
             node = list->freelist;
             list->freelist = node->next;
+            APR_VALGRIND_UNDEFINED((char *)node + SIZEOF_NODE_HEADER_T,
+                                   SMALL_NODE_SIZE - SIZEOF_NODE_HEADER_T);
         }
         else {
             endp = active->first_avail + SMALL_NODE_SIZE;
@@ -144,8 +149,11 @@ APR_DECLARE_NONSTD(void *) apr_bucket_al
                 list->blocks->next = active;
                 active = list->blocks;
                 endp = active->first_avail + SMALL_NODE_SIZE;
+                APR_VALGRIND_NOACCESS(active->first_avail,
+                                      active->endp - active->first_avail);
             }
             node = (node_header_t *)active->first_avail;
+            APR_VALGRIND_UNDEFINED(node, SMALL_NODE_SIZE);
             node->alloc = list;
             node->memnode = active;
             node->size = SMALL_NODE_SIZE;
@@ -194,6 +202,7 @@ APR_DECLARE_NONSTD(void) apr_bucket_free
         check_not_already_free(node);
         node->next = list->freelist;
         list->freelist = node;
+        APR_VALGRIND_NOACCESS(mem, SMALL_NODE_SIZE - SIZEOF_NODE_HEADER_T);
     }
     else {
         apr_allocator_free(list->allocator, node->memnode);

Modified: apr/apr/trunk/configure.in
URL: http://svn.apache.org/viewvc/apr/apr/trunk/configure.in?rev=1438957&r1=1438956&r2=1438957&view=diff
==============================================================================
--- apr/apr/trunk/configure.in (original)
+++ apr/apr/trunk/configure.in Sat Jan 26 20:41:15 2013
@@ -839,6 +839,22 @@ AC_ARG_WITH(efence, 
                  [ AC_MSG_ERROR(Electric Fence requested but not detected) ])
   ])
 
+AC_ARG_WITH(valgrind,
+  [  --with-valgrind[[=DIR]]   Enable code to teach valgrind about apr pools
+                          (optionally: set path to valgrind headers) ],
+  [ if test "$withval" != no; then
+      if test "$withval" = yes; then
+        withval=/usr/include/valgrind
+      fi
+      APR_ADDTO(CPPFLAGS, -I$withval)
+      AC_CHECK_HEADERS(valgrind.h memcheck.h)
+      APR_IFALLYES(header:valgrind.h header:memcheck.h,
+        [AC_DEFINE(HAVE_VALGRIND, 1, [Compile in valgrind support]) ],
+        [AC_MSG_ERROR(valgrind headers not found) ]
+      )
+    fi ]
+)
+
 AC_CHECK_FUNCS(sigsuspend, [ have_sigsuspend="1" ], [ have_sigsuspend="0" ])
 AC_CHECK_FUNCS(sigwait, [ have_sigwait="1" ], [ have_sigwait="0" ]) 
 dnl AC_CHECK_FUNCS doesn't work for this on Tru64 since the function

Modified: apr/apr/trunk/include/private/apr_support.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/private/apr_support.h?rev=1438957&r1=1438956&r2=1438957&view=diff
==============================================================================
--- apr/apr/trunk/include/private/apr_support.h (original)
+++ apr/apr/trunk/include/private/apr_support.h Sat Jan 26 20:41:15 2013
@@ -25,6 +25,26 @@
 #include "apr.h"
 #include "apr_network_io.h"
 #include "apr_file_io.h"
+#include "apr_private.h"
+
+#if HAVE_VALGRIND
+#include <valgrind.h>
+#include <memcheck.h>
+
+extern int apr_running_on_valgrind;
+
+#define APR_IF_VALGRIND(x)                                      \
+    do { if (apr_running_on_valgrind) { x; } } while (0)
+
+#else
+#define APR_IF_VALGRIND(x)
+#endif /* HAVE_VALGRIND */
+
+#define APR_VALGRIND_NOACCESS(addr_, size_)                     \
+    APR_IF_VALGRIND(VALGRIND_MAKE_MEM_NOACCESS(addr_, size_))
+#define APR_VALGRIND_UNDEFINED(addr_, size_)                    \
+    APR_IF_VALGRIND(VALGRIND_MAKE_MEM_UNDEFINED(addr_, size_))
+
 
 #ifdef __cplusplus
 extern "C" {

Modified: apr/apr/trunk/memory/unix/apr_pools.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/memory/unix/apr_pools.c?rev=1438957&r1=1438956&r2=1438957&view=diff
==============================================================================
--- apr/apr/trunk/memory/unix/apr_pools.c (original)
+++ apr/apr/trunk/memory/unix/apr_pools.c Sat Jan 26 20:41:15 2013
@@ -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_alloc
                 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_alloc
                 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_alloc
 #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 *all
         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_initi
     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_
     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_
     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_
     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_
     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_poo
     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_p
     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_creat
     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
         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
     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_po
      */
     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;
 }
 



Mime
View raw message