]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
event_map_maybe_GC: handle corner case that was previously simply
authorJulian Seward <jseward@acm.org>
Tue, 18 Nov 2008 23:40:00 +0000 (23:40 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 18 Nov 2008 23:40:00 +0000 (23:40 +0000)
asserted on: if all the entries in the event map are in the same
generation, then we have no LRU information at all with which to
decide which entries to discard.  So in this case throw away half of
them randomly -- there's nothing better we can do.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8783

helgrind/libhb_core.c

index 15a64c845cf35e746b3f64607103b1ccbac91e86..63f5b32f5638079e44862777d8c40d4347a9aaef 100644 (file)
@@ -3065,20 +3065,9 @@ static void event_map_maybe_GC ( void )
    }
    VG_(doneIterFM)( genMap );
 
-   if (VG_(clo_verbosity) > 1) {
-      VG_(message)(Vg_DebugMsg,
-         "libhb: EvM GC: delete generations %lu and below, "
-         "retaining %lu entries",
-         maxGen, retained );
-   }
-
    VG_(deleteFM)( genMap, NULL, NULL );
 
-   /* If this fails, it means there's only one generation in the
-      entire tree.  So we're kind of in a bad situation, and need to
-      do some stop-gap measure, such as randomly deleting half the
-      entries. */
-   tl_assert(retained < oldrefTreeN);
+   tl_assert(retained >= 0 && retained <= oldrefTreeN);
 
    /* Now make up a big list of the oldrefTree entries we want to
       delete.  We can't simultaneously traverse the tree and delete
@@ -3087,12 +3076,49 @@ static void event_map_maybe_GC ( void )
    refs2del = VG_(newXA)( HG_(zalloc), "libhb.emmG.1",
                           HG_(free), sizeof(OldRef*) );
 
-   VG_(OSetGen_ResetIter)( oldrefTree );
-   while ( (oldref = VG_(OSetGen_Next)( oldrefTree )) ) {
-      tl_assert(oldref->magic == OldRef_MAGIC);
-      if (oldref->gen <= maxGen) {
-         VG_(addToXA)( refs2del, &oldref );
+   if (retained < oldrefTreeN) {
+
+      /* This is the normal (expected) case.  We discard any ref whose
+         generation number <= maxGen. */
+      VG_(OSetGen_ResetIter)( oldrefTree );
+      while ( (oldref = VG_(OSetGen_Next)( oldrefTree )) ) {
+         tl_assert(oldref->magic == OldRef_MAGIC);
+         if (oldref->gen <= maxGen) {
+            VG_(addToXA)( refs2del, &oldref );
+         }
       }
+      if (VG_(clo_verbosity) > 1) {
+         VG_(message)(Vg_DebugMsg,
+            "libhb: EvM GC: delete generations %lu and below, "
+            "retaining %lu entries",
+            maxGen, retained );
+      }
+
+   } else {
+
+      static UInt rand_seed = 0; /* leave as static */
+
+      /* Degenerate case: there's only one generation in the entire
+         tree, so we need to have some other way of deciding which
+         refs to throw away.  Just throw out half of them randomly. */
+      tl_assert(retained == oldrefTreeN);
+      VG_(OSetGen_ResetIter)( oldrefTree );
+      while ( (oldref = VG_(OSetGen_Next)( oldrefTree )) ) {
+         UInt n;
+         tl_assert(oldref->magic == OldRef_MAGIC);
+         n = VG_(random)( &rand_seed );
+         if ((n & 0xFFF) < 0x800) {
+            VG_(addToXA)( refs2del, &oldref );
+            retained--;
+         }
+      }
+      if (VG_(clo_verbosity) > 1) {
+         VG_(message)(Vg_DebugMsg,
+            "libhb: EvM GC: randomly delete half the entries, "
+            "retaining %lu entries",
+            retained );
+      }
+
    }
 
    n2del = VG_(sizeXA)( refs2del );