]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a mempool-trimming client request (Graydon Hoare).
authorJulian Seward <jseward@acm.org>
Fri, 28 Jul 2006 00:06:37 +0000 (00:06 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 28 Jul 2006 00:06:37 +0000 (00:06 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5992

include/valgrind.h
memcheck/mc_include.h
memcheck/mc_main.c
memcheck/mc_malloc_wrappers.c

index a0dce038463c9ca7f04a56ff17f1a750c9475754..266e03fea3a4db0246535a60e28ce566c2ee417a 100644 (file)
@@ -2288,6 +2288,7 @@ typedef
           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 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
                                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;                                       \
index 36dc3ead6c1694e258a8d5ddd63ecc612579e2ae..4fa50d2433d9be95cb6368f7f325685b18ffd61b 100644 (file)
@@ -86,6 +86,7 @@ extern void MC_(destroy_mempool) ( Addr pool );
 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 0e3096f98cb4c425fe86044736b3f2dcd73c5187..026356b670bf52b445c980f5bc3a89950d0459bf 100644 (file)
@@ -4053,7 +4053,8 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
     && 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 @@ static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
          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 657901299907f995296a0c87d2aa24026612952b..736bc01d1cdff182bc7e5e1f2a7f93e2da0fdbe7 100644 (file)
@@ -469,6 +469,86 @@ void MC_(mempool_free)(Addr pool, Addr addr)
    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                                  ---*/
 /*------------------------------------------------------------*/