2009-09-23 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Wed, 23 Sep 2009 06:57:52 +0000 (06:57 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:47 +0000 (21:06 +0400)
(ivmai150.diff)

* Makefile.direct (MUNMAP_THRESHOLD, GC_FORCE_UNMAP_ON_GCOLLECT):
Add the comment for.
* alloc.c (GC_unmap_threshold, GC_force_unmap_on_gcollect):
Declare external variable (only if USE_MUNMAP).
* alloc.c (GC_try_to_collect): Temporarily set GC_unmap_threshold
value to 1 if GC_force_unmap_on_gcollect and restore it before
unlocking (only if USE_MUNMAP).
* doc/README.environment (GC_FORCE_UNMAP_ON_GCOLLECT): Add
information for.
* include/gc.h (GC_set_force_unmap_on_gcollect,
GC_get_force_unmap_on_gcollect): New public function prototype.
* include/gc.h (GC_FORCE_UNMAP_ON_GCOLLECT): New macro is
recognized.
* misc.c (GC_FORCE_UNMAP_ON_GCOLLECT): Ditto.
* include/gc.h (GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT): New
internal macro (used by GC_INIT only).
* misc.c (GC_force_unmap_on_gcollect): New global variable.
* misc.c (GC_init): Recognize new "GC_FORCE_UNMAP_ON_GCOLLECT"
environment variable (and set GC_force_unmap_on_gcollect).
* misc.c (GC_set_force_unmap_on_gcollect,
GC_get_force_unmap_on_gcollect): New public function.
* tests/test.c (window_proc): Call GC_set_force_unmap_on_gcollect
to force the mode on if WM_HIBERNATE; restore the mode after
GC_gcollect().

ChangeLog
Makefile.direct
alloc.c
doc/README.environment
include/gc.h
misc.c
tests/test.c

index 2dfe764..a7b83d1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,32 @@
 2009-09-23  Ivan Maidanski <ivmai@mail.ru>
+       (ivmai150.diff)
+
+       * Makefile.direct (MUNMAP_THRESHOLD, GC_FORCE_UNMAP_ON_GCOLLECT):
+       Add the comment for.
+       * alloc.c (GC_unmap_threshold, GC_force_unmap_on_gcollect):
+       Declare external variable (only if USE_MUNMAP).
+       * alloc.c (GC_try_to_collect): Temporarily set GC_unmap_threshold
+       value to 1 if GC_force_unmap_on_gcollect and restore it before
+       unlocking (only if USE_MUNMAP).
+       * doc/README.environment (GC_FORCE_UNMAP_ON_GCOLLECT): Add
+       information for.
+       * include/gc.h (GC_set_force_unmap_on_gcollect,
+       GC_get_force_unmap_on_gcollect): New public function prototype.
+       * include/gc.h (GC_FORCE_UNMAP_ON_GCOLLECT): New macro is
+       recognized.
+       * misc.c (GC_FORCE_UNMAP_ON_GCOLLECT): Ditto.
+       * include/gc.h (GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT): New
+       internal macro (used by GC_INIT only).
+       * misc.c (GC_force_unmap_on_gcollect): New global variable.
+       * misc.c (GC_init): Recognize new "GC_FORCE_UNMAP_ON_GCOLLECT"
+       environment variable (and set GC_force_unmap_on_gcollect).
+       * misc.c (GC_set_force_unmap_on_gcollect,
+       GC_get_force_unmap_on_gcollect): New public function.
+       * tests/test.c (window_proc): Call GC_set_force_unmap_on_gcollect
+       to force the mode on if WM_HIBERNATE; restore the mode after
+       GC_gcollect().
+
+2009-09-23  Ivan Maidanski <ivmai@mail.ru>
 
        * Makefile.direct (LARGE_CONFIG): Update information.
        * include/gc.h (GC_stop_func): Refine the comment.
index 7b49dc6..f15d265 100644 (file)
@@ -186,6 +186,13 @@ HOSTCFLAGS=$(CFLAGS)
 #   (except for Win32 with GetWriteWatch available).
 #   Works under some Unix, Linux and Windows versions.
 #   Requires -DUSE_MMAP except for Windows.
+# -DMUNMAP_THRESHOLD=<value> Set the desired memory blocks unmapping threshold
+#   (the number of sequential garbage collections for which a candidate block
+#   for unmapping should remain free).
+# -DGC_FORCE_UNMAP_ON_GCOLLECT Set "unmap as much as possible on explicit GC"
+#   mode on by default.  The mode could be changed at run-time.  Has no effect
+#   unless unmapping is turned on.  Has no effect on implicitly-initiated
+#   garbage collections.
 # -DMMAP_STACKS (for Solaris threads) Use mmap from /dev/zero rather than
 #   GC_scratch_alloc() to get stack memory.
 # -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever
diff --git a/alloc.c b/alloc.c
index 2f61d58..3b40f74 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -892,10 +892,18 @@ STATIC void GC_finish_collection(void)
 #   endif
 }
 
