Make valgrind know about eina mempools.
authorrfonseca <rfonseca@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 14 Oct 2010 15:18:15 +0000 (15:18 +0000)
committerrfonseca <rfonseca@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 14 Oct 2010 15:18:15 +0000 (15:18 +0000)
Because mempools generally allocate a big memory area and distribute chunks of
that area to the users, valgrind can not know about logical invalid access. By
using some valgrind macros we can tell valgrind about mempools and which area
can be accessed or not.

To start with I have just done valgrind integration on chained mempool but soon
it will be done for one_big too.

The code below is an example on which valgrind wouldn't complain without this
patch:

@code
#include <Eina.h>

int
main(int argc, char *argv[])
{
    int i, *pool[4];
    Eina_Mempool *mp;

    eina_init();
    mp = eina_mempool_add("chained_mempool", "test", NULL, sizeof(int), 4);

    for (i = 0; i < 4; i++) {
        pool[i] = eina_mempool_malloc(mp, sizeof(int));
        *pool[i] = i;
    }

    printf("Valid mp pointer: pool[0] = %d\n", *pool[0]);
    eina_mempool_free(mp, pool[0]);
    printf("Freed mp pointer: pool[0] = %d\n", *pool[0]);

    for (i = 1; i < 4; i++)
        eina_mempool_free(mp, pool[i]);

    eina_mempool_del(mp);
    eina_shutdown();

    return 0;
}
@endcode

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@53405 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/modules/mp/chained_pool/Makefile.am
src/modules/mp/chained_pool/eina_chained_mempool.c

index 6074c6e..b0fc28f 100644 (file)
@@ -121,6 +121,32 @@ if test "x${have_magic_debug}" = "xyes" ; then
 fi
 AC_SUBST(EINA_CONFIGURE_MAGIC_DEBUG)
 
+# Valgrind
+want_valgrind="no"
+
+AC_MSG_CHECKING(whether to enable build with valgrind)
+AC_ARG_ENABLE(valgrind,
+  AC_HELP_STRING([--enable-valgrind], [enable valgrind fixes to stop false reports]),
+  [want_valgrind=$enableval]
+)
+AC_MSG_RESULT($want_valgrind)
+
+if test x$want_valgrind = "xyes"; then
+    PKG_CHECK_MODULES(VALGRIND, valgrind >= 2.4.0,
+        [
+         requirement_eina="valgrind ${requirement_eina}"
+        ],
+        [
+         AC_DEFINE(NVALGRIND, 1, [Valgrind support disabled])
+         if test "x$want_valgrind" = "xyes"; then
+            AC_MSG_ERROR([Valgrind >= 2.4.0 is required)])
+         fi
+        ]
+    )
+else
+    AC_DEFINE(NVALGRIND, 1, [Valgrind support disabled])
+fi
+
 # Safety checks (avoid crashes on wrong api usage)
 AC_ARG_ENABLE(safety-checks,
    [AC_HELP_STRING([--disable-safety-checks], [disable safety checks for NULL pointers and like. @<:@default=enabled@:>@])],
index 584fb82..e5394f3 100644 (file)
@@ -7,7 +7,8 @@ AM_CPPFLAGS = \
 -I$(top_srcdir)/src/lib \
 -I$(top_builddir)/src/lib \
 @EINA_CPPFLAGS@ \
-@EFL_EINA_BUILD@
+@EFL_EINA_BUILD@ \
+@VALGRIND_CFLAGS@
 
 if EINA_BUILD_CHAINED_POOL
 if !EINA_STATIC_BUILD_CHAINED_POOL
index 49cacc6..fac12f5 100644 (file)
 
 #include "eina_private.h"
 
+#ifndef NVALGRIND
+# include <valgrind/memcheck.h>
+#endif
+
 #ifdef DEBUG
 #include "eina_log.h"
 
@@ -94,6 +98,7 @@ _eina_chained_mp_pool_new(Chained_Mempool *pool)
 {
    Chained_Pool *p;
    unsigned char *ptr;
+   unsigned int alignof;
 
    eina_error_set(0);
    p = malloc(pool->alloc_size);
@@ -103,12 +108,18 @@ _eina_chained_mp_pool_new(Chained_Mempool *pool)
         return NULL;
      }
 
-   ptr = (unsigned char *)p + eina_mempool_alignof(sizeof(Chained_Pool));
+   alignof = eina_mempool_alignof(sizeof(Chained_Pool));
+   ptr = (unsigned char *)p + alignof;
    p->usage = 0;
    p->base = NULL;
 
    p->last = ptr;
    p->limit = ptr + pool->item_alloc * pool->pool_size;
+
+#ifndef NVALGRIND
+   VALGRIND_MAKE_MEM_NOACCESS(ptr, pool->alloc_size - alignof);
+#endif
+
    return p;
 }
 
@@ -202,6 +213,10 @@ eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size)
      }
 #endif
 
+#ifndef NVALGRIND
+   VALGRIND_MEMPOOL_ALLOC(pool, mem, pool->item_alloc);
+#endif
+
    return mem;
 }
 
@@ -231,6 +246,10 @@ eina_chained_mempool_free(void *data, void *ptr)
 #endif
 #endif
 
+#ifndef NVALGRIND
+   VALGRIND_MEMPOOL_FREE(pool, ptr);
+#endif
+
    EINA_INLIST_FOREACH(pool->first, p)
    {
       // Could the pointer be inside that pool
@@ -309,6 +328,10 @@ eina_chained_mempool_init(const char *context,
    mp->group_size = mp->item_alloc * mp->pool_size;
    mp->alloc_size = mp->group_size + eina_mempool_alignof(sizeof(Chained_Pool));
 
+#ifndef NVALGRIND
+   VALGRIND_CREATE_MEMPOOL(mp, 0, 1);
+#endif
+
 #ifdef EFL_HAVE_THREADS
 # ifdef EFL_HAVE_POSIX_THREADS
 #  ifdef EFL_DEBUG_THREADS
@@ -345,6 +368,10 @@ eina_chained_mempool_shutdown(void *data)
         _eina_chained_mp_pool_free(p);
      }
 
+#ifndef NVALGRIND
+   VALGRIND_DESTROY_MEMPOOL(mp);
+#endif
+
 #ifdef EFL_HAVE_THREADS
 # ifdef EFL_HAVE_POSIX_THREADS
 #  ifdef EFL_DEBUG_THREADS