[MLton] Crash fread(...) failed (only read 0) (Cannot allocate memory) during deepFlatten with MLton 20070826

Matthew Fluet fluet at tti-c.org
Tue Apr 22 11:12:44 PDT 2008


On Tue, 22 Apr 2008, Matthew Fluet wrote:
> On Tue, 22 Apr 2008, Nicolas Bertolotti wrote:
>>  There was actually another bug in heap.c. Here is an additional patch to
>>  fix it:
>>  --- mlton/runtime/gc/heap.c   2008-04-11 19:12:58.000000000 +0200
>>  +++ mltonp1/runtime/gc/heap.c 2008-04-22 16:24:50.000000000 +0200
>>  @@ -337,6 +337,7 @@
>>        }
>>        GC_diskBack_read (data, curHeapp->start, size);
>>        GC_diskBack_close (data);
>>  +      curHeapp->oldGenSize = size;
>>      } else {
>>        GC_diskBack_close (data);
>>        if (s->controls.messages)
>
> Yes, I was just coming to that exact conclusion.
>
>>  Unfortunately, now, I get the following error:
>>             deepFlatten starting
>>  Out of memory.  Unable to allocate 1,686,393,408 bytes.
>>
>>  ... which, I guess, is a different problem.
>
> It is a different problem, in the sense that you succeeded (at least once) in 
> writing the heap to disk, allocating a larger heap, and reading the heap from 
> disk.  Getting an out of memory error suggests that even after writing the 
> heap to disk and releasing it, the operating system was unable to mmap 1.6G. 
> That seems strange, even on a 32bit system, where the virtual address space 
> is 4G, though I suppose it could happen with sufficient fragmentation.
>
> If you compile with @MLton gc-messages --, you should get a more detailed 
> memory listing of what memory is reserved, which might indicate whether there 
> is some extra memory being held.

One thing I notice is that when writing the heap to disk, we do not 
release the card/cross maps.  Although with a 1.6G heap, these are only 
12.8M, if they happen to fall in the middle of the virtual address space, 
then it may not be possible to find the requested 1.6G heap.

You could try the attached patch, which releases the card/cross maps after 
writing the heap to disk.
-------------- next part --------------
diff --git a/runtime/gc/done.c b/runtime/gc/done.c
index a7c1774..4838b56 100644
--- a/runtime/gc/done.c
+++ b/runtime/gc/done.c
@@ -93,4 +93,11 @@ void GC_done (GC_state s) {
   }
   releaseHeap (s, &s->heap);
   releaseHeap (s, &s->secondaryHeap);
+  if (s->mutatorMarksCards) {
+    releaseCardMapAndCrossMap (s,
+                               s->generationalMaps.cardMap,
+                               s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE,
+                               s->generationalMaps.crossMap,
+                               s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE);
+  }
 }