+#ifdef USE_MUNMAP
+    extern int GC_unmap_threshold;      /* defined in allchblk.c        */
+    extern GC_bool GC_force_unmap_on_gcollect;  /* defined in misc.c    */
+#endif
+
 /* Externally callable routine to invoke full, stop-world collection */
 GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func)
 {
     int result;
+#   ifdef USE_MUNMAP
+      int old_unmap_threshold;
+#   endif
     DCL_LOCK_STATE;
     
     if (!GC_is_initialized) GC_init();
@@ -903,11 +911,19 @@ GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func)
     if (GC_debugging_started) GC_print_all_smashed();
     GC_INVOKE_FINALIZERS();
     LOCK();
+#   ifdef USE_MUNMAP
+      old_unmap_threshold = GC_unmap_threshold;
+      if (GC_force_unmap_on_gcollect && old_unmap_threshold > 0)
+        GC_unmap_threshold = 1; /* unmap as much as possible */
+#   endif
     ENTER_GC();
     /* Minimize junk left in my registers */
       GC_noop(0,0,0,0,0,0);
     result = (int)GC_try_to_collect_inner(stop_func);
     EXIT_GC();
+#   ifdef USE_MUNMAP
+      GC_unmap_threshold = old_unmap_threshold; /* restore */
+#   endif
     UNLOCK();
     if(result) {
         if (GC_debugging_started) GC_print_all_smashed();
index ddfa60b..f59c4d4 100644 (file)
@@ -141,6 +141,12 @@ GC_UNMAP_THRESHOLD - Set the desired memory blocks unmapping threshold (the
                    a candidate block for unmapping should remain free).  The
                    special value "0" completely disables unmapping.
 
+GC_FORCE_UNMAP_ON_GCOLLECT - Turn "unmap as much as possible on explicit GC"
+                mode on (overrides the default value).  Has no effect on
+                implicitly-initiated garbage collections.  Has no effect if
+                memory unmapping is disabled (or not compiled in) or if the
+                unmapping threshold is 1.
+
 GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection.  Forces a
                collection at program termination to detect leaks that would
                otherwise occur after the last GC.
index 6ef6c65..549b9d8 100644 (file)
@@ -1306,6 +1306,13 @@ GC_API void GC_CALL GC_use_DllMain(void);
 
 #endif /* defined(GC_WIN32_THREADS)  && !cygwin */
 
+/* Public setter and getter for switching "unmap as much as possible"   */
+/* mode on(1) and off(0).  Has no effect unless unmapping is turned on. */
+/* Has no effect on implicitly-initiated garbage collections.  Initial  */
+/* value is controlled by GC_FORCE_UNMAP_ON_GCOLLECT.                   */
+GC_API void GC_CALL GC_set_force_unmap_on_gcollect(int);
+GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void);
+
  /* Fully portable code should call GC_INIT() from the main program     */
  /* before making any other GC_ calls.  On most platforms this is a     */
  /* no-op and the collector self-initializes.  But a number of          */
