From: Philippe Waroquiers Date: Sat, 15 Oct 2016 12:59:04 +0000 (+0000) Subject: Clarify name and description/manual for meta mempool X-Git-Tag: svn/VALGRIND_3_13_0~339 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38fab04de9dfc3e9db51f97df8e3fb1835185138;p=thirdparty%2Fvalgrind.git Clarify name and description/manual for meta mempool * rename macro VALGRIND_CREATE_META_MEMPOOL to VALGRIND_CREATE_MEMPOOL_EXT * abort execution if a pool is marked as auto_free but is not a meta pool + removed test leak-autofreepool-3.vgtest, which now aborts. * reword/clarify valgrind.h explanations for meta pool * similarly reword/clarify the manual git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16042 --- diff --git a/include/valgrind.h b/include/valgrind.h index 20a188179c..689200739f 100644 --- a/include/valgrind.h +++ b/include/valgrind.h @@ -7009,21 +7009,37 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...) VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ pool, rzB, is_zeroed, 0, 0) -/* Create a memory pool with special flags. When the VALGRIND_MEMPOOL_AUTO_FREE - is passed, a MEMPOOL_DELETE will auto-free all chunks (so not reported as - leaks) for allocators that assume that destroying a pool destroys all - objects in the pool. When VALGRIND_MEMPOOL_METAPOOL is passed, the custom - allocator uses the pool blocks as superblocks to dole out MALLOC_LIKE blocks. - The resulting behaviour would normally be classified as overlapping blocks, - and cause assert-errors in valgrind. - These 2 MEMPOOL flags can be OR-ed together into the "flags" argument. +/* Create a memory pool with some flags specifying extended behaviour. When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL. + + The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory + associated with the pool using VALGRIND_MEMPOOL_ALLOC will be used + by the application as superblocks to dole out MALLOC_LIKE blocks using + VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels" + pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC. + The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK. + Note that the association between the pool and the second level blocks + is implicit : second level blocks will be located inside first level + blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag + for such 2 levels pools, as otherwise valgrind will detect overlapping + memory blocks, and will abort execution (e.g. during leak search). + + Such a meta pool can also be marked as an 'auto free' pool using the flag + VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the + VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE + will automatically free the second level blocks that are contained + inside the first level block freed with VALGRIND_MEMPOOL_FREE. + In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls + to VALGRIND_FREELIKE_BLOCK for all the second level blocks included + in the first level block. + Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag + without the VALGRIND_MEMPOOL_METAPOOL flag. */ #define VALGRIND_MEMPOOL_AUTO_FREE 1 #define VALGRIND_MEMPOOL_METAPOOL 2 -#define VALGRIND_CREATE_META_MEMPOOL(pool, rzB, is_zeroed, flags) \ - VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ - pool, rzB, is_zeroed, flags, 0) +#define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags) \ + VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ + pool, rzB, is_zeroed, flags, 0) /* Destroy a memory pool. */ #define VALGRIND_DESTROY_MEMPOOL(pool) \ diff --git a/memcheck/docs/mc-manual.xml b/memcheck/docs/mc-manual.xml index 57a9d7dcc4..e8e08e2586 100644 --- a/memcheck/docs/mc-manual.xml +++ b/memcheck/docs/mc-manual.xml @@ -2320,34 +2320,53 @@ inform Memcheck about changes to the state of a mempool: + - VALGRIND_CREATE_META_MEMPOOL(pool, rzB, is_zeroed, flags): - This does the same as VALGRIND_CREATE_MEMPOOL, - but allows you to specify two seldom-used options for custom - allocators (or-ed together) in the flags argument: + VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags): + Create a memory pool with some flags (that can + be OR-ed together) specifying extended behaviour. When flags is + zero, the behaviour is identical to + VALGRIND_CREATE_MEMPOOL. - - VALGRIND_MEMPOOL_AUTO_FREE. - This indicates that items allocated from this - memory pool are automatically freed when - VALGRIND_MEMPOOL_FREE - is used on a block. This allows a custom allocator to delete - (part of) a memory pool without explicitly deleting all allocated - items. Without this option, such an action will report all items - in the pool as memory leaks. + The flag VALGRIND_MEMPOOL_METAPOOL + specifies that the pieces of memory associated with the pool + using VALGRIND_MEMPOOL_ALLOC will be used + by the application as superblocks to dole out MALLOC_LIKE + blocks using VALGRIND_MALLOCLIKE_BLOCK. + In other words, a meta pool is a "2 levels" pool : first + level is the blocks described + by VALGRIND_MEMPOOL_ALLOC. The second + level blocks are described + using VALGRIND_MALLOCLIKE_BLOCK. Note + that the association between the pool and the second level + blocks is implicit : second level blocks will be located + inside first level blocks. It is necessary to use + the VALGRIND_MEMPOOL_METAPOOL flag for + such 2 levels pools, as otherwise valgrind will detect + overlapping memory blocks, and will abort execution + (e.g. during leak search). - VALGRIND_MEMPOOL_METAPOOL. - This indicates that memory that has been - marked as being allocated with - VALGRIND_MALLOCLIKE_BLOCK is used - by a custom allocator to pass out memory to an application (again - marked with VALGRIND_MALLOCLIKE_BLOCK). - Without this option, such overlapping memory blocks may trigger - a fatal error message in memcheck. + VALGRIND_MEMPOOL_AUTO_FREE. Such a meta + pool can also be marked as an 'auto free' pool using the + flag VALGRIND_MEMPOOL_AUTO_FREE, which + must be OR-ed together with + the VALGRIND_MEMPOOL_METAPOOL. For an + 'auto free' pool, VALGRIND_MEMPOOL_FREE + will automatically free the second level blocks that are + contained inside the first level block freed + with VALGRIND_MEMPOOL_FREE. In other + words, calling VALGRIND_MEMPOOL_FREE will + cause implicit calls + to VALGRIND_FREELIKE_BLOCK for all the + second level blocks included in the first level block. + Note: it is an error to use + the VALGRIND_MEMPOOL_AUTO_FREE flag + without the + VALGRIND_MEMPOOL_METAPOOL flag. diff --git a/memcheck/mc_malloc_wrappers.c b/memcheck/mc_malloc_wrappers.c index 8259401c95..f488178524 100644 --- a/memcheck/mc_malloc_wrappers.c +++ b/memcheck/mc_malloc_wrappers.c @@ -711,12 +711,17 @@ void MC_(create_mempool)(Addr pool, UInt rzB, Bool is_zeroed, { MC_Mempool* mp; - if (VG_(clo_verbosity) > 2) { + if (VG_(clo_verbosity) > 2 || (auto_free && !metapool)) { VG_(message)(Vg_UserMsg, - "create_mempool(0x%lx, rzB=%u, zeroed=%d, autofree=%d, metapool=%d)\n", - pool, rzB, is_zeroed, auto_free, metapool); + "create_mempool(0x%lx, rzB=%u, zeroed=%d," + " autofree=%d, metapool=%d)\n", + pool, rzB, is_zeroed, + auto_free, metapool); VG_(get_and_pp_StackTrace) (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH); + if (auto_free && !metapool) + VG_(tool_panic)("Inappropriate use of mempool:" + " an auto free pool must be a meta pool. Aborting\n"); } mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 02888cb4cd..b432c078ac 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -153,13 +153,11 @@ EXTRA_DIST = \ leak-pool-0.vgtest leak-pool-0.stderr.exp \ leak-pool-1.vgtest leak-pool-1.stderr.exp \ leak-pool-2.vgtest leak-pool-2.stderr.exp \ - leak-pool-3.vgtest leak-pool-3.stderr.exp \ leak-pool-4.vgtest leak-pool-4.stderr.exp \ leak-pool-5.vgtest leak-pool-5.stderr.exp \ leak-autofreepool-0.vgtest leak-autofreepool-0.stderr.exp \ leak-autofreepool-1.vgtest leak-autofreepool-1.stderr.exp \ leak-autofreepool-2.vgtest leak-autofreepool-2.stderr.exp \ - leak-autofreepool-3.vgtest leak-autofreepool-3.stderr.exp \ leak-autofreepool-4.vgtest leak-autofreepool-4.stderr.exp \ leak-autofreepool-5.vgtest leak-autofreepool-5.stderr.exp \ leak-autofreepool-6.vgtest leak-autofreepool-6.stderr.exp \ diff --git a/memcheck/tests/leak-autofreepool-3.stderr.exp b/memcheck/tests/leak-autofreepool-3.stderr.exp deleted file mode 100644 index 4178c4e263..0000000000 --- a/memcheck/tests/leak-autofreepool-3.stderr.exp +++ /dev/null @@ -1,10 +0,0 @@ - - -HEAP SUMMARY: - in use at exit: ... bytes in ... blocks - total heap usage: ... allocs, ... frees, ... bytes allocated - -All heap blocks were freed -- no leaks are possible - -For counts of detected and suppressed errors, rerun with: -v -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/memcheck/tests/leak-autofreepool-3.vgtest b/memcheck/tests/leak-autofreepool-3.vgtest deleted file mode 100644 index 46e3457870..0000000000 --- a/memcheck/tests/leak-autofreepool-3.vgtest +++ /dev/null @@ -1,4 +0,0 @@ -prog: leak-autofreepool -vgopts: --leak-check=full --show-possibly-lost=no --track-origins=yes -args: 3 -stderr_filter: filter_allocs diff --git a/memcheck/tests/leak-autofreepool.c b/memcheck/tests/leak-autofreepool.c index f918fee324..3bd6e50dc3 100644 --- a/memcheck/tests/leak-autofreepool.c +++ b/memcheck/tests/leak-autofreepool.c @@ -7,7 +7,7 @@ #include "../memcheck.h" -// Test VALGRIND_CREATE_META_MEMPOOL features, the VALGRIND_MEMPOOL_METAPOOL and +// Test VALGRIND_CREATE_MEMPOOL_EXT features, the VALGRIND_MEMPOOL_METAPOOL and // VALGRIND_MEMPOOL_AUTO_FREE flags. // Also show that without these, having a custom allocator that: // - Allocates a MEMPOOL @@ -64,7 +64,7 @@ static char MetaBlock[POOL_BLOCK_SIZE]; void create_meta_pool (void) { - VALGRIND_CREATE_META_MEMPOOL(MetaPool, 0, 0, MetaPoolFlags); + VALGRIND_CREATE_MEMPOOL_EXT(MetaPool, 0, 0, MetaPoolFlags); VALGRIND_MEMPOOL_ALLOC(MetaPool, MetaBlock, POOL_BLOCK_SIZE); MetaPool->buf = (uint8_t *) MetaBlock; @@ -124,7 +124,7 @@ static void *allocate_plain_style (struct pool *p, size_t n) static void set_flags ( int n ) { switch (n) { - // Case 0: No special flags. VALGRIND_CREATE_META_MEMPOOL is same as + // Case 0: No special flags. VALGRIND_CREATE_MEMPOOL_EXT is same as // VALGRIND_CREATE_MEMPOOL. // When mempools are destroyed, the METAPOOL leaks because auto-free is // missing. Must show 2*N (20) leaks. @@ -148,13 +148,15 @@ static void set_flags ( int n ) // Same as before, but now the MALLOCLIKE blocks are auto-freed. // Must show 0 leaks. case 2: - MetaPoolFlags = VALGRIND_MEMPOOL_AUTO_FREE | VALGRIND_MEMPOOL_METAPOOL; + MetaPoolFlags = VALGRIND_MEMPOOL_METAPOOL | VALGRIND_MEMPOOL_AUTO_FREE; CleanupBeforeExit = 1; break; - case 3: - // Just auto-free, with cleanup. The cleanup removes the overlapping - // blocks, so this is the same as case 2: No leaks, no problems. + case 3: // Note: this is incorrect behaviour, and aborts valgrind. + // (so it is not exercised during regression testing). + // Just auto-free, not marked with meta pool flag. + // This is an error, and will cause valgrind to abort when the pool + // is created. MetaPoolFlags = VALGRIND_MEMPOOL_AUTO_FREE; CleanupBeforeExit = 1; break; @@ -185,7 +187,7 @@ static void set_flags ( int n ) // already done above) is by allocating lots of other chunks that are // NOT part of the pool so the MC_Alloc lists contain other stuff. // That will make the iterator find stuff AND skip stuff. - MetaPoolFlags = VALGRIND_MEMPOOL_AUTO_FREE | VALGRIND_MEMPOOL_METAPOOL; + MetaPoolFlags = VALGRIND_MEMPOOL_METAPOOL | VALGRIND_MEMPOOL_AUTO_FREE; CleanupBeforeExit = 1; GenerateNoise = 1; break; @@ -314,9 +316,9 @@ int main( int argc, char** argv ) pool_block_size = nr_elts * sizeof(struct cell) + sizeof(uint8_t) + 1; // Create perf meta pool - VALGRIND_CREATE_META_MEMPOOL + VALGRIND_CREATE_MEMPOOL_EXT (&perf_meta_pool, 0, 0, - VALGRIND_MEMPOOL_AUTO_FREE | VALGRIND_MEMPOOL_METAPOOL); + VALGRIND_MEMPOOL_METAPOOL | VALGRIND_MEMPOOL_AUTO_FREE); perf_meta_block = malloc(pool_block_size); VALGRIND_MEMPOOL_ALLOC(&perf_meta_pool, perf_meta_block,