Hi all

Attached is a patch to libgc that will allow it to actually unmap memory
when USE_MUNMAP is defined.  Currently, the unmap code just sets the
mmap flags on a region to 'no access'.  The patch unlinks blocks from
the gc free list larger than a defined min size (currently 4k bytes),
that haven't been used for several collections, and unmaps the memory.

It may or may not fix https://bugzilla.novell.com/show_bug.cgi?id=495486
- the reporter forgot to attach his test case.

Comments?

- Dick

Index: include/private/gc_priv.h
===================================================================
--- include/private/gc_priv.h	(revision 137556)
+++ include/private/gc_priv.h	(working copy)
@@ -253,6 +253,8 @@
 			   /* the block risks unreasonable immediate	 */
 			   /* heap growth.				 */
 
+# define REALLY_FREE_MIN 4096
+
 /*********************************/
 /*                               */
 /* Stack saving for debugging	 */
@@ -908,6 +910,7 @@
 # endif
 # ifdef USE_MUNMAP
     word _unmapped_bytes;
+    word _really_unmapped_bytes;
 # endif
 # ifdef MERGE_SIZES
     unsigned _size_map[WORDS_TO_BYTES(MAXOBJSZ+1)];
@@ -1054,6 +1057,7 @@
 # define GC_last_stack GC_arrays._last_stack
 # ifdef USE_MUNMAP
 #   define GC_unmapped_bytes GC_arrays._unmapped_bytes
+#   define GC_really_unmapped_bytes GC_arrays._really_unmapped_bytes
 # endif
 # if defined(MSWIN32) || defined(MSWINCE)
 #   define GC_heap_bases GC_arrays._heap_bases
@@ -1780,6 +1784,7 @@
   void GC_unmap(ptr_t start, word bytes);
   void GC_remap(ptr_t start, word bytes);
   void GC_unmap_gap(ptr_t start1, word bytes1, ptr_t start2, word bytes2);
+  void GC_really_unmap(ptr_t start, word bytes);
 #endif
 
 /* Virtual dirty bit implementation:		*/
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 137556)
+++ ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2009-08-13  Dick Porter  <dpor...@codicesoftware.com>
+
+	* include/private/gc_priv.h, allchblk.c, os_dep.c: Cause libgc to
+	return unused memory to the system in some cases.
+
 2009-04-28  Zoltan Varga  <var...@gmail.com>
 
 	* misc.c (GC_init): Avoid casting an lvalue. Fixes part of #498692.
Index: allchblk.c
===================================================================
--- allchblk.c	(revision 137556)
+++ allchblk.c	(working copy)
@@ -364,7 +364,7 @@
 /* way blocks are ever unmapped.					  */
 void GC_unmap_old(void)
 {
-    struct hblk * h;
+    struct hblk * h, * next;
     hdr * hhdr;
     word sz;
     unsigned short last_rec, threshold;
@@ -372,8 +372,9 @@
 #   define UNMAP_THRESHOLD 6
     
     for (i = 0; i <= N_HBLK_FLS; ++i) {
-      for (h = GC_hblkfreelist[i]; 0 != h; h = hhdr -> hb_next) {
+      for (h = GC_hblkfreelist[i]; 0 != h; h = next) {
         hhdr = HDR(h);
+	next = hhdr -> hb_next;
 	if (!IS_MAPPED(hhdr)) continue;
 	threshold = (unsigned short)(GC_gc_no - UNMAP_THRESHOLD);
 	last_rec = hhdr -> hb_last_reclaimed;
@@ -382,6 +383,16 @@
           sz = hhdr -> hb_sz;
 	  GC_unmap((ptr_t)h, sz);
 	  hhdr -> hb_flags |= WAS_UNMAPPED;
+
+#if !defined(MSWIN32) && !defined(MSWINCE)
+	  if (sz > REALLY_FREE_MIN) {
+	    GC_remove_from_fl(hhdr, i);
+	    GC_remove_header(h);
+
+	    /* Now really unmap the block */
+	    GC_really_unmap ((ptr_t)h, sz);
+	  }
+#endif
     	}
       }
     }  
@@ -412,6 +423,7 @@
 	      /* make both consistent, so that we can merge */
 	        if (size > nextsize) {
 		  GC_remap((ptr_t)next, nextsize);
+		  nexthdr -> hb_flags &= ~WAS_UNMAPPED;
 		} else {
 		  GC_unmap((ptr_t)h, size);
 		  hhdr -> hb_flags |= WAS_UNMAPPED;
Index: os_dep.c
===================================================================
--- os_dep.c	(revision 137556)
+++ os_dep.c	(working copy)
@@ -1966,6 +1966,23 @@
 #   endif
 }
 
+void GC_really_unmap(ptr_t start, word bytes)
+{
+    ptr_t start_addr = GC_unmap_start(start, bytes);
+    ptr_t end_addr = GC_unmap_end(start, bytes);
+    word len = end_addr - start_addr;
+    if (0 == start_addr) return;
+#   if defined(MSWIN32) || defined(MSWINCE)
+      /* No idea what to do here */
+#   else
+      {
+	int result;
+	result = munmap(start_addr, len);
+        if (result != 0) ABORT("munmap() failed");
+      }
+      GC_really_unmapped_bytes += len;
+#   endif
+}
 #endif /* USE_MUNMAP */
 
 /* Routine for pushing any additional roots.  In THREADS 	*/

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to