@@ -1346,6 +1353,14 @@ GC_API void GC_CALL GC_use_DllMain(void);
 # define GC_INIT_CONF_DONT_EXPAND /* empty */
 #endif
 
+#ifdef GC_FORCE_UNMAP_ON_GCOLLECT
+  /* Turn on "unmap as much as possible on explicit GC" mode at start-up */
+# define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT \
+                GC_set_force_unmap_on_gcollect(1)
+#else
+# define GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT /* empty */
+#endif
+
 #ifdef GC_MAX_RETRIES
   /* Set GC_max_retries to the desired value at start-up */
 # define GC_INIT_CONF_MAX_RETRIES GC_set_max_retries(GC_MAX_RETRIES)
@@ -1404,6 +1419,7 @@ GC_API void GC_CALL GC_use_DllMain(void);
 #endif
 
 #define GC_INIT() { GC_INIT_CONF_DONT_EXPAND; /* pre-init */ \
+                    GC_INIT_CONF_FORCE_UNMAP_ON_GCOLLECT; \
                     GC_INIT_CONF_MAX_RETRIES; \
                     GC_INIT_CONF_FREE_SPACE_DIVISOR; \
                     GC_INIT_CONF_FULL_FREQ; \
diff --git a/misc.c b/misc.c
index 4f8fae8..d49f424 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -112,6 +112,14 @@ GC_bool GC_print_back_height = 0;
   int GC_all_interior_pointers = 0;
 #endif
 
+#ifdef GC_FORCE_UNMAP_ON_GCOLLECT
+  /* Has no effect unless USE_MUNMAP.                           */
+  /* Has no effect on implicitly-initiated garbage collections. */
+  GC_bool GC_force_unmap_on_gcollect = TRUE;
+#else
+  GC_bool GC_force_unmap_on_gcollect = FALSE;
+#endif
+
 long GC_large_alloc_warn_interval = 5;
        /* Interval between unsuppressed warnings.      */
 
@@ -671,6 +679,17 @@ GC_API void GC_CALL GC_init(void)
          }
        }
       }
+      {
+       char * string = GETENV("GC_FORCE_UNMAP_ON_GCOLLECT");
+       if (string != NULL) {
+         if (*string == '0' && *(string + 1) == '\0') {
+           /* "0" is used to turn off the mode. */
+            GC_force_unmap_on_gcollect = FALSE;
+         } else {
+            GC_force_unmap_on_gcollect = TRUE;
+         }
+       }
+      }
 #   endif
     maybe_install_looping_handler();
     /* Adjust normal object descriptor for extra allocation.   */
@@ -1628,3 +1647,13 @@ GC_API unsigned long GC_CALL GC_get_time_limit(void)
 {
     return GC_time_limit;
 }
+
+GC_API void GC_CALL GC_set_force_unmap_on_gcollect(int value)
+{
+    GC_force_unmap_on_gcollect = (GC_bool)value;
+}
+
+GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void)
+{
+    return (int)GC_force_unmap_on_gcollect;
+}
index a14024b..4f59d32 100644 (file)
@@ -1431,10 +1431,15 @@ HWND win_handle;
 LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
   LRESULT ret = 0;
+  int old_force_unmap;
   switch (uMsg) {
     case WM_HIBERNATE:
       GC_printf("Received WM_HIBERNATE, calling GC_gcollect\n");
+      /* Force "unmap as much memory as possible" mode. */
+      old_force_unmap = GC_get_force_unmap_on_gcollect();
+      GC_set_force_unmap_on_gcollect(1);
       GC_gcollect();
+      GC_set_force_unmap_on_gcollect(old_force_unmap); /* restore mode */
       break;
     case WM_CLOSE:
       GC_printf("Received WM_CLOSE, closing window\n");