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.
# (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
# 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();
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();
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.
#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 */
# 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)
#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; \
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. */
}
}
}
+ {
+ 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. */
{
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;
+}
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");