diff --git a/runtime/gc/generational.c b/runtime/gc/generational.c
index 93124bc..f2b8f4d 100644
--- a/runtime/gc/generational.c
+++ b/runtime/gc/generational.c
@@ -147,13 +147,15 @@ void createCardMapAndCrossMap (GC_state s) {
   s->generationalMaps.crossMapLength = crossMapLength;
 
   totalMapSize = cardMapSize + crossMapSize;
-  if (DEBUG_MEM)
-    fprintf (stderr, "Creating card/cross map of size %s\n",
-             uintmaxToCommaString(totalMapSize));
   s->generationalMaps.cardMap =
     GC_mmapAnon_safe (NULL, totalMapSize);
   s->generationalMaps.crossMap =
     (s->generationalMaps.cardMap + (cardMapSize / CARD_MAP_ELEM_SIZE));
+  if (DEBUG_MEM or s->controls.messages)
+    fprintf (stderr,
+             "[GC: Created card/cross map at "FMTPTR" of size %s bytes.]\n",
+             (uintptr_t)(s->generationalMaps.cardMap),
+             uintmaxToCommaString(totalMapSize));
   if (DEBUG_CARD_MARKING)
     fprintf (stderr, "cardMap = "FMTPTR"  crossMap = "FMTPTR"\n",
              (uintptr_t)s->generationalMaps.cardMap,
@@ -163,6 +165,24 @@ void createCardMapAndCrossMap (GC_state s) {
   clearCrossMap (s);
 }
 
+void releaseCardMapAndCrossMap (GC_state s,
+                                GC_cardMap cardMap,
+                                size_t cardMapSize,
+                                __attribute__ ((unused)) GC_crossMap crossMap,
+                                size_t crossMapSize) {
+
+  size_t totalMapSize;
+
+  assert (crossMap == cardMap + (cardMapSize / CARD_MAP_ELEM_SIZE));
+  totalMapSize = cardMapSize + crossMapSize;
+  if (DEBUG_MEM or s->controls.messages)
+    fprintf (stderr,
+             "[GC: Releasing card/cross map at "FMTPTR" of size %s bytes.]\n",
+             (uintptr_t)cardMap,
+             uintmaxToCommaString(totalMapSize));
+  GC_release (cardMap, totalMapSize);
+}
+
 void resizeCardMapAndCrossMap (GC_state s) {
   if (s->mutatorMarksCards
       and (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)
@@ -180,9 +200,7 @@ void resizeCardMapAndCrossMap (GC_state s) {
     GC_memcpy ((pointer)oldCrossMap, (pointer)s->generationalMaps.crossMap,
                min (s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE,
                     oldCrossMapSize));
-    if (DEBUG_MEM)
-      fprintf (stderr, "Releasing card/cross map.\n");
-    GC_release (oldCardMap, oldCardMapSize + oldCrossMapSize);
+    releaseCardMapAndCrossMap (s, oldCardMap, oldCardMapSize, oldCrossMap, oldCrossMapSize);
   }
 }
 
diff --git a/runtime/gc/generational.h b/runtime/gc/generational.h
index 45e30a1..d16d84f 100644
--- a/runtime/gc/generational.h
+++ b/runtime/gc/generational.h
@@ -77,6 +77,9 @@ static inline pointer getCrossMapCardStart (GC_state s, pointer p);
 static inline void clearCardMap (GC_state s);
 static inline void clearCrossMap (GC_state s);
 static void createCardMapAndCrossMap (GC_state s);
+static void releaseCardMapAndCrossMap (GC_state s,
+                                       GC_cardMap cardMap, size_t cardMapSize,
+                                       GC_crossMap crossMap, size_t crossMapSize);
 static void resizeCardMapAndCrossMap (GC_state s);
 
 #if ASSERT
diff --git a/runtime/gc/heap.c b/runtime/gc/heap.c
index c042b46..365418a 100644
--- a/runtime/gc/heap.c
+++ b/runtime/gc/heap.c
@@ -337,6 +337,13 @@ copy:
     }
     data = GC_diskBack_write (orig, size);
     releaseHeap (s, curHeapp);
+    if (s->mutatorMarksCards) {
+      releaseCardMapAndCrossMap (s,
+                                 s->generationalMaps.cardMap,
+                                 s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE,
+                                 s->generationalMaps.crossMap,
+                                 s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE);
+    }
     if (createHeap (s, curHeapp, desiredSize, minSize)) {
       if (DEBUG or s->controls.messages) {
         fprintf (stderr,
@@ -347,6 +354,10 @@ copy:
       GC_diskBack_read (data, curHeapp->start, size);
       GC_diskBack_close (data);
       curHeapp->oldGenSize = size;
+      if (s->mutatorMarksCards) {
+        createCardMapAndCrossMap (s);
+        updateCrossMap (s);
+      }
     } else {
       GC_diskBack_close (data);
       if (s->controls.messages)


More information about the MLton mailing list