Index: memcheck/mc_main.c =================================================================== --- memcheck/mc_main.c (revision 5983) +++ memcheck/mc_main.c (working copy) @@ -4053,7 +4053,8 @@ && VG_USERREQ__CREATE_MEMPOOL != arg[0] && VG_USERREQ__DESTROY_MEMPOOL != arg[0] && VG_USERREQ__MEMPOOL_ALLOC != arg[0] - && VG_USERREQ__MEMPOOL_FREE != arg[0]) + && VG_USERREQ__MEMPOOL_FREE != arg[0] + && VG_USERREQ__MEMPOOL_TRIM != arg[0]) return False; switch (arg[0]) { @@ -4219,6 +4220,15 @@ return True; } + case VG_USERREQ__MEMPOOL_TRIM: { + Addr pool = (Addr)arg[1]; + Addr addr = (Addr)arg[2]; + UInt size = arg[3]; + + MC_(mempool_trim) ( pool, addr, size ); + return True; + } + default: VG_(message)(Vg_UserMsg, "Warning: unknown memcheck client request code %llx", Index: memcheck/mc_include.h =================================================================== --- memcheck/mc_include.h (revision 5983) +++ memcheck/mc_include.h (working copy) @@ -86,6 +86,7 @@ extern void MC_(mempool_alloc) ( ThreadId tid, Addr pool, Addr addr, SizeT size ); extern void MC_(mempool_free) ( Addr pool, Addr addr ); +extern void MC_(mempool_trim) ( Addr pool, Addr addr, SizeT size ); extern MC_Chunk* MC_(get_freed_list_head)( void ); Index: memcheck/mc_malloc_wrappers.c =================================================================== --- memcheck/mc_malloc_wrappers.c (revision 5983) +++ memcheck/mc_malloc_wrappers.c (working copy) @@ -469,6 +469,86 @@ die_and_free_mem ( tid, mc, mp->rzB ); } + +void MC_(mempool_trim)(Addr pool, Addr addr, SizeT size) +{ + MC_Mempool* mp; + MC_Chunk* mc; + ThreadId tid = VG_(get_running_tid)(); + UInt n_shadows, i; + VgHashNode** chunks; + + mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); + if (mp == NULL) { + MC_(record_illegal_mempool_error)(tid, pool); + return; + } + + chunks = VG_(HT_to_array) ( mp->chunks, &n_shadows ); + if (n_shadows == 0) { + tl_assert(chunks == NULL); + return; + } + + tl_assert(chunks != NULL); + for (i = 0; i < n_shadows; ++i) { + mc = (MC_Chunk*) chunks[i]; + + if (mc->size == 0) + continue; + +#define EXTENT_CONTAINS(x) ((addr <= (x)) && ((x) < addr + size)) + + if (EXTENT_CONTAINS(mc->data) && + EXTENT_CONTAINS(mc->data + mc->size - 1)) { + + /* The current chunk is entirely within the trim extent: keep + it. */ + + continue; + + } else if ( (! EXTENT_CONTAINS(mc->data)) && + (! EXTENT_CONTAINS(mc->data + mc->size - 1)) ) { + + /* The current chunk is entirely outside the trim extent: + delete it. */ + + if (VG_(HT_remove)(mp->chunks, (UWord)mc->data) == NULL) { + MC_(record_free_error)(tid, (Addr)mc->data); + VG_(free)(chunks); + return; + } + die_and_free_mem ( tid, mc, mp->rzB ); + + } else { + + /* The current chunk intersects the trim extent: remove, + trim, and reinsert it. */ + + Addr lo, hi; + tl_assert(EXTENT_CONTAINS(mc->data) || + EXTENT_CONTAINS(mc->data + mc->size - 1)); + if (VG_(HT_remove)(mp->chunks, (UWord)mc->data) == NULL) { + MC_(record_free_error)(tid, (Addr)mc->data); + VG_(free)(chunks); + return; + } + + lo = mc->data > addr ? mc->data : addr; + hi = mc->data + mc->size < addr + size ? mc->data + mc->size : addr + size; + + tl_assert(lo < hi); + mc->data = lo; + mc->size = (UInt) (hi - lo); + VG_(HT_add_node)( mp->chunks, mc ); + } + +#undef EXTENT_CONTAINS + + } + VG_(free)(chunks); +} + /*------------------------------------------------------------*/ /*--- Statistics printing ---*/ /*------------------------------------------------------------*/ Index: include/valgrind.h =================================================================== --- include/valgrind.h (revision 5983) +++ include/valgrind.h (working copy) @@ -2288,6 +2288,7 @@ VG_USERREQ__DESTROY_MEMPOOL = 0x1304, VG_USERREQ__MEMPOOL_ALLOC = 0x1305, VG_USERREQ__MEMPOOL_FREE = 0x1306, + VG_USERREQ__MEMPOOL_TRIM = 0x1307, /* Allow printfs to valgrind log. */ VG_USERREQ__PRINTF = 0x1401, @@ -2499,6 +2500,14 @@ pool, addr, 0, 0, 0); \ } +/* Disassociate any pieces outside a particular range. */ +#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ + {unsigned int _qzz_res; \ + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ + VG_USERREQ__MEMPOOL_TRIM, \ + pool, addr, size, 0, 0); \ + } + /* Mark a piece of memory as being a stack. Returns a stack id. */ #define VALGRIND_STACK_REGISTER(start, end) \ ({unsigned int _qzz_res; \